about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/base/math.h (renamed from src/base/math.hpp)12
-rw-r--r--src/base/system.c24
-rw-r--r--src/base/system.h51
-rw-r--r--src/base/tl/algorithm.h (renamed from src/base/tl/algorithm.hpp)4
-rw-r--r--src/base/tl/allocator.h (renamed from src/base/tl/allocator.hpp)0
-rw-r--r--src/base/tl/array.h (renamed from src/base/tl/array.hpp)10
-rw-r--r--src/base/tl/base.h (renamed from src/base/tl/base.hpp)0
-rw-r--r--src/base/tl/math.hpp45
-rw-r--r--src/base/tl/matrix.hpp163
-rw-r--r--src/base/tl/quat.hpp211
-rw-r--r--src/base/tl/range.h (renamed from src/base/tl/range.hpp)2
-rw-r--r--src/base/tl/sorted_array.h (renamed from src/base/tl/sorted_array.hpp)4
-rw-r--r--src/base/tl/stream.hpp65
-rw-r--r--src/base/tl/string.h (renamed from src/base/tl/string.hpp)4
-rw-r--r--src/base/tl/vector.hpp198
-rw-r--r--src/base/vmath.h (renamed from src/base/vmath.hpp)0
-rw-r--r--src/engine/client.h159
-rw-r--r--src/engine/client/client.cpp2062
-rw-r--r--src/engine/client/client.h286
-rw-r--r--src/engine/client/ec_client.cpp2087
-rw-r--r--src/engine/client/ec_gfx.cpp992
-rw-r--r--src/engine/client/ec_gfx_text.cpp669
-rw-r--r--src/engine/client/ec_inp.cpp234
-rw-r--r--src/engine/client/ec_snd.cpp471
-rw-r--r--src/engine/client/ec_srvbrowse.cpp736
-rw-r--r--src/engine/client/editor.h10
-rw-r--r--src/engine/client/graphics.cpp938
-rw-r--r--src/engine/client/graphics.h180
-rw-r--r--src/engine/client/input.cpp208
-rw-r--r--src/engine/client/input.h37
-rw-r--r--src/engine/client/keynames.h (renamed from src/engine/e_keynames.cpp)10
-rw-r--r--src/engine/client/sound.cpp485
-rw-r--r--src/engine/client/sound.h39
-rw-r--r--src/engine/client/srvbrowse.cpp721
-rw-r--r--src/engine/client/srvbrowse.h111
-rw-r--r--src/engine/client/text.cpp718
-rw-r--r--src/engine/config.h23
-rw-r--r--src/engine/console.h58
-rw-r--r--src/engine/demo.h29
-rw-r--r--src/engine/e_client_interface.h16
-rw-r--r--src/engine/e_common_interface.h8
-rw-r--r--src/engine/e_compression.cpp86
-rw-r--r--src/engine/e_compression.h7
-rw-r--r--src/engine/e_config.cpp49
-rw-r--r--src/engine/e_config.h44
-rw-r--r--src/engine/e_config_variables.h77
-rw-r--r--src/engine/e_console.cpp464
-rw-r--r--src/engine/e_console.h48
-rw-r--r--src/engine/e_datafile.cpp677
-rw-r--r--src/engine/e_datafile.h29
-rw-r--r--src/engine/e_demorec.cpp640
-rw-r--r--src/engine/e_demorec.h69
-rw-r--r--src/engine/e_engine.cpp596
-rw-r--r--src/engine/e_engine.h51
-rw-r--r--src/engine/e_huffman.cpp276
-rw-r--r--src/engine/e_huffman.h83
-rw-r--r--src/engine/e_if_client.h579
-rw-r--r--src/engine/e_if_gfx.h674
-rw-r--r--src/engine/e_if_inp.h244
-rw-r--r--src/engine/e_if_modc.h145
-rw-r--r--src/engine/e_if_mods.h168
-rw-r--r--src/engine/e_if_msg.h151
-rw-r--r--src/engine/e_if_other.h385
-rw-r--r--src/engine/e_if_server.h140
-rw-r--r--src/engine/e_if_snd.h91
-rw-r--r--src/engine/e_jobs.cpp76
-rw-r--r--src/engine/e_jobs.h33
-rw-r--r--src/engine/e_linereader.cpp62
-rw-r--r--src/engine/e_linereader.h14
-rw-r--r--src/engine/e_map.cpp66
-rw-r--r--src/engine/e_memheap.cpp102
-rw-r--r--src/engine/e_memheap.h6
-rw-r--r--src/engine/e_msg.cpp70
-rw-r--r--src/engine/e_protocol.h73
-rw-r--r--src/engine/e_server_interface.h12
-rw-r--r--src/engine/e_snapshot.cpp571
-rw-r--r--src/engine/editor.h16
-rw-r--r--src/engine/graphics.h151
-rw-r--r--src/engine/input.h89
-rw-r--r--src/engine/kernel.h66
-rw-r--r--src/engine/keys.h (renamed from src/engine/e_keys.h)0
-rw-r--r--src/engine/map.h32
-rw-r--r--src/engine/masterserver.h40
-rw-r--r--src/engine/message.h14
-rw-r--r--src/engine/server.h81
-rw-r--r--src/engine/server/es_register.cpp271
-rw-r--r--src/engine/server/es_server.cpp1969
-rw-r--r--src/engine/server/register.cpp264
-rw-r--r--src/engine/server/register.h48
-rw-r--r--src/engine/server/server.cpp1400
-rw-r--r--src/engine/server/server.h195
-rw-r--r--src/engine/serverbrowser.h93
-rw-r--r--src/engine/shared/compression.cpp88
-rw-r--r--src/engine/shared/compression.h12
-rw-r--r--src/engine/shared/config.cpp111
-rw-r--r--src/engine/shared/config.h22
-rw-r--r--src/engine/shared/config_variables.h80
-rw-r--r--src/engine/shared/console.cpp489
-rw-r--r--src/engine/shared/console.h96
-rw-r--r--src/engine/shared/datafile.cpp643
-rw-r--r--src/engine/shared/datafile.h77
-rw-r--r--src/engine/shared/demorec.cpp623
-rw-r--r--src/engine/shared/demorec.h117
-rw-r--r--src/engine/shared/engine.cpp76
-rw-r--r--src/engine/shared/engine.h23
-rw-r--r--src/engine/shared/huffman.cpp276
-rw-r--r--src/engine/shared/huffman.h89
-rw-r--r--src/engine/shared/jobs.cpp74
-rw-r--r--src/engine/shared/jobs.h51
-rw-r--r--src/engine/shared/kernel.cpp93
-rw-r--r--src/engine/shared/linereader.cpp62
-rw-r--r--src/engine/shared/linereader.h17
-rw-r--r--src/engine/shared/map.cpp45
-rw-r--r--src/engine/shared/masterserver.cpp187
-rw-r--r--src/engine/shared/memheap.cpp96
-rw-r--r--src/engine/shared/memheap.h32
-rw-r--r--src/engine/shared/message.h9
-rw-r--r--src/engine/shared/network.cpp (renamed from src/engine/e_network.cpp)96
-rw-r--r--src/engine/shared/network.h (renamed from src/engine/e_network.h)43
-rw-r--r--src/engine/shared/network_client.cpp (renamed from src/engine/e_network_client.cpp)12
-rw-r--r--src/engine/shared/network_conn.cpp (renamed from src/engine/e_network_conn.cpp)131
-rw-r--r--src/engine/shared/network_server.cpp (renamed from src/engine/e_network_server.cpp)121
-rw-r--r--src/engine/shared/packer.cpp (renamed from src/engine/e_packer.cpp)36
-rw-r--r--src/engine/shared/packer.h (renamed from src/engine/e_packer.h)11
-rw-r--r--src/engine/shared/protocol.h91
-rw-r--r--src/engine/shared/ringbuffer.cpp (renamed from src/engine/e_ringbuffer.cpp)40
-rw-r--r--src/engine/shared/ringbuffer.h (renamed from src/engine/e_ringbuffer.h)6
-rw-r--r--src/engine/shared/snapshot.cpp537
-rw-r--r--src/engine/shared/snapshot.h (renamed from src/engine/e_snapshot.h)78
-rw-r--r--src/engine/shared/storage.cpp196
-rw-r--r--src/engine/sound.h40
-rw-r--r--src/engine/storage.h25
-rw-r--r--src/engine/textrender.h60
-rw-r--r--src/game/client/animstate.cpp103
-rw-r--r--src/game/client/animstate.h22
-rw-r--r--src/game/client/animstate.hpp24
-rw-r--r--src/game/client/clienthooks.cpp27
-rw-r--r--src/game/client/component.h43
-rw-r--r--src/game/client/component.hpp35
-rw-r--r--src/game/client/components/binds.cpp220
-rw-r--r--src/game/client/components/binds.h41
-rw-r--r--src/game/client/components/binds.hpp35
-rw-r--r--src/game/client/components/broadcast.cpp36
-rw-r--r--src/game/client/components/broadcast.h17
-rw-r--r--src/game/client/components/broadcast.hpp14
-rw-r--r--src/game/client/components/camera.cpp41
-rw-r--r--src/game/client/components/camera.h16
-rw-r--r--src/game/client/components/camera.hpp13
-rw-r--r--src/game/client/components/chat.cpp290
-rw-r--r--src/game/client/components/chat.h60
-rw-r--r--src/game/client/components/chat.hpp54
-rw-r--r--src/game/client/components/console.cpp606
-rw-r--r--src/game/client/components/console.h72
-rw-r--r--src/game/client/components/console.hpp68
-rw-r--r--src/game/client/components/controls.cpp251
-rw-r--r--src/game/client/components/controls.h25
-rw-r--r--src/game/client/components/controls.hpp22
-rw-r--r--src/game/client/components/damageind.cpp69
-rw-r--r--src/game/client/components/damageind.h34
-rw-r--r--src/game/client/components/damageind.hpp31
-rw-r--r--src/game/client/components/debughud.cpp105
-rw-r--r--src/game/client/components/debughud.h13
-rw-r--r--src/game/client/components/debughud.hpp10
-rw-r--r--src/game/client/components/effects.cpp340
-rw-r--r--src/game/client/components/effects.h27
-rw-r--r--src/game/client/components/effects.hpp24
-rw-r--r--src/game/client/components/emoticon.cpp178
-rw-r--r--src/game/client/components/emoticon.h31
-rw-r--r--src/game/client/components/emoticon.hpp28
-rw-r--r--src/game/client/components/flow.cpp99
-rw-r--r--src/game/client/components/flow.h28
-rw-r--r--src/game/client/components/flow.hpp25
-rw-r--r--src/game/client/components/hud.cpp330
-rw-r--r--src/game/client/components/hud.h27
-rw-r--r--src/game/client/components/hud.hpp24
-rw-r--r--src/game/client/components/items.cpp267
-rw-r--r--src/game/client/components/items.h16
-rw-r--r--src/game/client/components/items.hpp13
-rw-r--r--src/game/client/components/killmessages.cpp120
-rw-r--r--src/game/client/components/killmessages.h31
-rw-r--r--src/game/client/components/killmessages.hpp24
-rw-r--r--src/game/client/components/mapimages.cpp51
-rw-r--r--src/game/client/components/mapimages.h18
-rw-r--r--src/game/client/components/mapimages.hpp15
-rw-r--r--src/game/client/components/maplayers.cpp187
-rw-r--r--src/game/client/components/maplayers.h24
-rw-r--r--src/game/client/components/maplayers.hpp19
-rw-r--r--src/game/client/components/menus.cpp1052
-rw-r--r--src/game/client/components/menus.h223
-rw-r--r--src/game/client/components/menus.hpp216
-rw-r--r--src/game/client/components/menus_browser.cpp920
-rw-r--r--src/game/client/components/menus_demo.cpp545
-rw-r--r--src/game/client/components/menus_ingame.cpp394
-rw-r--r--src/game/client/components/menus_settings.cpp1205
-rw-r--r--src/game/client/components/motd.cpp78
-rw-r--r--src/game/client/components/motd.h21
-rw-r--r--src/game/client/components/motd.hpp18
-rw-r--r--src/game/client/components/nameplates.cpp71
-rw-r--r--src/game/client/components/nameplates.h17
-rw-r--r--src/game/client/components/nameplates.hpp14
-rw-r--r--src/game/client/components/particles.cpp161
-rw-r--r--src/game/client/components/particles.h94
-rw-r--r--src/game/client/components/particles.hpp91
-rw-r--r--src/game/client/components/players.cpp647
-rw-r--r--src/game/client/components/players.h25
-rw-r--r--src/game/client/components/players.hpp16
-rw-r--r--src/game/client/components/scoreboard.cpp311
-rw-r--r--src/game/client/components/scoreboard.h22
-rw-r--r--src/game/client/components/scoreboard.hpp19
-rw-r--r--src/game/client/components/skins.cpp169
-rw-r--r--src/game/client/components/skins.h39
-rw-r--r--src/game/client/components/skins.hpp36
-rw-r--r--src/game/client/components/sounds.cpp93
-rw-r--r--src/game/client/components/sounds.h36
-rw-r--r--src/game/client/components/sounds.hpp22
-rw-r--r--src/game/client/components/voting.cpp257
-rw-r--r--src/game/client/components/voting.h58
-rw-r--r--src/game/client/components/voting.hpp52
-rw-r--r--src/game/client/gameclient.cpp1159
-rw-r--r--src/game/client/gameclient.h208
-rw-r--r--src/game/client/gameclient.hpp181
-rw-r--r--src/game/client/lineinput.cpp107
-rw-r--r--src/game/client/lineinput.h31
-rw-r--r--src/game/client/lineinput.hpp29
-rw-r--r--src/game/client/render.cpp313
-rw-r--r--src/game/client/render.h79
-rw-r--r--src/game/client/render.hpp81
-rw-r--r--src/game/client/render_map.cpp273
-rw-r--r--src/game/client/ui.cpp206
-rw-r--r--src/game/client/ui.h (renamed from src/game/client/ui.hpp)21
-rw-r--r--src/game/collision.cpp223
-rw-r--r--src/game/collision.h37
-rw-r--r--src/game/collision.hpp21
-rwxr-xr-xsrc/game/editor/array.hpp238
-rw-r--r--src/game/editor/ed_editor.cpp3505
-rw-r--r--src/game/editor/ed_editor.h615
-rw-r--r--src/game/editor/ed_editor.hpp589
-rw-r--r--src/game/editor/ed_io.cpp488
-rw-r--r--src/game/editor/ed_layer_game.cpp18
-rw-r--r--src/game/editor/ed_layer_quads.cpp245
-rw-r--r--src/game/editor/ed_layer_tiles.cpp354
-rw-r--r--src/game/editor/ed_popups.cpp426
-rw-r--r--src/game/gamecore.cpp526
-rw-r--r--src/game/gamecore.h205
-rw-r--r--src/game/gamecore.hpp200
-rw-r--r--src/game/layers.cpp78
-rw-r--r--src/game/layers.h28
-rw-r--r--src/game/layers.hpp12
-rw-r--r--src/game/localization.cpp99
-rw-r--r--src/game/localization.h57
-rw-r--r--src/game/localization.hpp54
-rw-r--r--src/game/mapitems.h179
-rw-r--r--src/game/mapitems.hpp178
-rw-r--r--src/game/server/entities/character.cpp964
-rw-r--r--src/game/server/entities/character.h133
-rw-r--r--src/game/server/entities/character.hpp134
-rw-r--r--src/game/server/entities/laser.cpp130
-rw-r--r--src/game/server/entities/laser.h28
-rw-r--r--src/game/server/entities/laser.hpp31
-rw-r--r--src/game/server/entities/pickup.cpp180
-rw-r--r--src/game/server/entities/pickup.h23
-rw-r--r--src/game/server/entities/pickup.hpp24
-rw-r--r--src/game/server/entities/projectile.cpp145
-rw-r--r--src/game/server/entities/projectile.h30
-rw-r--r--src/game/server/entities/projectile.hpp37
-rw-r--r--src/game/server/entity.cpp49
-rw-r--r--src/game/server/entity.h (renamed from src/game/server/entity.hpp)92
-rw-r--r--src/game/server/eventhandler.cpp54
-rw-r--r--src/game/server/eventhandler.h30
-rw-r--r--src/game/server/eventhandler.hpp25
-rw-r--r--src/game/server/gamecontext.cpp1036
-rw-r--r--src/game/server/gamecontext.h168
-rw-r--r--src/game/server/gamecontext.hpp105
-rw-r--r--src/game/server/gamecontroller.cpp641
-rw-r--r--src/game/server/gamecontroller.h145
-rw-r--r--src/game/server/gamecontroller.hpp136
-rw-r--r--src/game/server/gamemodes/ctf.cpp252
-rw-r--r--src/game/server/gamemodes/ctf.h38
-rw-r--r--src/game/server/gamemodes/ctf.hpp36
-rw-r--r--src/game/server/gamemodes/dm.cpp15
-rw-r--r--src/game/server/gamemodes/dm.h11
-rw-r--r--src/game/server/gamemodes/dm.hpp10
-rw-r--r--src/game/server/gamemodes/mod.cpp19
-rw-r--r--src/game/server/gamemodes/mod.h14
-rw-r--r--src/game/server/gamemodes/mod.hpp13
-rw-r--r--src/game/server/gamemodes/tdm.cpp33
-rw-r--r--src/game/server/gamemodes/tdm.h13
-rw-r--r--src/game/server/gamemodes/tdm.hpp12
-rw-r--r--src/game/server/gameworld.cpp233
-rw-r--r--src/game/server/gameworld.h (renamed from src/game/server/gameworld.hpp)68
-rw-r--r--src/game/server/hooks.cpp599
-rw-r--r--src/game/server/player.cpp220
-rw-r--r--src/game/server/player.h89
-rw-r--r--src/game/server/player.hpp75
-rw-r--r--src/game/tuning.h46
-rw-r--r--src/game/tuning.hpp41
-rw-r--r--src/game/variables.h79
-rw-r--r--src/game/variables.hpp75
-rw-r--r--src/game/version.h8
-rw-r--r--src/game/version.hpp4
-rw-r--r--src/mastersrv/mastersrv.cpp377
-rw-r--r--src/mastersrv/mastersrv.h8
-rw-r--r--src/osxlaunch/client.h3
-rw-r--r--src/tools/crapnet.cpp204
-rw-r--r--src/tools/dilate.c2
-rw-r--r--src/tools/fake_server.c232
-rw-r--r--src/tools/fake_server.cpp211
-rw-r--r--src/tools/map_resave.c36
-rw-r--r--src/tools/map_resave.cpp44
-rw-r--r--src/tools/tileset_borderfix.c2
-rw-r--r--src/versionsrv/versionsrv.cpp53
-rw-r--r--src/versionsrv/versionsrv.h4
312 files changed, 28481 insertions, 30044 deletions
diff --git a/src/base/math.hpp b/src/base/math.h
index 302935d7..f3ba2ea8 100644
--- a/src/base/math.hpp
+++ b/src/base/math.h
@@ -49,20 +49,10 @@ public:
 	operator float() const { return value/(float)(1<<10); }
 };
 
-class tune_param
-{
-	int value;
-public:
-	void set(int v) { value = v; }
-	int get() const { return value; }
-	tune_param &operator = (int v) { value = (int)(v*100.0f); return *this; }
-	tune_param &operator = (float v) { value = (int)(v*100.0f); return *this; }
-	operator float() const { return value/100.0f; }
-};
-
 const float pi = 3.1415926535897932384626433f;
 
 template <typename T> inline T min(T a, T b) { return a<b?a:b; }
 template <typename T> inline T max(T a, T b) { return a>b?a:b; }
+template <typename T> inline T absolute(T a) { return a<T(0)?-a:a; }
 
 #endif // BASE_MATH_H
diff --git a/src/base/system.c b/src/base/system.c
index f570fdf3..47893aa3 100644
--- a/src/base/system.c
+++ b/src/base/system.c
@@ -42,7 +42,9 @@
 	#include <direct.h>
 	#include <errno.h>
 
-	#define EWOULDBLOCK WSAEWOULDBLOCK
+	#ifndef EWOULDBLOCK
+		#define EWOULDBLOCK WSAEWOULDBLOCK
+	#endif
 #else
 	#error NOT IMPLEMENTED
 #endif
@@ -86,11 +88,11 @@ void dbg_msg(const char *sys, const char *fmt, ...)
 	char str[1024*4];
 	char *msg;
 	int i, len;
-	
+
 	str_format(str, sizeof(str), "[%08x][%s]: ", (int)time(0), sys);
 	len = strlen(str);
 	msg = (char *)str + len;
-	
+
 	va_start(args, fmt);
 #if defined(CONF_FAMILY_WINDOWS)
 	_vsnprintf(msg, sizeof(str)-len, fmt, args);
@@ -98,7 +100,7 @@ void dbg_msg(const char *sys, const char *fmt, ...)
 	vsnprintf(msg, sizeof(str)-len, fmt, args);
 #endif
 	va_end(args);
-	
+
 	for(i = 0; i < num_loggers; i++)
 		loggers[i](str);
 }
@@ -118,7 +120,7 @@ static void logger_debugger(const char *line)
 }
 
 
-IOHANDLE logfile = 0;
+static IOHANDLE logfile = 0;
 static void logger_file(const char *line)
 {
 	io_write(logfile, line, strlen(line));
@@ -137,7 +139,6 @@ void dbg_logger_file(const char *filename)
 		dbg_msg("dbg/logger", "failed to open '%s' for logging", filename);
 
 }
-
 /* */
 
 int memory_alloced = 0;
@@ -674,7 +675,7 @@ int net_udp_send(NETSOCKET sock, const NETADDR *addr, const void *data, int size
 	mem_zero(&sa, sizeof(sa));
 	netaddr_to_sockaddr(addr, &sa);
 	d = sendto((int)sock, (const char*)data, size, 0, &sa, sizeof(sa));
-	if(d < 0)
+	/*if(d < 0)
 	{
 		char addrstr[256];
 		net_addr_str(addr, addrstr, sizeof(addrstr));
@@ -684,7 +685,7 @@ int net_udp_send(NETSOCKET sock, const NETADDR *addr, const void *data, int size
 		dbg_msg("net", "\tsize = %d %x", size, size);
 		dbg_msg("net", "\taddr = %s", addrstr);
 
-	}
+	}*/
 	network_stats.sent_bytes += size;
 	network_stats.sent_packets++;
 	return d;
@@ -1102,6 +1103,10 @@ int str_comp(const char *a, const char *b)
 	return strcmp(a, b);
 }
 
+int str_comp_num(const char *a, const char *b, const int num)
+{
+	return strncmp(a, b, num);
+}
 
 const char *str_find_nocase(const char *haystack, const char *needle)
 {
@@ -1220,6 +1225,9 @@ char str_uppercase(char c)
 	return c;
 }
 
+int str_toint(const char *str) { return atoi(str); }
+float str_tofloat(const char *str) { return atof(str); }
+
 
 
 static int str_utf8_isstart(char c)
diff --git a/src/base/system.h b/src/base/system.h
index 3c9974d8..0850a08b 100644
--- a/src/base/system.h
+++ b/src/base/system.h
@@ -46,14 +46,15 @@ void dbg_break();
 
 /*
 	Function: dbg_msg
-		Prints a debug message.
+	
+	Prints a debug message.
 	
 	Parameters:
 		sys - A string that describes what system the message belongs to
 		fmt - A printf styled format string.
 	
 	Remarks:
-		Does nothing in relase version of the library.
+		Does nothing in release version of the library.
 		
 	See Also:
 		<dbg_assert>
@@ -351,7 +352,7 @@ void *thread_create(void (*threadfunc)(void *), void *user);
 void thread_wait(void *thread);
 
 /*
-	Function: thread_destoy
+	Function: thread_destroy
 		Destroys a thread.
 	
 	Parameters:
@@ -782,6 +783,25 @@ int str_comp_nocase(const char *a, const char *b);
 int str_comp(const char *a, const char *b);
 
 /*
+	Function: str_comp_nocase
+		Compares up to num characters of two strings case sensitive.
+	
+	Parameters:
+		a - String to compare.
+		b - String to compare.
+		num - Maximum characters to compare
+	
+	Returns:	
+		<0 - String a is lesser then string b
+		0 - String a is equal to string b
+		>0 - String a is greater then string b
+
+	Remarks:
+		- The strings are treated as zero-termineted strings.
+*/
+int str_comp_num(const char *a, const char *b, const int num);
+
+/*
 	Function: str_find_nocase
 		Finds a string inside another string case insensitive.
 
@@ -942,8 +962,29 @@ void mem_debug_dump();
 
 void swap_endian(void *data, unsigned elem_size, unsigned num);
 
-typedef void (*DBG_LOGGER)(const char *line);
+/* Group: Debug levels */
+//by format
+enum {
+	DBG_FMT_RAW				= 1,	//raw output
+	DBG_FMT_TIME			= 2,	//show time
+	DBG_FMT_SYS				= 3,	//show sys
+	DBG_FMT_FULL			= 4		//show both
+};
+
+enum {
+	DBG_LEVEL_IMPORTANT			= 0,	//important always showed messages
+	DBG_LEVEL_ERROR				= 1,	//error messages
+	DBG_LEVEL_WARNING			= 2,	//warning messages
+	DBG_LEVEL_MSG				= 3,	//extra debug messages
+	DBG_LEVEL_INFO				= 4		//info messages
+};
+
+#define DBG_LEVEL_LOW DBG_LEVEL_IMPORTANT
+#define DBG_LEVEL_HIGH DBG_LEVEL_INFO
+
+typedef void (*DBG_LOGGER)(const char *line); 
 void dbg_logger(DBG_LOGGER logger);
+
 void dbg_logger_stdout();
 void dbg_logger_debugger();
 void dbg_logger_file(const char *filename);
@@ -968,6 +1009,8 @@ typedef struct
 
 void net_stats(NETSTATS *stats);
 
+int str_toint(const char *str);
+float str_tofloat(const char *str);
 int str_isspace(char c);
 char str_uppercase(char c);
 unsigned str_quickhash(const char *str);
diff --git a/src/base/tl/algorithm.hpp b/src/base/tl/algorithm.h
index 9d78810b..32c2da73 100644
--- a/src/base/tl/algorithm.hpp
+++ b/src/base/tl/algorithm.h
@@ -1,7 +1,7 @@
 #ifndef TL_FILE_ALGORITHM_HPP
 #define TL_FILE_ALGORITHM_HPP
 
-#include "range.hpp"
+#include "range.h"
 
 
 /*
@@ -59,7 +59,7 @@ R find_linear(R range, T value)
 	concept_empty::check(range);
 	concept_forwarditeration::check(range);
 	for(; !range.empty(); range.pop_front())
-		if(value < range.front())
+		if(value == range.front())
 			break;
 	return range;
 }
diff --git a/src/base/tl/allocator.hpp b/src/base/tl/allocator.h
index 3baa1c19..3baa1c19 100644
--- a/src/base/tl/allocator.hpp
+++ b/src/base/tl/allocator.h
diff --git a/src/base/tl/array.hpp b/src/base/tl/array.h
index 7b8698d4..580f4682 100644
--- a/src/base/tl/array.hpp
+++ b/src/base/tl/array.h
@@ -1,8 +1,8 @@
 #ifndef TL_FILE_ARRAY_HPP
 #define TL_FILE_ARRAY_HPP
 
-#include "range.hpp"
-#include "allocator.hpp"
+#include "range.h"
+#include "allocator.h"
 
 
 /*
@@ -165,7 +165,7 @@ public:
 	int add(const T& item)
 	{
 		incsize();
-		num_elements = size()+1;
+		set_size(size()+1);
 		list[num_elements-1] = item;
 		return num_elements-1;
 	}
@@ -189,7 +189,7 @@ public:
 			
 		int index = (int)(&r.front()-list);
 		incsize();
-		num_elements = size()+1;
+		set_size(size()+1);
 		
 		for(int i = num_elements-1; i > index; i--)
 			list[i] = list[i-1];
@@ -283,7 +283,7 @@ public:
 	*/
 	int memusage()
 	{
-		return sizeof(*this) + sizeof(T)*list_size;
+		return sizeof(array) + sizeof(T)*size;
 	}
 
 	/*
diff --git a/src/base/tl/base.hpp b/src/base/tl/base.h
index c202de79..c202de79 100644
--- a/src/base/tl/base.hpp
+++ b/src/base/tl/base.h
diff --git a/src/base/tl/math.hpp b/src/base/tl/math.hpp
deleted file mode 100644
index b323dea8..00000000
--- a/src/base/tl/math.hpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef BASE_MATH_H
-#define BASE_MATH_H
-
-#include <stdlib.h>
-
-template <typename T>
-inline T clamp(T val, T min, T max)
-{
-	if(val < min)
-		return min;
-	if(val > max)
-		return max;
-	return val;
-}
-
-inline float sign(float f)
-{
-	return f<0.0f?-1.0f:1.0f;
-}
-
-inline int round(float f)
-{
-	if(f > 0)
-		return (int)(f+0.5f);
-	return (int)(f-0.5f);
-}
-
-template<typename T, typename TB>
-inline T mix(const T a, const T b, TB amount)
-{
-	return a + (b-a)*amount;
-}
-
-inline float frandom() { return rand()/(float)(RAND_MAX); }
-
-const float pi = 3.1415926535897932384626433f;
-
-template <typename T> inline T min(T a, T b) { return a<b?a:b; }
-template <typename T> inline T max(T a, T b) { return a>b?a:b; }
-
-template <typename T> inline T min(T a, T b, T c) { return min(min(a,b),c); }
-template <typename T> inline T max(T a, T b, T c) { return max(max(a,b),c); }
-
-#endif // BASE_MATH_H
diff --git a/src/base/tl/matrix.hpp b/src/base/tl/matrix.hpp
deleted file mode 100644
index b723eaa7..00000000
--- a/src/base/tl/matrix.hpp
+++ /dev/null
@@ -1,163 +0,0 @@
-#ifndef TL_FILE_MATRIX_HPP
-#define TL_FILE_MATRIX_HPP
-
-/*
- 
- Looks like OpenGL 
- 
- Column Major
-
-        / m[0][0]  m[1][0]  m[2][0]  m[3][0] \     / v[0] \
-        |                                    |     |      |
-		| m[0][1]  m[1][1]  m[2][1]  m[3][1] |     | v[1] |
-        |                                    |     |      |
- M(v) = | m[0][2]  m[1][2]  m[2][2]  m[3][2] |  X  | v[2] |
-        |                                    |     |      |
-        \ m[0][3]  m[1][3]  m[2][3]  m[3][3] /     \ v[3] /
- 
- v[0] = x
- v[1] = y
- v[2] = z
- v[3] = w or 1
- 
-   +y
-   |
-   |
-   |_____ +x
-   /
-  /
- +z
- 
- right = +x
- up = +y
- forward = -z
-
-*/
-
-template<class T>
-class matrix4_base
-{
-public:
-	// [col][row]
-	T m[4][4];
-
-	//
-	inline matrix4_base()
-	{}
-
-	inline vector3_base<T> get_column3(const int i) const { return vector3_base<T>(m[i][0], m[i][1], m[i][2]); }
-	inline vector3_base<T> get_column4(const int i) const { return vector4_base<T>(m[i][0], m[i][1], m[i][2], m[i][3]); }
-	inline vector3_base<T> get_row3(const int i) const { return vector3_base<T>(m[0][i], m[1][i], m[2][i]); }
-	inline vector4_base<T> get_row4(const int i) const { return vector4_base<T>(m[0][i], m[1][i], m[2][i], m[3][i]); }
-
-	inline vector3_base<T> get_right() const { return get_row3(0); }
-	inline vector3_base<T> get_up() const { return get_row3(1); }
-	inline vector3_base<T> get_forward() const { return -get_row3(2); }
-	inline vector3_base<T> get_translation() const { return get_column3(3); }
-
-	//
-	void unit()
-	{
-		m[0][1] = m[0][2] = m[0][3] = 0;
-		m[1][0] = m[1][2] = m[1][3] = 0;
-		m[2][0] = m[2][1] = m[2][3] = 0;
-		m[3][0] = m[3][1] = m[3][2] = 0;
-
-		m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1;
-	}
-
-	//
-	vector3_base<T> operator *(const vector3_base<T> &v) const
-	{
-		vector3_base<T> r(0,0,0);
-
-		r.x += v.x*m[0][0] + v.y*m[1][0] + v.z*m[2][0] + m[3][0];
-		r.y += v.x*m[0][1] + v.y*m[1][1] + v.z*m[2][1] + m[3][1];
-		r.z += v.x*m[0][2] + v.y*m[1][2] + v.z*m[2][2] + m[3][2];
-		return r;
-	}
-
-	//
-	vector4_base<T> operator *(const vector4_base<T> &v) const
-	{
-		vector4_base<T> r(0,0,0,0);
-
-		r.x += v.x*m[0][0] + v.y*m[1][0] + v.z*m[2][0] + v.w*m[3][0];
-		r.y += v.x*m[0][1] + v.y*m[1][1] + v.z*m[2][1] + v.w*m[3][1];
-		r.z += v.x*m[0][2] + v.y*m[1][2] + v.z*m[2][2] + v.w*m[3][2];
-		r.w += v.x*m[0][3] + v.y*m[1][3] + v.z*m[2][3] + v.w*m[3][3];
-		return r;
-	}
-	//
-	matrix4_base operator *(const matrix4_base &other) const
-	{
-		matrix4_base r;
-
-		for(int i = 0; i < 4; i++)
-			for(int j = 0; j < 4; j++)
-			{
-				r.m[i][j] = 0;
-				for(int a = 0; a < 4; a++)
-					r.m[i][j] += m[a][j] * other.m[i][a];
-			}
-		return r;
-	}
-	
-	
-	//
-	// THIS PART IS KINDA UGLY BECAUSE MAT4 IS NOT IMMUTABLE
-	//
-	
-	inline void set_row(const vector3_base<T>& v, const int row)
-	{
-		m[0][row] = v.x;
-		m[1][row] = v.y;
-		m[2][row] = v.z;
-	}
-
-	inline void set_column(const vector3_base<T>& v, const int col)
-	{
-		m[col][0] = v.x;
-		m[col][1] = v.y;
-		m[col][2] = v.z;
-	}
-
-	inline void set_translation(const vector3_base<T>& v) { set_column(v,3); }	
-
-	//
-	void rot_x(T angle)
-	{
-		T sina = (T)sin(angle);
-		T cosa = (T)cos(angle);
-
-		unit();
-		m[1][1] = cosa; m[2][1] =-sina;
-		m[1][2] = sina; m[2][2] = cosa;
-	}
-
-	//
-	void rot_y(T angle)
-	{
-		T sina = (T)sin(-angle);
-		T cosa = (T)cos(-angle);
-
-		unit();
-		m[0][0] = cosa; m[2][0] =-sina;
-		m[0][2] = sina; m[2][2] = cosa;
-	}
-
-	//
-	void rot_z(T angle)
-	{
-		T sina = (T)sin(angle);
-		T cosa = (T)cos(angle);
-
-		unit();
-		m[0][0] = cosa; m[1][0] =-sina;
-		m[0][1] = sina; m[1][1] = cosa;
-	}
-};
-
-typedef matrix4_base<float> mat4;
-
-#endif
diff --git a/src/base/tl/quat.hpp b/src/base/tl/quat.hpp
deleted file mode 100644
index 2f381e11..00000000
--- a/src/base/tl/quat.hpp
+++ /dev/null
@@ -1,211 +0,0 @@
-
-
-template<class T>
-class quaternion_base
-{
-public:
-	T k[4];
-
-	/*void Unit()
-	{
-		k[0] = 0;
-		k[1] = 0;
-		k[2] = 0;
-		k[3] = 1;
-	}*/
-	
-	inline quaternion_base(){}
-
-	inline quaternion_base(T x, T y, T z, T w)
-	{
-		k[0] = x;
-		k[1] = y;
-		k[2] = z;
-		k[3] = w;
-	}
-	
-	inline quaternion_base(vector3_base<T> axis, T angle)
-	{
-		T sin_angle = sin(angle * (T)0.5);
-		T cos_angle = cos(angle * (T)0.5);
-		k[0] = axis.x * sin_angle;
-		k[1] = axis.y * sin_angle;
-		k[2] = axis.z * sin_angle;
-		k[3] = cos_angle;
-	}
-	
-
-	T magnitude()
-	{
-		return sqrt(k[0] * k[0] + k[1] * k[1] + k[2] * k[2] + k[3] * k[3]);
-	}
-
-	matrix4_base<T> create_matrix() const
-	{
-		matrix4_base<T> mat;
-		
-		T xx = k[0] * k[0];
-		T xy = k[0] * k[1];
-		T xz = k[0] * k[2];
-		T xw = k[0] * k[3];
-		T yy = k[1] * k[1];
-		T yz = k[1] * k[2];
-		T yw = k[1] * k[3];
-		T zz = k[2] * k[2];
-		T zw = k[2] * k[3];
-		
-		mat.k[0][0] = 1 - 2 * (yy + zz);
-		mat.k[0][1] = 2 * (xy + zw);
-		mat.k[0][2] = 2 * (xz - yw);
-		mat.k[0][3] = 0;
-		
-		mat.k[1][0] = 2 * (xy - zw);
-		mat.k[1][1] = 1 - 2 * (xx + zz);
-		mat.k[1][2] = 2 * (yz + xw);
-		mat.k[1][3] = 0;
-
-		mat.k[2][0] = 2 * (xz + yw);
-		mat.k[2][1] = 2 * (yz - xw);
-		mat.k[2][2] = 1 - 2 * (xx + yy);
-		mat.k[2][3] = 0;
-
-		mat.k[3][0] = 0;
-		mat.k[3][1] = 0;
-		mat.k[3][2] = 0;
-		mat.k[3][3] = 1;
-	}
-
-	/*
-	void CreateDOOM(T x, T y, T z)
-	{
-		k[0] = x;
-		k[1] = y;
-		k[2] = z;
-		T Term = 1 - (x * x) - (y * y) - (z * z);
-		if (Term < 0)
-			k[3] = 0;
-		else
-			k[3] = -sqrt(Term);
-
-		Normalize();
-	}
-	
-	T DotProd(const TQuaternion<T>& Quat) const
-	{
-		return (k[0] * Quat.k[0] + k[1] * Quat.k[1] + k[2] * Quat.k[2] + k[3] * Quat.k[3]);
-	}
-
-	void Interpolate(const TQuaternion<T>& Quat, TQuaternion& Dest, T Scale)
-	{
-		T Separation = k[0] * Quat.k[0] + k[1] * Quat.k[1] + k[2] * Quat.k[2] + k[3] * Quat.k[3];
-		T Factor1,Factor2;
-
-		if (Separation > 1)
-			Separation = 1;
-		if (Separation < -1)
-			Separation = -1;
-		Separation = acos(Separation);
-		if (Separation == 0 || Separation == pi)
-		{
-			Factor1 = 1;
-			Factor2 = 0;
-		}
-		else
-		{
-			Factor1 = sin((1 - Scale)*Separation) / sin(Separation);
-			Factor2 = sin(Scale * Separation) / sin(Separation);
-		}
-		
-		Dest.k[0] = k[0] * Factor1 + Quat.k[0] * Factor2;
-		Dest.k[1] = k[1] * Factor1 + Quat.k[1] * Factor2;
-		Dest.k[2] = k[2] * Factor1 + Quat.k[2] * Factor2;
-		Dest.k[3] = k[3] * Factor1 + Quat.k[3] * Factor2;
-	}
-
-	void Slerp(const TQuaternion<T>& Quat, TQuaternion& Dest, T Scale) const
-	{
-		T Sq1,Sq2;
-		T Dot = DotProd(Quat);
-
-		TQuaternion Temp;
-
-		if (Dot < 0.0f)
-		{
-			Dot = -Dot;
-			Temp.k[0] = -Quat.k[0];
-			Temp.k[1] = -Quat.k[1];
-			Temp.k[2] = -Quat.k[2];
-			Temp.k[3] = -Quat.k[3];
-		}
-		else
-		{
-			Temp = Quat;
-		}
-
-		if ((1.0 + Dot) > 0.00001)
-		{
-			if ((1.0 - Dot) > 0.00001)
-			{
-				T om = (T)acos(Dot);
-				T rsinom = (T)(1.0f / sin(om));
-				Sq1 = (T)sin(((T)1.0 - Scale) * om) * rsinom;
-				Sq2 = (T)sin(Scale * om) * rsinom;
-			}
-			else
-			{
-				Sq1 = (T)(1.0 - Scale);
-				Sq2 = Scale;
-			}
-			Dest.k[0] = Sq1 * k[0] + Sq2 * Temp[0];
-			Dest.k[1] = Sq1 * k[1] + Sq2 * Temp[1];
-			Dest.k[2] = Sq1 * k[2] + Sq2 * Temp[2];
-			Dest.k[3] = Sq1 * k[3] + Sq2 * Temp[3];
-		}
-		else
-		{
-			Sq1 = (T)sin(((T)1.0 - Scale) * (T)0.5 * pi);
-			Sq2 = (T)sin(Scale * (T)0.5 * pi);
-
-			Dest.k[0] = Sq1 * k[0] + Sq2 * Temp[1];
-			Dest.k[1] = Sq1 * k[1] + Sq2 * Temp[0];
-			Dest.k[2] = Sq1 * k[2] + Sq2 * Temp[3];
-			Dest.k[3] = Sq1 * k[3] + Sq2 * Temp[2];
-		}
-	}*/
-
-	// perators
-	T& operator [] (int i) { return k[i]; }
-
-	// quaternion multiply
-	quaternion_base operator *(const quaternion_base& other) const
-	{
-		// (w1 dot w2 - v1 dot v2, w1 dot v2 + w2 dot v1 + v1 cross v2)
-		quaternion_base r;
-		r.k[0] = k[3] * other.k[0] + k[0] * other.k[3] + k[1] * other.k[2] - k[2] * other.k[1];
-		r.k[1] = k[3] * other.k[1] + k[1] * other.k[3] + k[2] * other.k[0] - k[0] * other.k[2];
-		r.k[2] = k[3] * other.k[2] + k[2] * other.k[3] + k[0] * other.k[1] - k[1] * other.k[0];
-		r.k[3] = k[3] * other.k[3] - k[0] * other.k[0] - k[1] * other.k[1] - k[2] * other.k[2];
-
-		return normalize(r);
-	}
-	
-	/*
-	bool operator == (const quaternion_base<T>& t) const { return ((k[0] == t.k[0]) && (k[1] == t.k[1]) && (k[2] == t.k[2]) && (k[3] == t.k[3])); }
-	bool operator != (const quaternion_base<T>& t) const { return ((k[0] != t.k[0]) || (k[1] != t.k[1]) || (k[2] != t.k[2]) || (k[3] != t.k[3])); }
-
-	void operator = (const quaternion_base<T>& other) { k[0] = other.k[0]; k[1] = other.k[1]; k[2] = other.k[2]; k[3] = other.k[3]; }
-	*/
-	
-	/*void operator *= (const TQuaternion<T>& t) 				{ TQuaternion Temp = Multiply(t); *this = Temp; }
-	TQuaternion operator * (const TQuaternion<T>& t)		const	{ return Multiply(t); }
-	*/
-};
-
-template<typename T>
-inline quaternion_base<T> normalize(const quaternion_base<T> &v)
-{
-	T factor = 1.0f/v.magnitude();
-	return quaternion_base<T>(v.k[0]*factor, v.k[1]*factor,v. k[2]*factor,v. k[3]*factor);
-}
-
-
diff --git a/src/base/tl/range.hpp b/src/base/tl/range.h
index 559daffa..1c63e73c 100644
--- a/src/base/tl/range.hpp
+++ b/src/base/tl/range.h
@@ -1,7 +1,7 @@
 #ifndef TL_FILE_RANGE_HPP
 #define TL_FILE_RANGE_HPP
 
-#include "base.hpp"
+#include "base.h"
 
 /*
 	Group: Range concepts
diff --git a/src/base/tl/sorted_array.hpp b/src/base/tl/sorted_array.h
index 30c1df24..95f06157 100644
--- a/src/base/tl/sorted_array.hpp
+++ b/src/base/tl/sorted_array.h
@@ -1,8 +1,8 @@
 #ifndef TL_FILE_SORTED_ARRAY_HPP
 #define TL_FILE_SORTED_ARRAY_HPP
 
-#include "algorithm.hpp"
-#include "array.hpp"
+#include "algorithm.h"
+#include "array.h"
 
 template <class T, class ALLOCATOR = allocator_default<T> >
 class sorted_array : public array<T, ALLOCATOR>
diff --git a/src/base/tl/stream.hpp b/src/base/tl/stream.hpp
deleted file mode 100644
index c307b968..00000000
--- a/src/base/tl/stream.hpp
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef TL_FILE_STREAM_HPP
-#define TL_FILE_STREAM_HPP
-
-class input_stream
-{
-public:	
-	virtual ~input_stream() {}
-	virtual size_t read(void *data, size_t size) = 0;
-	virtual size_t size() = 0;
-};
-
-class output_stream
-{
-public:	
-	virtual ~output_stream() {}
-	virtual size_t write(const void *data, size_t size) = 0;
-};
-
-
-// input wrapping
-// RAII style
-class file_backend
-{
-private:
-	file_backend(const file_backend &other) { /* no copy allowed */ }
-protected:
-	IOHANDLE file_handle;
-	
-	explicit file_backend(const char *filename, int flags)
-	{
-		file_handle = io_open(filename, flags);
-	}
-	
-	~file_backend()
-	{
-		if(file_handle)
-			io_close(file_handle);
-	}
-public:
-	bool is_open() const { return file_handle != 0; }
-};
-
-class file_reader : public input_stream, public file_backend
-{
-public:	
-	explicit file_reader(const char *filename)
-	: file_backend(filename, IOFLAG_READ)
-	{}
-	
-	virtual size_t read(void *data, size_t size) { return io_read(file_handle, data, size); }
-	virtual size_t size() { return io_length(file_handle); }
-};
-
-
-class file_writer : public output_stream, public file_backend
-{
-public:	
-	explicit file_writer(const char *filename)
-	: file_backend(filename, IOFLAG_WRITE)
-	{}
-	
-	virtual size_t write(const void *data, size_t size) { return io_write(file_handle, data, size); }
-};
-
-#endif
diff --git a/src/base/tl/string.hpp b/src/base/tl/string.h
index 2b164091..155ca2a4 100644
--- a/src/base/tl/string.hpp
+++ b/src/base/tl/string.h
@@ -1,8 +1,8 @@
 #ifndef TL_FILE_STRING_HPP
 #define TL_FILE_STRING_HPP
 
-#include "base.hpp"
-#include "allocator.hpp"
+#include "base.h"
+#include "allocator.h"
 
 template<class ALLOCATOR >
 class string_base : private ALLOCATOR
diff --git a/src/base/tl/vector.hpp b/src/base/tl/vector.hpp
deleted file mode 100644
index 1c1bb804..00000000
--- a/src/base/tl/vector.hpp
+++ /dev/null
@@ -1,198 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef TL_FILE_VECTOR_HPP
-#define TL_FILE_VECTOR_HPP
-
-#include <math.h>
-
-// ------------------------------------
-
-template<typename T>
-class vector2_base
-{
-public:
-	union { T x,u; };
-	union { T y,v; };
-	
-	vector2_base() {}
-	vector2_base(float nx, float ny)
-	{
-		x = nx;
-		y = ny;
-	}
-	
-	vector2_base operator -() const { return vector2_base(-x, -y); }
-	vector2_base operator -(const vector2_base &v) const { return vector2_base(x-v.x, y-v.y); }
-	vector2_base operator +(const vector2_base &v) const { return vector2_base(x+v.x, y+v.y); }
-	vector2_base operator *(const T v) const { return vector2_base(x*v, y*v); }
-	
-	const vector2_base &operator =(const vector2_base &v) { x = v.x; y = v.y; return *this; }
-
-	const vector2_base &operator +=(const vector2_base &v) { x += v.x; y += v.y; return *this; }
-	const vector2_base &operator -=(const vector2_base &v) { x -= v.x; y -= v.y; return *this; }
-	const vector2_base &operator *=(const T v) { x *= v; y *= v; return *this;	}
-
-	bool operator ==(const vector2_base &v) const { return x == v.x && y == v.y; } //TODO: do this with an eps instead
-
-	operator const T* () { return &x; }
-};
-
-
-template<typename T>
-inline T length(const vector2_base<T> &a)
-{
-	return sqrtf(a.x*a.x + a.y*a.y);
-}
-
-template<typename T>
-inline T distance(const vector2_base<T> a, const vector2_base<T> &b)
-{
-	return length(a-b);
-}
-
-template<typename T>
-inline T dot(const vector2_base<T> a, const vector2_base<T> &b)
-{
-	return a.x*b.x + a.y*b.y;
-}
-
-template<typename T>
-inline vector2_base<T> normalize(const vector2_base<T> &v)
-{
-	T l = (T)(1.0f/sqrtf(v.x*v.x + v.y*v.y));
-	return vector2_base<T>(v.x*l, v.y*l);
-}
-
-typedef vector2_base<float> vec2;
-typedef vector2_base<bool> bvec2;
-typedef vector2_base<int> ivec2;
-
-template<typename T>
-inline vector2_base<T> closest_point_on_line(vector2_base<T> line_point0, vector2_base<T> line_point1, vector2_base<T> target_point)
-{
-	vector2_base<T> c = target_point - line_point0;
-	vector2_base<T> v = (line_point1 - line_point0);
-	v = normalize(v);
-	T d = length(line_point0-line_point1);
-	T t = dot(v, c)/d;
-	return mix(line_point0, line_point1, clamp(t, (T)0, (T)1));
-	/*
-	if (t < 0) t = 0;
-	if (t > 1.0f) return 1.0f;
-	return t;*/
-}
-	
-// ------------------------------------
-template<typename T>
-class vector3_base
-{
-public:
-	union { T x,r,h; };
-	union { T y,g,s; };
-	union { T z,b,v,l; };
-
-	vector3_base() {}
-	vector3_base(float nx, float ny, float nz)
-	{
-		x = nx;
-		y = ny;
-		z = nz;
-	}
-	
-	const vector3_base &operator =(const vector3_base &v) { x = v.x; y = v.y; z = v.z; return *this; }
-
-	vector3_base operator -(const vector3_base &v) const { return vector3_base(x-v.x, y-v.y, z-v.z); }
-	vector3_base operator -() const { return vector3_base(-x, -y, -z); }
-	vector3_base operator +(const vector3_base &v) const { return vector3_base(x+v.x, y+v.y, z+v.z); }
-	vector3_base operator *(const T v) const { return vector3_base(x*v, y*v, z*v); }
-	vector3_base operator *(const vector3_base &v) const { return vector3_base(x*v.x, y*v.y, z*v.z); }
-	vector3_base operator /(const T v) const { return vector3_base(x/v, y/v, z/v); }
-	
-	const vector3_base &operator +=(const vector3_base &v) { x += v.x; y += v.y; z += v.z; return *this; }
-	const vector3_base &operator -=(const vector3_base &v) { x -= v.x; y -= v.y; z -= v.z; return *this; }
-	const vector3_base &operator *=(const T v) { x *= v; y *= v; z *= v; return *this;	}
-
-	bool operator ==(const vector3_base &v) const { return x == v.x && y == v.y && z == v.z; } //TODO: do this with an eps instead
-
-	operator const T* () { return &x; }
-};
-
-template<typename T>
-inline T length(const vector3_base<T> &a)
-{
-	return sqrtf(a.x*a.x + a.y*a.y + a.z*a.z);
-}
-
-template<typename T>
-inline T distance(const vector3_base<T> &a, const vector3_base<T> &b)
-{
-	return length(a-b);
-}
-
-template<typename T>
-inline T dot(const vector3_base<T> &a, const vector3_base<T> &b)
-{
-	return a.x*b.x + a.y*b.y + a.z*b.z;
-}
-
-template<typename T>
-inline vector3_base<T> normalize(const vector3_base<T> &v)
-{
-	T l = (T)(1.0f/sqrtf(v.x*v.x + v.y*v.y + v.z*v.z));
-	return vector3_base<T>(v.x*l, v.y*l, v.z*l);
-}
-
-template<typename T>
-inline vector3_base<T> cross(const vector3_base<T> &a, const vector3_base<T> &b)
-{
-	return vector3_base<T>(
-		a.y*b.z - a.z*b.y,
-		a.z*b.x - a.x*b.z,
-		a.x*b.y - a.y*b.x);
-}
-
-typedef vector3_base<float> vec3;
-typedef vector3_base<bool> bvec3;
-typedef vector3_base<int> ivec3;
-
-// ------------------------------------
-
-template<typename T>
-class vector4_base
-{
-public:
-	union { T x,r; };
-	union { T y,g; };
-	union { T z,b; };
-	union { T w,a; };
-
-	vector4_base() {}
-	vector4_base(float nx, float ny, float nz, float nw)
-	{
-		x = nx;
-		y = ny;
-		z = nz;
-		w = nw;
-	}
-	
-	vector4_base operator +(const vector4_base &v) const { return vector4_base(x+v.x, y+v.y, z+v.z, w+v.w); }
-	vector4_base operator -(const vector4_base &v) const { return vector4_base(x-v.x, y-v.y, z-v.z, w-v.w); }
-	vector4_base operator -() const { return vector4_base(-x, -y, -z, -w); }
-	vector4_base operator *(const vector4_base &v) const { return vector4_base(x*v.x, y*v.y, z*v.z, w*v.w); }
-	vector4_base operator *(const T v) const { return vector4_base(x*v, y*v, z*v, w*v); }
-	
-	const vector4_base &operator =(const vector4_base &v) { x = v.x; y = v.y; z = v.z; w = v.w; return *this; }
-
-	const vector4_base &operator +=(const vector4_base &v) { x += v.x; y += v.y; z += v.z; w += v.w; return *this; }
-	const vector4_base &operator -=(const vector4_base &v) { x -= v.x; y -= v.y; z -= v.z; w -= v.w; return *this; }
-	const vector4_base &operator *=(const T v) { x *= v; y *= v; z *= v; w *= v; return *this;	}
-
-	bool operator ==(const vector4_base &v) const { return x == v.x && y == v.y && z == v.z && w == v.w; } //TODO: do this with an eps instead
-
-	operator const T* () { return &x; }
-};
-
-typedef vector4_base<float> vec4;
-typedef vector4_base<bool> bvec4;
-typedef vector4_base<int> ivec4;
-
-#endif
diff --git a/src/base/vmath.hpp b/src/base/vmath.h
index 49dd26d1..49dd26d1 100644
--- a/src/base/vmath.hpp
+++ b/src/base/vmath.h
diff --git a/src/engine/client.h b/src/engine/client.h
new file mode 100644
index 00000000..8e5a5577
--- /dev/null
+++ b/src/engine/client.h
@@ -0,0 +1,159 @@
+#ifndef ENGINE_CLIENT_H
+#define ENGINE_CLIENT_H
+#include "kernel.h"
+
+#include "message.h"
+
+class IClient : public IInterface
+{
+	MACRO_INTERFACE("client", 0)
+protected:
+	// quick access to state of the client
+	int m_State;
+
+	// quick access to time variables
+	int m_PrevGameTick;
+	int m_CurGameTick;
+	float m_GameIntraTick;
+	float m_GameTickTime;
+	
+	int m_PredTick;
+	float m_PredIntraTick;
+	
+	float m_LocalTime;
+	float m_FrameTime;
+	
+	int m_GameTickSpeed;
+public:
+
+	class CSnapItem
+	{
+	public:
+		int m_Type;
+		int m_Id;
+		int m_DataSize;
+	};
+
+	/* Constants: Client States
+		STATE_OFFLINE - The client is offline.
+		STATE_CONNECTING - The client is trying to connect to a server.
+		STATE_LOADING - The client has connected to a server and is loading resources.
+		STATE_ONLINE - The client is connected to a server and running the game.
+		STATE_DEMOPLAYBACK - The client is playing a demo
+		STATE_QUITING - The client is quiting.
+	*/
+
+	enum
+	{
+		STATE_OFFLINE=0,
+		STATE_CONNECTING,
+		STATE_LOADING,
+		STATE_ONLINE,
+		STATE_DEMOPLAYBACK,
+		STATE_QUITING,
+	};
+
+	//
+	inline int State() const { return m_State; }
+
+	// tick time access
+	inline int PrevGameTick() const { return m_PrevGameTick; }
+	inline int GameTick() const { return m_CurGameTick; }
+	inline int PredGameTick() const { return m_PredTick; }
+	inline float IntraGameTick() const { return m_GameIntraTick; }
+	inline float PredIntraGameTick() const { return m_PredIntraTick; }
+	inline float GameTickTime() const { return m_GameTickTime; }
+	inline int GameTickSpeed() const { return m_GameTickSpeed; }
+	
+	// other time access
+	inline float FrameTime() const { return m_FrameTime; }
+	inline float LocalTime() const { return m_LocalTime; }
+	
+	// actions
+	virtual void Connect(const char *pAddress) = 0;
+	virtual void Disconnect() = 0;
+	virtual void Quit() = 0;
+	virtual const char *DemoPlayer_Play(const char *pFilename) = 0;
+
+	// networking
+	virtual void EnterGame() = 0;
+
+	//
+	virtual int MapDownloadAmount() = 0;
+	virtual int MapDownloadTotalsize() = 0;
+	
+	// input
+	virtual int *GetInput(int Tick) = 0;
+	
+	// remote console
+	virtual void RconAuth(const char *pUsername, const char *pPassword) = 0;
+	virtual bool RconAuthed() = 0;
+	virtual void Rcon(const char *pLine) = 0;
+	
+	// server info
+	virtual void GetServerInfo(class CServerInfo *pServerInfo) = 0;
+	
+	// snapshot interface
+	
+	enum
+	{
+		SNAP_CURRENT=0,
+		SNAP_PREV=1
+	};
+		
+	// TODO: Refactor: should redo this a bit i think, too many virtual calls
+	virtual int SnapNumItems(int SnapId) = 0;
+	virtual void *SnapFindItem(int SnapId, int Type, int Id) = 0;
+	virtual void *SnapGetItem(int SnapId, int Index, CSnapItem *pItem) = 0;
+	virtual void SnapInvalidateItem(int SnapId, int Index) = 0;
+
+	virtual void SnapSetStaticsize(int ItemType, int Size) = 0;
+
+	virtual int SendMsg(CMsgPacker *pMsg, int Flags) = 0;
+
+	template<class T>
+	int SendPackMsg(T *pMsg, int Flags)
+	{
+		CMsgPacker Packer(pMsg->MsgID());
+		if(pMsg->Pack(&Packer))
+			return -1;
+		return SendMsg(&Packer, Flags);
+	}
+	
+	//
+	virtual const char *UserDirectory() = 0;
+	
+	// 
+	virtual const char *ErrorString() = 0;
+	virtual const char *LatestVersion() = 0;
+	virtual bool ConnectionProblems() = 0;
+};
+
+class IGameClient : public IInterface
+{
+	MACRO_INTERFACE("gameclient", 0)
+protected:
+public:
+	virtual void OnConsoleInit() = 0;
+
+	virtual void OnRconLine(const char *pLine) = 0;
+	virtual void OnInit() = 0;
+	virtual void OnNewSnapshot() = 0;
+	virtual void OnEnterGame() = 0;
+	virtual void OnShutdown() = 0;
+	virtual void OnRender() = 0;
+	virtual void OnStateChange(int NewState, int OldState) = 0;
+	virtual void OnConnected() = 0;
+	virtual void OnMessage(int MsgId, CUnpacker *pUnpacker) = 0;
+	virtual void OnPredict() = 0;
+	
+	virtual int OnSnapInput(int *pData) = 0;
+	
+	virtual const char *GetItemName(int Type) = 0;
+	virtual const char *Version() = 0;
+	virtual const char *NetVersion() = 0;
+
+};
+
+extern IGameClient *CreateGameClient();
+#endif
diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp
new file mode 100644
index 00000000..dbcaa1ed
--- /dev/null
+++ b/src/engine/client/client.cpp
@@ -0,0 +1,2062 @@
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+
+#include <stdlib.h> // qsort
+#include <stdarg.h>
+#include <math.h>
+
+#include <base/system.h>
+#include <engine/shared/engine.h>
+
+#include <engine/shared/protocol.h>
+#include <engine/shared/snapshot.h>
+#include <engine/shared/compression.h>
+#include <engine/shared/network.h>
+#include <engine/shared/config.h>
+#include <engine/shared/packer.h>
+#include <engine/shared/memheap.h>
+#include <engine/shared/datafile.h>
+#include <engine/shared/ringbuffer.h>
+#include <engine/shared/protocol.h>
+
+#include <engine/shared/demorec.h>
+
+#include <mastersrv/mastersrv.h>
+#include <versionsrv/versionsrv.h>
+
+#include "client.h"
+
+
+void CGraph::Init(float Min, float Max)
+{
+	m_Min = Min;
+	m_Max = Max;
+	m_Index = 0;
+}
+
+void CGraph::ScaleMax()
+{
+	int i = 0;
+	m_Max = 0;
+	for(i = 0; i < MAX_VALUES; i++)
+	{
+		if(m_aValues[i] > m_Max)
+			m_Max = m_aValues[i];
+	}
+}
+
+void CGraph::ScaleMin()
+{
+	int i = 0;
+	m_Min = m_Max;
+	for(i = 0; i < MAX_VALUES; i++)
+	{
+		if(m_aValues[i] < m_Min)
+			m_Min = m_aValues[i];
+	}
+}
+
+void CGraph::Add(float v, float r, float g, float b)
+{
+	m_Index = (m_Index+1)&(MAX_VALUES-1);
+	m_aValues[m_Index] = v;
+	m_aColors[m_Index][0] = r;
+	m_aColors[m_Index][1] = g;
+	m_aColors[m_Index][2] = b;
+}
+
+void CGraph::Render(IGraphics *pGraphics, int Font, float x, float y, float w, float h, const char *pDescription)
+{
+	//m_pGraphics->BlendNormal();
+
+
+	pGraphics->TextureSet(-1);
+
+	pGraphics->QuadsBegin();
+	pGraphics->SetColor(0, 0, 0, 0.75f);
+	IGraphics::CQuadItem QuadItem(x, y, w, h);
+	pGraphics->QuadsDrawTL(&QuadItem, 1);
+	pGraphics->QuadsEnd();
+
+	pGraphics->LinesBegin();
+	pGraphics->SetColor(0.95f, 0.95f, 0.95f, 1.00f);
+	IGraphics::CLineItem LineItem(x, y+h/2, x+w, y+h/2);
+	pGraphics->LinesDraw(&LineItem, 1);
+	pGraphics->SetColor(0.5f, 0.5f, 0.5f, 0.75f);
+	IGraphics::CLineItem Array[2] = {
+		IGraphics::CLineItem(x, y+(h*3)/4, x+w, y+(h*3)/4),
+		IGraphics::CLineItem(x, y+h/4, x+w, y+h/4)};
+	pGraphics->LinesDraw(Array, 2);
+	for(int i = 1; i < MAX_VALUES; i++)
+	{
+		float a0 = (i-1)/(float)MAX_VALUES;
+		float a1 = i/(float)MAX_VALUES;
+		int i0 = (m_Index+i-1)&(MAX_VALUES-1);
+		int i1 = (m_Index+i)&(MAX_VALUES-1);
+
+		float v0 = (m_aValues[i0]-m_Min) / (m_Max-m_Min);
+		float v1 = (m_aValues[i1]-m_Min) / (m_Max-m_Min);
+
+		IGraphics::CColorVertex Array[2] = {
+			IGraphics::CColorVertex(0, m_aColors[i0][0], m_aColors[i0][1], m_aColors[i0][2], 0.75f),
+			IGraphics::CColorVertex(1, m_aColors[i1][0], m_aColors[i1][1], m_aColors[i1][2], 0.75f)};
+		pGraphics->SetColorVertex(Array, 2);
+		IGraphics::CLineItem LineItem(x+a0*w, y+h-v0*h, x+a1*w, y+h-v1*h);
+		pGraphics->LinesDraw(&LineItem, 1);
+
+	}
+	pGraphics->LinesEnd();
+
+	pGraphics->TextureSet(Font);
+	pGraphics->QuadsText(x+2, y+h-16, 16, 1,1,1,1, pDescription);
+
+	char aBuf[32];
+	str_format(aBuf, sizeof(aBuf), "%.2f", m_Max);
+	pGraphics->QuadsText(x+w-8*str_length(aBuf)-8, y+2, 16, 1,1,1,1, aBuf);
+
+	str_format(aBuf, sizeof(aBuf), "%.2f", m_Min);
+	pGraphics->QuadsText(x+w-8*str_length(aBuf)-8, y+h-16, 16, 1,1,1,1, aBuf);
+}
+
+
+void CSmoothTime::Init(int64 Target)
+{
+	m_Snap = time_get();
+	m_Current = Target;
+	m_Target = Target;
+	m_aAdjustSpeed[0] = 0.3f;
+	m_aAdjustSpeed[1] = 0.3f;
+	m_Graph.Init(0.0f, 0.5f);
+}
+
+void CSmoothTime::SetAdjustSpeed(int Direction, float Value)
+{
+	m_aAdjustSpeed[Direction] = Value;
+}
+
+int64 CSmoothTime::Get(int64 Now)
+{
+	int64 c = m_Current + (Now - m_Snap);
+	int64 t = m_Target + (Now - m_Snap);
+
+	// it's faster to adjust upward instead of downward
+	// we might need to adjust these abit
+
+	float AdjustSpeed = m_aAdjustSpeed[0];
+	if(t > c)
+		AdjustSpeed = m_aAdjustSpeed[1];
+
+	float a = ((Now-m_Snap)/(float)time_freq()) * AdjustSpeed;
+	if(a > 1.0f)
+		a = 1.0f;
+
+	int64 r = c + (int64)((t-c)*a);
+
+	m_Graph.Add(a+0.5f,1,1,1);
+
+	return r;
+}
+
+void CSmoothTime::UpdateInt(int64 Target)
+{
+	int64 Now = time_get();
+	m_Current = Get(Now);
+	m_Snap = Now;
+	m_Target = Target;
+}
+
+void CSmoothTime::Update(CGraph *pGraph, int64 Target, int TimeLeft, int AdjustDirection)
+{
+	int UpdateTimer = 1;
+
+	if(TimeLeft < 0)
+	{
+		int IsSpike = 0;
+		if(TimeLeft < -50)
+		{
+			IsSpike = 1;
+
+			m_SpikeCounter += 5;
+			if(m_SpikeCounter > 50)
+				m_SpikeCounter = 50;
+		}
+
+		if(IsSpike && m_SpikeCounter < 15)
+		{
+			// ignore this ping spike
+			UpdateTimer = 0;
+			pGraph->Add(TimeLeft, 1,1,0);
+		}
+		else
+		{
+			pGraph->Add(TimeLeft, 1,0,0);
+			if(m_aAdjustSpeed[AdjustDirection] < 30.0f)
+				m_aAdjustSpeed[AdjustDirection] *= 2.0f;
+		}
+	}
+	else
+	{
+		if(m_SpikeCounter)
+			m_SpikeCounter--;
+
+		pGraph->Add(TimeLeft, 0,1,0);
+
+		m_aAdjustSpeed[AdjustDirection] *= 0.95f;
+		if(m_aAdjustSpeed[AdjustDirection] < 2.0f)
+			m_aAdjustSpeed[AdjustDirection] = 2.0f;
+	}
+
+	if(UpdateTimer)
+		UpdateInt(Target);
+}
+
+
+CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotDelta)
+{
+	m_pEditor = 0;
+	m_pInput = 0;
+	m_pGraphics = 0;
+	m_pSound = 0;
+	m_pGameClient = 0;
+	m_pMap = 0;
+	m_pConsole = 0;
+
+	m_FrameTime = 0.0001f;
+	m_FrameTimeLow = 1.0f;
+	m_FrameTimeHigh = 0.0f;
+	m_Frames = 0;
+
+	m_GameTickSpeed = SERVER_TICK_SPEED;
+
+	m_WindowMustRefocus = 0;
+	m_SnapCrcErrors = 0;
+
+	m_AckGameTick = -1;
+	m_CurrentRecvTick = 0;
+	m_RconAuthed = 0;
+
+	// version-checking
+	m_aVersionStr[0] = '0';
+	m_aVersionStr[1] = 0;
+
+	// pinging
+	m_PingStartTime = 0;
+
+	//
+	m_aCurrentMap[0] = 0;
+	m_CurrentMapCrc = 0;
+
+	//
+	m_aCmdConnect[0] = 0;
+
+	// map download
+	m_aMapdownloadFilename[0] = 0;
+	m_aMapdownloadName[0] = 0;
+	m_MapdownloadFile = 0;
+	m_MapdownloadChunk = 0;
+	m_MapdownloadCrc = 0;
+	m_MapdownloadAmount = -1;
+	m_MapdownloadTotalsize = -1;
+
+	m_CurrentServerInfoRequestTime = -1;
+
+	m_CurrentInput = 0;
+
+	m_State = IClient::STATE_OFFLINE;
+	m_aServerAddressStr[0] = 0;
+
+	mem_zero(m_aSnapshots, sizeof(m_aSnapshots));
+	m_RecivedSnapshots = 0;
+
+	m_VersionInfo.m_State = 0;
+}
+
+// ----- send functions -----
+int CClient::SendMsg(CMsgPacker *pMsg, int Flags)
+{
+	return SendMsgEx(pMsg, Flags, false);
+}
+
+int CClient::SendMsgEx(CMsgPacker *pMsg, int Flags, bool System)
+{
+	CNetChunk Packet;
+
+	if(State() == IClient::STATE_OFFLINE)
+		return 0;
+
+	mem_zero(&Packet, sizeof(CNetChunk));
+
+	Packet.m_ClientID = 0;
+	Packet.m_pData = pMsg->Data();
+	Packet.m_DataSize = pMsg->Size();
+
+	// HACK: modify the message id in the packet and store the system flag
+	if(*((unsigned char*)Packet.m_pData) == 1 && System && Packet.m_DataSize == 1)
+		dbg_break();
+
+	*((unsigned char*)Packet.m_pData) <<= 1;
+	if(System)
+		*((unsigned char*)Packet.m_pData) |= 1;
+
+	if(Flags&MSGFLAG_VITAL)
+		Packet.m_Flags |= NETSENDFLAG_VITAL;
+	if(Flags&MSGFLAG_FLUSH)
+		Packet.m_Flags |= NETSENDFLAG_FLUSH;
+
+	if(Flags&MSGFLAG_RECORD)
+	{
+		if(m_DemoRecorder.IsRecording())
+			m_DemoRecorder.RecordMessage(Packet.m_pData, Packet.m_DataSize);
+	}
+
+	if(!(Flags&MSGFLAG_NOSEND))
+		m_NetClient.Send(&Packet);
+	return 0;
+}
+
+void CClient::SendInfo()
+{
+	CMsgPacker Msg(NETMSG_INFO);
+	Msg.AddString(GameClient()->NetVersion(), 128);
+	Msg.AddString(g_Config.m_PlayerName, 128);
+	Msg.AddString(g_Config.m_ClanName, 128);
+	Msg.AddString(g_Config.m_Password, 128);
+	SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH);
+}
+
+
+void CClient::SendEnterGame()
+{
+	CMsgPacker Msg(NETMSG_ENTERGAME);
+	SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH);
+}
+
+void CClient::SendReady()
+{
+	CMsgPacker Msg(NETMSG_READY);
+	SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH);
+}
+
+bool CClient::RconAuthed()
+{
+	return m_RconAuthed;
+}
+
+void CClient::RconAuth(const char *pName, const char *pPassword)
+{
+	if(RconAuthed())
+		return;
+        
+	CMsgPacker Msg(NETMSG_RCON_AUTH);
+	Msg.AddString(pName, 32);
+	Msg.AddString(pPassword, 32);
+	SendMsgEx(&Msg, MSGFLAG_VITAL);
+}
+
+void CClient::Rcon(const char *pCmd)
+{
+	CMsgPacker Msg(NETMSG_RCON_CMD);
+	Msg.AddString(pCmd, 256);
+	SendMsgEx(&Msg, MSGFLAG_VITAL);
+}
+
+bool CClient::ConnectionProblems()
+{
+	return m_NetClient.GotProblems() != 0;
+}
+
+void CClient::DirectInput(int *pInput, int Size)
+{
+	int i;
+	CMsgPacker Msg(NETMSG_INPUT);
+	Msg.AddInt(m_AckGameTick);
+	Msg.AddInt(m_PredTick);
+	Msg.AddInt(Size);
+
+	for(i = 0; i < Size/4; i++)
+		Msg.AddInt(pInput[i]);
+
+	SendMsgEx(&Msg, 0);
+}
+
+
+void CClient::SendInput()
+{
+	int64 Now = time_get();
+
+	if(m_PredTick <= 0)
+		return;
+
+	// fetch input
+	int Size = GameClient()->OnSnapInput(m_aInputs[m_CurrentInput].m_aData);
+
+	if(!Size)
+		return;
+
+	// pack input
+	CMsgPacker Msg(NETMSG_INPUT);
+	Msg.AddInt(m_AckGameTick);
+	Msg.AddInt(m_PredTick);
+	Msg.AddInt(Size);
+
+	m_aInputs[m_CurrentInput].m_Tick = m_PredTick;
+	m_aInputs[m_CurrentInput].m_PredictedTime = m_PredictedTime.Get(Now);
+	m_aInputs[m_CurrentInput].m_Time = Now;
+
+	// pack it
+	for(int i = 0; i < Size/4; i++)
+		Msg.AddInt(m_aInputs[m_CurrentInput].m_aData[i]);
+
+	m_CurrentInput++;
+	m_CurrentInput%=200;
+
+	SendMsgEx(&Msg, MSGFLAG_FLUSH);
+}
+
+const char *CClient::LatestVersion()
+{
+	return m_aVersionStr;
+}
+
+// TODO: OPT: do this alot smarter!
+int *CClient::GetInput(int Tick)
+{
+	int Best = -1;
+	for(int i = 0; i < 200; i++)
+	{
+		if(m_aInputs[i].m_Tick <= Tick && (Best == -1 || m_aInputs[Best].m_Tick < m_aInputs[i].m_Tick))
+			Best = i;
+	}
+
+	if(Best != -1)
+		return (int *)m_aInputs[Best].m_aData;
+	return 0;
+}
+
+// ------ state handling -----
+void CClient::SetState(int s)
+{
+	int Old = m_State;
+	if(g_Config.m_Debug)
+		dbg_msg("client", "state change. last=%d current=%d", m_State, s);
+	m_State = s;
+	if(Old != s)
+		GameClient()->OnStateChange(m_State, Old);
+}
+
+// called when the map is loaded and we should init for a new round
+void CClient::OnEnterGame()
+{
+	// reset input
+	int i;
+	for(i = 0; i < 200; i++)
+		m_aInputs[i].m_Tick = -1;
+	m_CurrentInput = 0;
+
+	// reset snapshots
+	m_aSnapshots[SNAP_CURRENT] = 0;
+	m_aSnapshots[SNAP_PREV] = 0;
+	m_SnapshotStorage.PurgeAll();
+	m_RecivedSnapshots = 0;
+	m_SnapshotParts = 0;
+	m_PredTick = 0;
+	m_CurrentRecvTick = 0;
+	m_CurGameTick = 0;
+	m_PrevGameTick = 0;
+}
+
+void CClient::EnterGame()
+{
+	if(State() == IClient::STATE_DEMOPLAYBACK)
+		return;
+
+	// now we will wait for two snapshots
+	// to finish the connection
+	SendEnterGame();
+	OnEnterGame();
+}
+
+void CClient::Connect(const char *pAddress)
+{
+	char aBuf[512];
+	const char *pPortStr = 0;
+	int Port = 8303;
+
+	Disconnect();
+
+	str_copy(m_aServerAddressStr, pAddress, sizeof(m_aServerAddressStr));
+
+	dbg_msg("client", "connecting to '%s'", m_aServerAddressStr);
+
+	ServerInfoRequest();
+	str_copy(aBuf, m_aServerAddressStr, sizeof(aBuf));
+
+	for(int k = 0; aBuf[k]; k++)
+	{
+		if(aBuf[k] == ':')
+		{
+			pPortStr = &(aBuf[k+1]);
+			aBuf[k] = 0;
+			break;
+		}
+	}
+
+	if(pPortStr)
+		Port = str_toint(pPortStr);
+
+	// TODO: IPv6 support
+	if(net_host_lookup(aBuf, &m_ServerAddress, NETTYPE_IPV4) != 0)
+		dbg_msg("client", "could not find the address of %s, connecting to localhost", aBuf);
+
+	m_RconAuthed = 0;
+	m_ServerAddress.port = Port;
+	m_NetClient.Connect(&m_ServerAddress);
+	SetState(IClient::STATE_CONNECTING);
+
+	if(m_DemoRecorder.IsRecording())
+		m_DemoRecorder.Stop();
+
+	m_InputtimeMarginGraph.Init(-150.0f, 150.0f);
+	m_GametimeMarginGraph.Init(-150.0f, 150.0f);
+}
+
+void CClient::DisconnectWithReason(const char *pReason)
+{
+	// stop demo playback and recorder
+	m_DemoPlayer.Stop();
+	m_DemoRecorder.Stop();
+
+	//
+	m_RconAuthed = 0;
+	m_NetClient.Disconnect(pReason);
+	SetState(IClient::STATE_OFFLINE);
+	m_pMap->Unload();
+
+	// disable all downloads
+	m_MapdownloadChunk = 0;
+	if(m_MapdownloadFile)
+		io_close(m_MapdownloadFile);
+	m_MapdownloadFile = 0;
+	m_MapdownloadCrc = 0;
+	m_MapdownloadTotalsize = -1;
+	m_MapdownloadAmount = 0;
+
+	// clear the current server info
+	mem_zero(&m_CurrentServerInfo, sizeof(m_CurrentServerInfo));
+	mem_zero(&m_ServerAddress, sizeof(m_ServerAddress));
+
+	// clear snapshots
+	m_aSnapshots[SNAP_CURRENT] = 0;
+	m_aSnapshots[SNAP_PREV] = 0;
+	m_RecivedSnapshots = 0;
+}
+
+void CClient::Disconnect()
+{
+	DisconnectWithReason(0);
+}
+
+
+void CClient::GetServerInfo(CServerInfo *pServerInfo)
+{
+	mem_copy(pServerInfo, &m_CurrentServerInfo, sizeof(m_CurrentServerInfo));
+}
+
+void CClient::ServerInfoRequest()
+{
+	mem_zero(&m_CurrentServerInfo, sizeof(m_CurrentServerInfo));
+	m_CurrentServerInfoRequestTime = 0;
+}
+
+int CClient::LoadData()
+{
+	m_DebugFont = Graphics()->LoadTexture("debug_font.png", CImageInfo::FORMAT_AUTO, IGraphics::TEXLOAD_NORESAMPLE);
+	return 1;
+}
+
+// ---
+
+void *CClient::SnapGetItem(int SnapId, int Index, CSnapItem *pItem)
+{
+	CSnapshotItem *i;
+	dbg_assert(SnapId >= 0 && SnapId < NUM_SNAPSHOT_TYPES, "invalid SnapId");
+	i = m_aSnapshots[SnapId]->m_pAltSnap->GetItem(Index);
+	pItem->m_DataSize = m_aSnapshots[SnapId]->m_pAltSnap->GetItemSize(Index);
+	pItem->m_Type = i->Type();
+	pItem->m_Id = i->ID();
+	return (void *)i->Data();
+}
+
+void CClient::SnapInvalidateItem(int SnapId, int Index)
+{
+	CSnapshotItem *i;
+	dbg_assert(SnapId >= 0 && SnapId < NUM_SNAPSHOT_TYPES, "invalid SnapId");
+	i = m_aSnapshots[SnapId]->m_pAltSnap->GetItem(Index);
+	if(i)
+	{
+		if((char *)i < (char *)m_aSnapshots[SnapId]->m_pAltSnap || (char *)i > (char *)m_aSnapshots[SnapId]->m_pAltSnap + m_aSnapshots[SnapId]->m_SnapSize)
+			dbg_msg("ASDFASDFASdf", "ASDFASDFASDF");
+		if((char *)i >= (char *)m_aSnapshots[SnapId]->m_pSnap && (char *)i < (char *)m_aSnapshots[SnapId]->m_pSnap + m_aSnapshots[SnapId]->m_SnapSize)
+			dbg_msg("ASDFASDFASdf", "ASDFASDFASDF");
+		i->m_TypeAndID = -1;
+	}
+}
+
+void *CClient::SnapFindItem(int SnapId, int Type, int Id)
+{
+	// TODO: linear search. should be fixed.
+	int i;
+
+	if(!m_aSnapshots[SnapId])
+		return 0x0;
+
+	for(i = 0; i < m_aSnapshots[SnapId]->m_pSnap->NumItems(); i++)
+	{
+		CSnapshotItem *pItem = m_aSnapshots[SnapId]->m_pAltSnap->GetItem(i);
+		if(pItem->Type() == Type && pItem->ID() == Id)
+			return (void *)pItem->Data();
+	}
+	return 0x0;
+}
+
+int CClient::SnapNumItems(int SnapId)
+{
+	dbg_assert(SnapId >= 0 && SnapId < NUM_SNAPSHOT_TYPES, "invalid SnapId");
+	if(!m_aSnapshots[SnapId])
+		return 0;
+	return m_aSnapshots[SnapId]->m_pSnap->NumItems();
+}
+
+void CClient::SnapSetStaticsize(int ItemType, int Size)
+{
+	m_SnapshotDelta.SetStaticsize(ItemType, Size);
+}
+
+
+void CClient::DebugRender()
+{
+	static NETSTATS Prev, Current;
+	static int64 LastSnap = 0;
+	static float FrameTimeAvg = 0;
+	int64 Now = time_get();
+	char aBuffer[512];
+
+	if(!g_Config.m_Debug)
+		return;
+
+	//m_pGraphics->BlendNormal();
+	Graphics()->TextureSet(m_DebugFont);
+	Graphics()->MapScreen(0,0,Graphics()->ScreenWidth(),Graphics()->ScreenHeight());
+
+	if(time_get()-LastSnap > time_freq())
+	{
+		LastSnap = time_get();
+		Prev = Current;
+		net_stats(&Current);
+	}
+
+	/*
+		eth = 14
+		ip = 20
+		udp = 8
+		total = 42
+	*/
+	FrameTimeAvg = FrameTimeAvg*0.9f + m_FrameTime*0.1f;
+	str_format(aBuffer, sizeof(aBuffer), "ticks: %8d %8d mem %dk %d  gfxmem: %dk  fps: %3d",
+		m_CurGameTick, m_PredTick,
+		mem_stats()->allocated/1024,
+		mem_stats()->total_allocations,
+		Graphics()->MemoryUsage()/1024,
+		(int)(1.0f/FrameTimeAvg));
+	Graphics()->QuadsText(2, 2, 16, 1,1,1,1, aBuffer);
+
+
+	{
+		int SendPackets = (Current.sent_packets-Prev.sent_packets);
+		int SendBytes = (Current.sent_bytes-Prev.sent_bytes);
+		int SendTotal = SendBytes + SendPackets*42;
+		int RecvPackets = (Current.recv_packets-Prev.recv_packets);
+		int RecvBytes = (Current.recv_bytes-Prev.recv_bytes);
+		int RecvTotal = RecvBytes + RecvPackets*42;
+
+		if(!SendPackets) SendPackets++;
+		if(!RecvPackets) RecvPackets++;
+		str_format(aBuffer, sizeof(aBuffer), "send: %3d %5d+%4d=%5d (%3d kbps) avg: %5d\nrecv: %3d %5d+%4d=%5d (%3d kbps) avg: %5d",
+			SendPackets, SendBytes, SendPackets*42, SendTotal, (SendTotal*8)/1024, SendBytes/SendPackets,
+			RecvPackets, RecvBytes, RecvPackets*42, RecvTotal, (RecvTotal*8)/1024, RecvBytes/RecvPackets);
+		Graphics()->QuadsText(2, 14, 16, 1,1,1,1, aBuffer);
+	}
+
+	// render rates
+	{
+		int y = 0;
+		int i;
+		for(i = 0; i < 256; i++)
+		{
+			if(m_SnapshotDelta.GetDataRate(i))
+			{
+				str_format(aBuffer, sizeof(aBuffer), "%4d %20s: %8d %8d %8d", i, GameClient()->GetItemName(i), m_SnapshotDelta.GetDataRate(i)/8, m_SnapshotDelta.GetDataUpdates(i),
+					(m_SnapshotDelta.GetDataRate(i)/m_SnapshotDelta.GetDataUpdates(i))/8);
+				Graphics()->QuadsText(2, 100+y*12, 16, 1,1,1,1, aBuffer);
+				y++;
+			}
+		}
+	}
+
+	str_format(aBuffer, sizeof(aBuffer), "pred: %d ms",
+		(int)((m_PredictedTime.Get(Now)-m_GameTime.Get(Now))*1000/(float)time_freq()));
+	Graphics()->QuadsText(2, 70, 16, 1,1,1,1, aBuffer);
+
+	// render graphs
+	if(g_Config.m_DbgGraphs)
+	{
+		//Graphics()->MapScreen(0,0,400.0f,300.0f);
+		float w = Graphics()->ScreenWidth()/4.0f;
+		float h = Graphics()->ScreenHeight()/6.0f;
+		float sp = Graphics()->ScreenWidth()/100.0f;
+		float x = Graphics()->ScreenWidth()-w-sp;
+
+		m_FpsGraph.ScaleMax();
+		m_FpsGraph.ScaleMin();
+		m_FpsGraph.Render(Graphics(), m_DebugFont, x, sp*5, w, h, "FPS");
+		m_InputtimeMarginGraph.Render(Graphics(), m_DebugFont, x, sp*5+h+sp, w, h, "Prediction Margin");
+		m_GametimeMarginGraph.Render(Graphics(), m_DebugFont, x, sp*5+h+sp+h+sp, w, h, "Gametime Margin");
+	}
+}
+
+void CClient::Quit()
+{
+	SetState(IClient::STATE_QUITING);
+}
+
+const char *CClient::ErrorString()
+{
+	return m_NetClient.ErrorString();
+}
+
+void CClient::Render()
+{
+	if(g_Config.m_GfxClear)
+		Graphics()->Clear(1,1,0);
+
+	GameClient()->OnRender();
+	DebugRender();
+}
+
+const char *CClient::LoadMap(const char *pName, const char *pFilename, unsigned WantedCrc)
+{
+	static char aErrorMsg[128];
+
+	SetState(IClient::STATE_LOADING);
+
+	if(!m_pMap->Load(pFilename))
+	{
+		str_format(aErrorMsg, sizeof(aErrorMsg), "map '%s' not found", pFilename);
+		return aErrorMsg;
+	}
+
+	// get the crc of the map
+	if(m_pMap->Crc() != WantedCrc)
+	{
+		m_pMap->Unload();
+		str_format(aErrorMsg, sizeof(aErrorMsg), "map differs from the server. %08x != %08x", m_pMap->Crc(), WantedCrc);
+		return aErrorMsg;
+	}
+
+	// stop demo recording if we loaded a new map
+	m_DemoRecorder.Stop();
+
+	dbg_msg("client", "loaded map '%s'", pFilename);
+	m_RecivedSnapshots = 0;
+
+	str_copy(m_aCurrentMap, pName, sizeof(m_aCurrentMap));
+	m_CurrentMapCrc = m_pMap->Crc();
+
+	return 0x0;
+}
+
+
+
+const char *CClient::LoadMapSearch(const char *pMapName, int WantedCrc)
+{
+	const char *pError = 0;
+	char aBuf[512];
+	dbg_msg("client", "loading map, map=%s wanted crc=%08x", pMapName, WantedCrc);
+	SetState(IClient::STATE_LOADING);
+
+	// try the normal maps folder
+	str_format(aBuf, sizeof(aBuf), "maps/%s.map", pMapName);
+	pError = LoadMap(pMapName, aBuf, WantedCrc);
+	if(!pError)
+		return pError;
+
+	// try the downloaded maps
+	str_format(aBuf, sizeof(aBuf), "downloadedmaps/%s_%08x.map", pMapName, WantedCrc);
+	pError = LoadMap(pMapName, aBuf, WantedCrc);
+	return pError;
+}
+
+int CClient::PlayerScoreComp(const void *a, const void *b)
+{
+	CServerInfo::CPlayer *p0 = (CServerInfo::CPlayer *)a;
+	CServerInfo::CPlayer *p1 = (CServerInfo::CPlayer *)b;
+	if(p0->m_Score == p1->m_Score)
+		return 0;
+	if(p0->m_Score < p1->m_Score)
+		return 1;
+	return -1;
+}
+
+void CClient::ProcessPacket(CNetChunk *pPacket)
+{
+	if(pPacket->m_ClientID == -1)
+	{
+		// connectionlesss
+		if(pPacket->m_DataSize == (int)(sizeof(VERSIONSRV_VERSION) + sizeof(VERSION_DATA)) &&
+			mem_comp(pPacket->m_pData, VERSIONSRV_VERSION, sizeof(VERSIONSRV_VERSION)) == 0)
+		{
+			unsigned char *pVersionData = (unsigned char*)pPacket->m_pData + sizeof(VERSIONSRV_VERSION);
+			int VersionMatch = !mem_comp(pVersionData, VERSION_DATA, sizeof(VERSION_DATA));
+
+			dbg_msg("client/version", "version does %s (%d.%d.%d)",
+				VersionMatch ? "match" : "NOT match",
+				pVersionData[1], pVersionData[2], pVersionData[3]);
+
+			// assume version is out of date when version-data doesn't match
+			if (!VersionMatch)
+			{
+				str_format(m_aVersionStr, sizeof(m_aVersionStr), "%d.%d.%d", pVersionData[1], pVersionData[2], pVersionData[3]);
+			}
+		}
+
+		if(pPacket->m_DataSize >= (int)sizeof(SERVERBROWSE_LIST) &&
+			mem_comp(pPacket->m_pData, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST)) == 0)
+		{
+			int Size = pPacket->m_DataSize-sizeof(SERVERBROWSE_LIST);
+			int Num = Size/sizeof(MASTERSRV_ADDR);
+			MASTERSRV_ADDR *pAddrs = (MASTERSRV_ADDR *)((char*)pPacket->m_pData+sizeof(SERVERBROWSE_LIST));
+			int i;
+
+			for(i = 0; i < Num; i++)
+			{
+				NETADDR Addr;
+
+				// convert address
+				mem_zero(&Addr, sizeof(Addr));
+				Addr.type = NETTYPE_IPV4;
+				Addr.ip[0] = pAddrs[i].m_aIp[0];
+				Addr.ip[1] = pAddrs[i].m_aIp[1];
+				Addr.ip[2] = pAddrs[i].m_aIp[2];
+				Addr.ip[3] = pAddrs[i].m_aIp[3];
+				Addr.port = (pAddrs[i].m_aPort[1]<<8) | pAddrs[i].m_aPort[0];
+
+				m_ServerBrowser.Set(Addr, IServerBrowser::SET_MASTER_ADD, -1, 0x0);
+			}
+		}
+
+		{
+			int PacketType = 0;
+			if(pPacket->m_DataSize >= (int)sizeof(SERVERBROWSE_INFO) && mem_comp(pPacket->m_pData, SERVERBROWSE_INFO, sizeof(SERVERBROWSE_INFO)) == 0)
+				PacketType = 2;
+
+			if(pPacket->m_DataSize >= (int)sizeof(SERVERBROWSE_OLD_INFO) && mem_comp(pPacket->m_pData, SERVERBROWSE_OLD_INFO, sizeof(SERVERBROWSE_OLD_INFO)) == 0)
+				PacketType = 1;
+
+			if(PacketType)
+			{
+				// we got ze info
+				CUnpacker Up;
+				CServerInfo Info = {0};
+				int Token = -1;
+
+				Up.Reset((unsigned char*)pPacket->m_pData+sizeof(SERVERBROWSE_INFO), pPacket->m_DataSize-sizeof(SERVERBROWSE_INFO));
+				if(PacketType >= 2)
+					Token = str_toint(Up.GetString());
+				str_copy(Info.m_aVersion, Up.GetString(), sizeof(Info.m_aVersion));
+				str_copy(Info.m_aName, Up.GetString(), sizeof(Info.m_aName));
+				str_copy(Info.m_aMap, Up.GetString(), sizeof(Info.m_aMap));
+				str_copy(Info.m_aGameType, Up.GetString(), sizeof(Info.m_aGameType));
+				Info.m_Flags = str_toint(Up.GetString());
+				Info.m_Progression = str_toint(Up.GetString());
+				Info.m_NumPlayers = str_toint(Up.GetString());
+				Info.m_MaxPlayers = str_toint(Up.GetString());
+
+				// don't add invalid info to the server browser list
+				if(Info.m_NumPlayers > MAX_CLIENTS || Info.m_MaxPlayers > MAX_CLIENTS)
+					return;
+
+				str_format(Info.m_aAddress, sizeof(Info.m_aAddress), "%d.%d.%d.%d:%d",
+					pPacket->m_Address.ip[0], pPacket->m_Address.ip[1], pPacket->m_Address.ip[2],
+					pPacket->m_Address.ip[3], pPacket->m_Address.port);
+
+				for(int i = 0; i < Info.m_NumPlayers; i++)
+				{
+					str_copy(Info.m_aPlayers[i].m_aName, Up.GetString(), sizeof(Info.m_aPlayers[i].m_aName));
+					Info.m_aPlayers[i].m_Score = str_toint(Up.GetString());
+				}
+
+				if(!Up.Error())
+				{
+					// sort players
+					qsort(Info.m_aPlayers, Info.m_NumPlayers, sizeof(*Info.m_aPlayers), PlayerScoreComp);
+
+					if(net_addr_comp(&m_ServerAddress, &pPacket->m_Address) == 0)
+					{
+						mem_copy(&m_CurrentServerInfo, &Info, sizeof(m_CurrentServerInfo));
+						m_CurrentServerInfo.m_NetAddr = m_ServerAddress;
+						m_CurrentServerInfoRequestTime = -1;
+					}
+					else
+					{
+						if(PacketType == 2)
+							m_ServerBrowser.Set(pPacket->m_Address, IServerBrowser::SET_TOKEN, Token, &Info);
+						else
+							m_ServerBrowser.Set(pPacket->m_Address, IServerBrowser::SET_OLD_INTERNET, -1, &Info);
+					}
+				}
+			}
+		}
+	}
+	else
+	{
+		CUnpacker Unpacker;
+		Unpacker.Reset(pPacket->m_pData, pPacket->m_DataSize);
+
+		// unpack msgid and system flag
+		int Msg = Unpacker.GetInt();
+		int Sys = Msg&1;
+		Msg >>= 1;
+
+		if(Unpacker.Error())
+			return;
+
+		if(Sys)
+		{
+			// system message
+			if(Msg == NETMSG_MAP_CHANGE)
+			{
+				const char *pMap = Unpacker.GetString();
+				int MapCrc = Unpacker.GetInt();
+				const char *pError = 0;
+
+				if(Unpacker.Error())
+					return;
+
+				for(int i = 0; pMap[i]; i++) // protect the player from nasty map names
+				{
+					if(pMap[i] == '/' || pMap[i] == '\\')
+						pError = "strange character in map name";
+				}
+
+				if(pError)
+					DisconnectWithReason(pError);
+				else
+				{
+					pError = LoadMapSearch(pMap, MapCrc);
+
+					if(!pError)
+					{
+						dbg_msg("client/network", "loading done");
+						SendReady();
+						GameClient()->OnConnected();
+					}
+					else
+					{
+						str_format(m_aMapdownloadFilename, sizeof(m_aMapdownloadFilename), "downloadedmaps/%s_%08x.map", pMap, MapCrc);
+
+						dbg_msg("client/network", "starting to download map to '%s'", m_aMapdownloadFilename);
+
+						m_MapdownloadChunk = 0;
+						str_copy(m_aMapdownloadName, pMap, sizeof(m_aMapdownloadName));
+						m_MapdownloadFile = Storage()->OpenFile(m_aMapdownloadFilename, IOFLAG_WRITE);
+						m_MapdownloadCrc = MapCrc;
+						m_MapdownloadTotalsize = -1;
+						m_MapdownloadAmount = 0;
+
+						CMsgPacker Msg(NETMSG_REQUEST_MAP_DATA);
+						Msg.AddInt(m_MapdownloadChunk);
+						SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH);
+
+						if(g_Config.m_Debug)
+							dbg_msg("client/network", "requested chunk %d", m_MapdownloadChunk);
+					}
+				}
+			}
+			else if(Msg == NETMSG_MAP_DATA)
+			{
+				int Last = Unpacker.GetInt();
+				int TotalSize = Unpacker.GetInt();
+				int Size = Unpacker.GetInt();
+				const unsigned char *pData = Unpacker.GetRaw(Size);
+
+				// check fior errors
+				if(Unpacker.Error() || Size <= 0 || TotalSize <= 0 || !m_MapdownloadFile)
+					return;
+
+				io_write(m_MapdownloadFile, pData, Size);
+
+				m_MapdownloadTotalsize = TotalSize;
+				m_MapdownloadAmount += Size;
+
+				if(Last)
+				{
+					const char *pError;
+					dbg_msg("client/network", "download complete, loading map");
+
+					io_close(m_MapdownloadFile);
+					m_MapdownloadFile = 0;
+					m_MapdownloadAmount = 0;
+					m_MapdownloadTotalsize = -1;
+
+					// load map
+					pError = LoadMap(m_aMapdownloadName, m_aMapdownloadFilename, m_MapdownloadCrc);
+					if(!pError)
+					{
+						dbg_msg("client/network", "loading done");
+						SendReady();
+						GameClient()->OnConnected();
+					}
+					else
+						DisconnectWithReason(pError);
+				}
+				else
+				{
+					// request new chunk
+					m_MapdownloadChunk++;
+
+					CMsgPacker Msg(NETMSG_REQUEST_MAP_DATA);
+					Msg.AddInt(m_MapdownloadChunk);
+					SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH);
+
+					if(g_Config.m_Debug)
+						dbg_msg("client/network", "requested chunk %d", m_MapdownloadChunk);
+				}
+			}
+			else if(Msg == NETMSG_PING)
+			{
+				CMsgPacker Msg(NETMSG_PING_REPLY);
+				SendMsgEx(&Msg, 0);
+			}
+			else if(Msg == NETMSG_RCON_AUTH_STATUS)
+			{
+				int Result = Unpacker.GetInt();
+				if(Unpacker.Error() == 0)
+					m_RconAuthed = Result;
+			}
+			else if(Msg == NETMSG_RCON_LINE)
+			{
+				const char *pLine = Unpacker.GetString();
+				if(Unpacker.Error() == 0)
+				{
+					//dbg_msg("remote", "%s", line);
+					GameClient()->OnRconLine(pLine);
+				}
+			}
+			else if(Msg == NETMSG_PING_REPLY)
+				dbg_msg("client/network", "latency %.2f", (time_get() - m_PingStartTime)*1000 / (float)time_freq());
+			else if(Msg == NETMSG_INPUTTIMING)
+			{
+				int InputPredTick = Unpacker.GetInt();
+				int TimeLeft = Unpacker.GetInt();
+
+				// adjust our prediction time
+				int64 Target = 0;
+				for(int k = 0; k < 200; k++)
+				{
+					if(m_aInputs[k].m_Tick == InputPredTick)
+					{
+						Target = m_aInputs[k].m_PredictedTime + (time_get() - m_aInputs[k].m_Time);
+						Target = Target - (int64)(((TimeLeft-PREDICTION_MARGIN)/1000.0f)*time_freq());
+						//st_update(&predicted_time, );
+						break;
+					}
+				}
+
+				if(Target)
+					m_PredictedTime.Update(&m_InputtimeMarginGraph, Target, TimeLeft, 1);
+			}
+			else if(Msg == NETMSG_SNAP || Msg == NETMSG_SNAPSINGLE || Msg == NETMSG_SNAPEMPTY)
+			{
+				//dbg_msg("client/network", "got snapshot");
+				int NumParts = 1;
+				int Part = 0;
+				int GameTick = Unpacker.GetInt();
+				int DeltaTick = GameTick-Unpacker.GetInt();
+				int PartSize = 0;
+				int Crc = 0;
+				int CompleteSize = 0;
+				const char *pData = 0;
+
+				// we are not allowed to process snapshot yet
+				if(State() < IClient::STATE_LOADING)
+					return;
+
+				if(Msg == NETMSG_SNAP)
+				{
+					NumParts = Unpacker.GetInt();
+					Part = Unpacker.GetInt();
+				}
+
+				if(Msg != NETMSG_SNAPEMPTY)
+				{
+					Crc = Unpacker.GetInt();
+					PartSize = Unpacker.GetInt();
+				}
+
+				pData = (const char *)Unpacker.GetRaw(PartSize);
+
+				if(Unpacker.Error())
+					return;
+
+				if(GameTick >= m_CurrentRecvTick)
+				{
+					if(GameTick != m_CurrentRecvTick)
+					{
+						m_SnapshotParts = 0;
+						m_CurrentRecvTick = GameTick;
+					}
+
+					// TODO: clean this up abit
+					mem_copy((char*)m_aSnapshotIncommingData + Part*MAX_SNAPSHOT_PACKSIZE, pData, PartSize);
+					m_SnapshotParts |= 1<<Part;
+
+					if(m_SnapshotParts == (unsigned)((1<<NumParts)-1))
+					{
+						static CSnapshot Emptysnap;
+						CSnapshot *pDeltaShot = &Emptysnap;
+						int PurgeTick;
+						void *pDeltaData;
+						int DeltaSize;
+						unsigned char aTmpBuffer2[CSnapshot::MAX_SIZE];
+						unsigned char aTmpBuffer3[CSnapshot::MAX_SIZE];
+						int SnapSize;
+
+						CompleteSize = (NumParts-1) * MAX_SNAPSHOT_PACKSIZE + PartSize;
+
+						// reset snapshoting
+						m_SnapshotParts = 0;
+
+						// find snapshot that we should use as delta
+						Emptysnap.Clear();
+
+						// find delta
+						if(DeltaTick >= 0)
+						{
+							int DeltashotSize = m_SnapshotStorage.Get(DeltaTick, 0, &pDeltaShot, 0);
+
+							if(DeltashotSize < 0)
+							{
+								// couldn't find the delta snapshots that the server used
+								// to compress this snapshot. force the server to resync
+								if(g_Config.m_Debug)
+									dbg_msg("client", "error, couldn't find the delta snapshot");
+
+								// ack snapshot
+								// TODO: combine this with the input message
+								m_AckGameTick = -1;
+								return;
+							}
+						}
+
+						// decompress snapshot
+						pDeltaData = m_SnapshotDelta.EmptyDelta();
+						DeltaSize = sizeof(int)*3;
+
+						if(CompleteSize)
+						{
+							int IntSize = CVariableInt::Decompress(m_aSnapshotIncommingData, CompleteSize, aTmpBuffer2);
+
+							if(IntSize < 0) // failure during decompression, bail
+								return;
+
+							pDeltaData = aTmpBuffer2;
+							DeltaSize = IntSize;
+						}
+
+						// unpack delta
+						PurgeTick = DeltaTick;
+						SnapSize = m_SnapshotDelta.UnpackDelta(pDeltaShot, (CSnapshot*)aTmpBuffer3, pDeltaData, DeltaSize);
+						if(SnapSize < 0)
+						{
+							dbg_msg("client", "delta unpack failed!");
+							return;
+						}
+
+						if(Msg != NETMSG_SNAPEMPTY && ((CSnapshot*)aTmpBuffer3)->Crc() != Crc)
+						{
+							if(g_Config.m_Debug)
+							{
+								dbg_msg("client", "snapshot crc error #%d - tick=%d wantedcrc=%d gotcrc=%d compressed_size=%d delta_tick=%d",
+									m_SnapCrcErrors, GameTick, Crc, ((CSnapshot*)aTmpBuffer3)->Crc(), CompleteSize, DeltaTick);
+							}
+
+							m_SnapCrcErrors++;
+							if(m_SnapCrcErrors > 10)
+							{
+								// to many errors, send reset
+								m_AckGameTick = -1;
+								SendInput();
+								m_SnapCrcErrors = 0;
+							}
+							return;
+						}
+						else
+						{
+							if(m_SnapCrcErrors)
+								m_SnapCrcErrors--;
+						}
+
+						// purge old snapshots
+						PurgeTick = DeltaTick;
+						if(m_aSnapshots[SNAP_PREV] && m_aSnapshots[SNAP_PREV]->m_Tick < PurgeTick)
+							PurgeTick = m_aSnapshots[SNAP_PREV]->m_Tick;
+						if(m_aSnapshots[SNAP_CURRENT] && m_aSnapshots[SNAP_CURRENT]->m_Tick < PurgeTick)
+							PurgeTick = m_aSnapshots[SNAP_PREV]->m_Tick;
+						m_SnapshotStorage.PurgeUntil(PurgeTick);
+
+						// add new
+						m_SnapshotStorage.Add(GameTick, time_get(), SnapSize, (CSnapshot*)aTmpBuffer3, 1);
+
+						// add snapshot to demo
+						if(m_DemoRecorder.IsRecording())
+						{
+
+							// write tick marker
+							/*
+							DEMOREC_TICKMARKER marker;
+							marker.tick = game_tick;
+							swap_endian(&marker, sizeof(int), sizeof(marker)/sizeof(int));
+							demorec_record_write("TICK", sizeof(marker), &marker);
+							demorec_record_write("SNAP", snapsize, tmpbuffer3);
+							*/
+
+							// write snapshot
+							m_DemoRecorder.RecordSnapshot(GameTick, aTmpBuffer3, SnapSize);
+						}
+
+						// apply snapshot, cycle pointers
+						m_RecivedSnapshots++;
+
+						m_CurrentRecvTick = GameTick;
+
+						// we got two snapshots until we see us self as connected
+						if(m_RecivedSnapshots == 2)
+						{
+							// start at 200ms and work from there
+							m_PredictedTime.Init(GameTick*time_freq()/50);
+							m_PredictedTime.SetAdjustSpeed(1, 1000.0f);
+							m_GameTime.Init((GameTick-1)*time_freq()/50);
+							m_aSnapshots[SNAP_PREV] = m_SnapshotStorage.m_pFirst;
+							m_aSnapshots[SNAP_CURRENT] = m_SnapshotStorage.m_pLast;
+							m_LocalStartTime = time_get();
+							SetState(IClient::STATE_ONLINE);
+						}
+
+						// adjust game time
+						{
+							int64 Now = m_GameTime.Get(time_get());
+							int64 TickStart = GameTick*time_freq()/50;
+							int64 TimeLeft = (TickStart-Now)*1000 / time_freq();
+							//st_update(&game_time, (game_tick-1)*time_freq()/50);
+							m_GameTime.Update(&m_GametimeMarginGraph, (GameTick-1)*time_freq()/50, TimeLeft, 0);
+						}
+
+						// ack snapshot
+						m_AckGameTick = GameTick;
+					}
+				}
+			}
+		}
+		else
+		{
+			// game message
+			if(m_DemoRecorder.IsRecording())
+				m_DemoRecorder.RecordMessage(pPacket->m_pData, pPacket->m_DataSize);
+				// demorec_record_write("MESG", pPacket->data_size, );
+
+			GameClient()->OnMessage(Msg, &Unpacker);
+		}
+	}
+}
+
+void CClient::PumpNetwork()
+{
+	m_NetClient.Update();
+
+	if(State() != IClient::STATE_DEMOPLAYBACK)
+	{
+		// check for errors
+		if(State() != IClient::STATE_OFFLINE && m_NetClient.State() == NETSTATE_OFFLINE)
+		{
+			SetState(IClient::STATE_OFFLINE);
+			Disconnect();
+			dbg_msg("client", "offline error='%s'", m_NetClient.ErrorString());
+		}
+
+		//
+		if(State() == IClient::STATE_CONNECTING && m_NetClient.State() == NETSTATE_ONLINE)
+		{
+			// we switched to online
+			dbg_msg("client", "connected, sending info");
+			SetState(IClient::STATE_LOADING);
+			SendInfo();
+		}
+	}
+
+	// process packets
+	CNetChunk Packet;
+	while(m_NetClient.Recv(&Packet))
+		ProcessPacket(&Packet);
+}
+
+void CClient::OnDemoPlayerSnapshot(void *pData, int Size)
+{
+	// update ticks, they could have changed
+	const CDemoPlayer::CPlaybackInfo *pInfo = m_DemoPlayer.Info();
+	CSnapshotStorage::CHolder *pTemp;
+	m_CurGameTick = pInfo->m_Info.m_CurrentTick;
+	m_PrevGameTick = pInfo->m_PreviousTick;
+
+	// handle snapshots
+	pTemp = m_aSnapshots[SNAP_PREV];
+	m_aSnapshots[SNAP_PREV] = m_aSnapshots[SNAP_CURRENT];
+	m_aSnapshots[SNAP_CURRENT] = pTemp;
+
+	mem_copy(m_aSnapshots[SNAP_CURRENT]->m_pSnap, pData, Size);
+	mem_copy(m_aSnapshots[SNAP_CURRENT]->m_pAltSnap, pData, Size);
+
+	GameClient()->OnNewSnapshot();
+}
+
+void CClient::OnDemoPlayerMessage(void *pData, int Size)
+{
+	CUnpacker Unpacker;
+	Unpacker.Reset(pData, Size);
+
+	// unpack msgid and system flag
+	int Msg = Unpacker.GetInt();
+	int Sys = Msg&1;
+	Msg >>= 1;
+
+	if(Unpacker.Error())
+		return;
+
+	if(!Sys)
+		GameClient()->OnMessage(Msg, &Unpacker);
+}
+/*
+const IDemoPlayer::CInfo *client_demoplayer_getinfo()
+{
+	static DEMOPLAYBACK_INFO ret;
+	const DEMOREC_PLAYBACKINFO *info = m_DemoPlayer.Info();
+	ret.first_tick = info->first_tick;
+	ret.last_tick = info->last_tick;
+	ret.current_tick = info->current_tick;
+	ret.paused = info->paused;
+	ret.speed = info->speed;
+	return &ret;
+}*/
+
+/*
+void DemoPlayer()->SetPos(float percent)
+{
+	demorec_playback_set(percent);
+}
+
+void DemoPlayer()->SetSpeed(float speed)
+{
+	demorec_playback_setspeed(speed);
+}
+
+void DemoPlayer()->SetPause(int paused)
+{
+	if(paused)
+		demorec_playback_pause();
+	else
+		demorec_playback_unpause();
+}*/
+
+void CClient::Update()
+{
+	if(State() == IClient::STATE_DEMOPLAYBACK)
+	{
+		m_DemoPlayer.Update();
+		if(m_DemoPlayer.IsPlaying())
+		{
+			// update timers
+			const CDemoPlayer::CPlaybackInfo *pInfo = m_DemoPlayer.Info();
+			m_CurGameTick = pInfo->m_Info.m_CurrentTick;
+			m_PrevGameTick = pInfo->m_PreviousTick;
+			m_GameIntraTick = pInfo->m_IntraTick;
+			m_GameTickTime = pInfo->m_TickTime;
+		}
+		else
+		{
+			// disconnect on error
+			Disconnect();
+		}
+	}
+	else if(State() != IClient::STATE_OFFLINE && m_RecivedSnapshots >= 3)
+	{
+		// switch snapshot
+		int Repredict = 0;
+		int64 Freq = time_freq();
+		int64 Now = m_GameTime.Get(time_get());
+		int64 PredNow = m_PredictedTime.Get(time_get());
+
+		while(1)
+		{
+			CSnapshotStorage::CHolder *pCur = m_aSnapshots[SNAP_CURRENT];
+			int64 TickStart = (pCur->m_Tick)*time_freq()/50;
+
+			if(TickStart < Now)
+			{
+				CSnapshotStorage::CHolder *pNext = m_aSnapshots[SNAP_CURRENT]->m_pNext;
+				if(pNext)
+				{
+					m_aSnapshots[SNAP_PREV] = m_aSnapshots[SNAP_CURRENT];
+					m_aSnapshots[SNAP_CURRENT] = pNext;
+
+					// set ticks
+					m_CurGameTick = m_aSnapshots[SNAP_CURRENT]->m_Tick;
+					m_PrevGameTick = m_aSnapshots[SNAP_PREV]->m_Tick;
+
+					if(m_aSnapshots[SNAP_CURRENT] && m_aSnapshots[SNAP_PREV])
+					{
+						GameClient()->OnNewSnapshot();
+						Repredict = 1;
+					}
+				}
+				else
+					break;
+			}
+			else
+				break;
+		}
+
+		if(m_aSnapshots[SNAP_CURRENT] && m_aSnapshots[SNAP_PREV])
+		{
+			int64 CurtickStart = (m_aSnapshots[SNAP_CURRENT]->m_Tick)*time_freq()/50;
+			int64 PrevtickStart = (m_aSnapshots[SNAP_PREV]->m_Tick)*time_freq()/50;
+			//tg_add(&predicted_time_graph, pred_now, 0);
+			int PrevPredTick = (int)(PredNow*50/time_freq());
+			int NewPredTick = PrevPredTick+1;
+			static float LastPredintra = 0;
+
+			m_GameIntraTick = (Now - PrevtickStart) / (float)(CurtickStart-PrevtickStart);
+			m_GameTickTime = (Now - PrevtickStart) / (float)Freq; //(float)SERVER_TICK_SPEED);
+
+			CurtickStart = NewPredTick*time_freq()/50;
+			PrevtickStart = PrevPredTick*time_freq()/50;
+			m_PredIntraTick = (PredNow - PrevtickStart) / (float)(CurtickStart-PrevtickStart);
+
+			if(NewPredTick < m_aSnapshots[SNAP_PREV]->m_Tick-SERVER_TICK_SPEED || NewPredTick > m_aSnapshots[SNAP_PREV]->m_Tick+SERVER_TICK_SPEED)
+			{
+				dbg_msg("client", "prediction time reset!");
+				m_PredictedTime.Init(m_aSnapshots[SNAP_CURRENT]->m_Tick*time_freq()/50);
+			}
+
+			if(NewPredTick > m_PredTick)
+			{
+				LastPredintra = m_PredIntraTick;
+				m_PredTick = NewPredTick;
+				Repredict = 1;
+
+				// send input
+				SendInput();
+			}
+
+			LastPredintra = m_PredIntraTick;
+		}
+
+		// only do sane predictions
+		if(Repredict)
+		{
+			if(m_PredTick > m_CurGameTick && m_PredTick < m_CurGameTick+50)
+				GameClient()->OnPredict();
+		}
+
+		// fetch server info if we don't have it
+		if(State() >= IClient::STATE_LOADING &&
+			m_CurrentServerInfoRequestTime >= 0 &&
+			time_get() > m_CurrentServerInfoRequestTime)
+		{
+			m_ServerBrowser.Request(m_ServerAddress);
+			m_CurrentServerInfoRequestTime = time_get()+time_freq()*2;
+		}
+	}
+
+	// STRESS TEST: join the server again
+	if(g_Config.m_DbgStress)
+	{
+		static int64 ActionTaken = 0;
+		int64 Now = time_get();
+		if(State() == IClient::STATE_OFFLINE)
+		{
+			if(Now > ActionTaken+time_freq()*2)
+			{
+				dbg_msg("stress", "reconnecting!");
+				Connect(g_Config.m_DbgStressServer);
+				ActionTaken = Now;
+			}
+		}
+		else
+		{
+			/*if(now > action_taken+time_freq()*(10+config.dbg_stress))
+			{
+				dbg_msg("stress", "disconnecting!");
+				Disconnect();
+				action_taken = now;
+			}*/
+		}
+	}
+
+	// pump the network
+	PumpNetwork();
+
+	// update the maser server registry
+	MasterServer()->Update();
+
+	// update the server browser
+	m_ServerBrowser.Update();
+}
+
+const char *CClient::UserDirectory()
+{
+	static char saPath[1024] = {0};
+	fs_storage_path("Teeworlds", saPath, sizeof(saPath));
+	return saPath;
+}
+
+void CClient::VersionUpdate()
+{
+	if(m_VersionInfo.m_State == 0)
+	{
+		m_Engine.HostLookup(&m_VersionInfo.m_VersionServeraddr, g_Config.m_ClVersionServer);
+		m_VersionInfo.m_State++;
+	}
+	else if(m_VersionInfo.m_State == 1)
+	{
+		if(m_VersionInfo.m_VersionServeraddr.m_Job.Status() == CJob::STATE_DONE)
+		{
+			CNetChunk Packet;
+
+			mem_zero(&Packet, sizeof(Packet));
+
+			m_VersionInfo.m_VersionServeraddr.m_Addr.port = VERSIONSRV_PORT;
+
+			Packet.m_ClientID = -1;
+			Packet.m_Address = m_VersionInfo.m_VersionServeraddr.m_Addr;
+			Packet.m_pData = VERSIONSRV_GETVERSION;
+			Packet.m_DataSize = sizeof(VERSIONSRV_GETVERSION);
+			Packet.m_Flags = NETSENDFLAG_CONNLESS;
+
+			m_NetClient.Send(&Packet);
+			m_VersionInfo.m_State++;
+		}
+	}
+}
+
+void CClient::InitEngine(const char *pAppname)
+{
+	m_Engine.Init(pAppname);
+}
+
+void CClient::RegisterInterfaces()
+{
+	Kernel()->RegisterInterface(static_cast<IDemoPlayer*>(&m_DemoPlayer));
+	Kernel()->RegisterInterface(static_cast<IServerBrowser*>(&m_ServerBrowser));
+}
+
+void CClient::InitInterfaces()
+{
+	// fetch interfaces
+	m_pEditor = Kernel()->RequestInterface<IEditor>();
+	m_pGraphics = Kernel()->RequestInterface<IEngineGraphics>();
+	m_pSound = Kernel()->RequestInterface<IEngineSound>();
+	m_pGameClient = Kernel()->RequestInterface<IGameClient>();
+	m_pInput = Kernel()->RequestInterface<IEngineInput>();
+	m_pMap = Kernel()->RequestInterface<IEngineMap>();
+	m_pMasterServer = Kernel()->RequestInterface<IEngineMasterServer>();
+	m_pStorage = Kernel()->RequestInterface<IStorage>();
+
+	//
+	m_ServerBrowser.SetBaseInfo(&m_NetClient, m_pGameClient->NetVersion());
+}
+
+void CClient::Run()
+{
+	int64 ReportTime = time_get();
+	int64 ReportInterval = time_freq()*1;
+
+	m_LocalStartTime = time_get();
+	m_SnapshotParts = 0;
+
+	// init graphics
+	if(m_pGraphics->Init() != 0)
+		return;
+
+	// init font rendering
+	Kernel()->RequestInterface<IEngineTextRender>()->Init();
+
+	// init the input
+	Input()->Init();
+
+	// start refreshing addresses while we load
+	MasterServer()->RefreshAddresses();
+
+	// init the editor
+	m_pEditor->Init();
+
+	// init sound, allowed to fail
+	Sound()->Init();
+
+	// load data
+	if(!LoadData())
+		return;
+
+	GameClient()->OnInit();
+	dbg_msg("client", "version %s", GameClient()->NetVersion());
+
+	// open socket
+	{
+		NETADDR BindAddr;
+		mem_zero(&BindAddr, sizeof(BindAddr));
+		m_NetClient.Open(BindAddr, 0);
+	}
+
+	// connect to the server if wanted
+	/*
+	if(config.cl_connect[0] != 0)
+		Connect(config.cl_connect);
+	config.cl_connect[0] = 0;
+	*/
+
+	//
+	m_FpsGraph.Init(0.0f, 200.0f);
+
+	// never start with the editor
+	g_Config.m_ClEditor = 0;
+
+	Input()->MouseModeRelative();
+
+	while (1)
+	{
+		int64 FrameStartTime = time_get();
+		m_Frames++;
+
+		//
+		VersionUpdate();
+
+		// handle pending connects
+		if(m_aCmdConnect[0])
+		{
+			str_copy(g_Config.m_UiServerAddress, m_aCmdConnect, sizeof(g_Config.m_UiServerAddress));
+			Connect(m_aCmdConnect);
+			m_aCmdConnect[0] = 0;
+		}
+
+		// update input
+		Input()->Update();
+
+		// update sound
+		Sound()->Update();
+
+		// release focus
+		if(!m_pGraphics->WindowActive())
+		{
+			if(m_WindowMustRefocus == 0)
+				Input()->MouseModeAbsolute();
+			m_WindowMustRefocus = 1;
+		}
+		else if (g_Config.m_DbgFocus && Input()->KeyPressed(KEY_ESCAPE))
+		{
+			Input()->MouseModeAbsolute();
+			m_WindowMustRefocus = 1;
+		}
+
+		// refocus
+		if(m_WindowMustRefocus && m_pGraphics->WindowActive())
+		{
+			if(m_WindowMustRefocus < 3)
+			{
+				Input()->MouseModeAbsolute();
+				m_WindowMustRefocus++;
+			}
+
+			if(Input()->KeyPressed(KEY_MOUSE_1))
+			{
+				Input()->MouseModeRelative();
+				m_WindowMustRefocus = 0;
+			}
+		}
+
+		// panic quit button
+		if(Input()->KeyPressed(KEY_LCTRL) && Input()->KeyPressed(KEY_LSHIFT) && Input()->KeyPressed('q'))
+			break;
+
+		if(Input()->KeyPressed(KEY_LCTRL) && Input()->KeyPressed(KEY_LSHIFT) && Input()->KeyDown('d'))
+			g_Config.m_Debug ^= 1;
+
+		if(Input()->KeyPressed(KEY_LCTRL) && Input()->KeyPressed(KEY_LSHIFT) && Input()->KeyDown('g'))
+			g_Config.m_DbgGraphs ^= 1;
+
+		if(Input()->KeyPressed(KEY_LCTRL) && Input()->KeyPressed(KEY_LSHIFT) && Input()->KeyDown('e'))
+		{
+			g_Config.m_ClEditor = g_Config.m_ClEditor^1;
+			Input()->MouseModeRelative();
+		}
+
+		/*
+		if(!gfx_window_open())
+			break;
+		*/
+
+		// render
+		if(g_Config.m_ClEditor)
+		{
+			Update();
+			m_pEditor->UpdateAndRender();
+			m_pGraphics->Swap();
+		}
+		else
+		{
+			Update();
+
+			if(g_Config.m_DbgStress)
+			{
+				if((m_Frames%10) == 0)
+				{
+					Render();
+					m_pGraphics->Swap();
+				}
+			}
+			else
+			{
+				Render();
+				m_pGraphics->Swap();
+			}
+		}
+
+		// check conditions
+		if(State() == IClient::STATE_QUITING)
+			break;
+
+		// beNice
+		if(g_Config.m_DbgStress)
+			thread_sleep(5);
+		else if(g_Config.m_ClCpuThrottle || !m_pGraphics->WindowActive())
+			thread_sleep(1);
+
+		if(g_Config.m_DbgHitch)
+		{
+			thread_sleep(g_Config.m_DbgHitch);
+			g_Config.m_DbgHitch = 0;
+		}
+
+		if(ReportTime < time_get())
+		{
+			if(0 && g_Config.m_Debug)
+			{
+				dbg_msg("client/report", "fps=%.02f (%.02f %.02f) netstate=%d",
+					m_Frames/(float)(ReportInterval/time_freq()),
+					1.0f/m_FrameTimeHigh,
+					1.0f/m_FrameTimeLow,
+					m_NetClient.State());
+			}
+			m_FrameTimeLow = 1;
+			m_FrameTimeHigh = 0;
+			m_Frames = 0;
+			ReportTime += ReportInterval;
+		}
+
+		// update frametime
+		m_FrameTime = (time_get()-FrameStartTime)/(float)time_freq();
+		if(m_FrameTime < m_FrameTimeLow)
+			m_FrameTimeLow = m_FrameTime;
+		if(m_FrameTime > m_FrameTimeHigh)
+			m_FrameTimeHigh = m_FrameTime;
+
+		m_LocalTime = (time_get()-m_LocalStartTime)/(float)time_freq();
+
+		m_FpsGraph.Add(1.0f/m_FrameTime, 1,1,1);
+	}
+
+	GameClient()->OnShutdown();
+	Disconnect();
+
+	m_pGraphics->Shutdown();
+	m_pSound->Shutdown();
+}
+
+
+void CClient::Con_Connect(IConsole::IResult *pResult, void *pUserData)
+{
+	CClient *pSelf = (CClient *)pUserData;
+	str_copy(pSelf->m_aCmdConnect, pResult->GetString(0), sizeof(pSelf->m_aCmdConnect));
+}
+
+void CClient::Con_Disconnect(IConsole::IResult *pResult, void *pUserData)
+{
+	CClient *pSelf = (CClient *)pUserData;
+	pSelf->Disconnect();
+}
+
+void CClient::Con_Quit(IConsole::IResult *pResult, void *pUserData)
+{
+	CClient *pSelf = (CClient *)pUserData;
+	pSelf->Quit();
+}
+
+void CClient::Con_Minimize(IConsole::IResult *pResult, void *pUserData)
+{
+	CClient *pSelf = (CClient *)pUserData;
+	pSelf->Graphics()->Minimize();
+}
+
+void CClient::Con_Ping(IConsole::IResult *pResult, void *pUserData)
+{
+	CClient *pSelf = (CClient *)pUserData;
+
+	CMsgPacker Msg(NETMSG_PING);
+	pSelf->SendMsgEx(&Msg, 0);
+	pSelf->m_PingStartTime = time_get();
+}
+
+void CClient::Con_Screenshot(IConsole::IResult *pResult, void *pUserData)
+{
+	CClient *pSelf = (CClient *)pUserData;
+	pSelf->Graphics()->TakeScreenshot();
+}
+
+void CClient::Con_Rcon(IConsole::IResult *pResult, void *pUserData)
+{
+	CClient *pSelf = (CClient *)pUserData;
+	pSelf->Rcon(pResult->GetString(0));
+}
+
+void CClient::Con_RconAuth(IConsole::IResult *pResult, void *pUserData)
+{
+	CClient *pSelf = (CClient *)pUserData;
+	pSelf->RconAuth("", pResult->GetString(0));
+}
+
+void CClient::Con_AddFavorite(IConsole::IResult *pResult, void *pUserData)
+{
+	CClient *pSelf = (CClient *)pUserData;
+	NETADDR Addr;
+	if(net_addr_from_str(&Addr, pResult->GetString(0)) == 0)
+		pSelf->m_ServerBrowser.AddFavorite(Addr);
+}
+
+const char *CClient::DemoPlayer_Play(const char *pFilename)
+{
+	int Crc;
+	const char *pError;
+	Disconnect();
+	m_NetClient.ResetErrorString();
+
+	// try to start playback
+	m_DemoPlayer.SetListner(this);
+
+	if(m_DemoPlayer.Load(Storage(), pFilename))
+		return "error loading demo";
+
+	// load map
+	Crc = (m_DemoPlayer.Info()->m_Header.m_aCrc[0]<<24)|
+		(m_DemoPlayer.Info()->m_Header.m_aCrc[1]<<16)|
+		(m_DemoPlayer.Info()->m_Header.m_aCrc[2]<<8)|
+		(m_DemoPlayer.Info()->m_Header.m_aCrc[3]);
+	pError = LoadMapSearch(m_DemoPlayer.Info()->m_Header.m_aMap, Crc);
+	if(pError)
+	{
+		DisconnectWithReason(pError);
+		return pError;
+	}
+
+	GameClient()->OnConnected();
+
+	// setup buffers
+	mem_zero(m_aDemorecSnapshotData, sizeof(m_aDemorecSnapshotData));
+
+	m_aSnapshots[SNAP_CURRENT] = &m_aDemorecSnapshotHolders[SNAP_CURRENT];
+	m_aSnapshots[SNAP_PREV] = &m_aDemorecSnapshotHolders[SNAP_PREV];
+
+	m_aSnapshots[SNAP_CURRENT]->m_pSnap = (CSnapshot *)m_aDemorecSnapshotData[SNAP_CURRENT][0];
+	m_aSnapshots[SNAP_CURRENT]->m_pAltSnap = (CSnapshot *)m_aDemorecSnapshotData[SNAP_CURRENT][1];
+	m_aSnapshots[SNAP_CURRENT]->m_SnapSize = 0;
+	m_aSnapshots[SNAP_CURRENT]->m_Tick = -1;
+
+	m_aSnapshots[SNAP_PREV]->m_pSnap = (CSnapshot *)m_aDemorecSnapshotData[SNAP_PREV][0];
+	m_aSnapshots[SNAP_PREV]->m_pAltSnap = (CSnapshot *)m_aDemorecSnapshotData[SNAP_PREV][1];
+	m_aSnapshots[SNAP_PREV]->m_SnapSize = 0;
+	m_aSnapshots[SNAP_PREV]->m_Tick = -1;
+
+	// enter demo playback state
+	SetState(IClient::STATE_DEMOPLAYBACK);
+
+	m_DemoPlayer.Play();
+	GameClient()->OnEnterGame();
+
+	return 0;
+}
+
+void CClient::Con_Play(IConsole::IResult *pResult, void *pUserData)
+{
+	CClient *pSelf = (CClient *)pUserData;
+	pSelf->DemoPlayer_Play(pResult->GetString(0));
+}
+
+void CClient::Con_Record(IConsole::IResult *pResult, void *pUserData)
+{
+	CClient *pSelf = (CClient *)pUserData;
+	if(pSelf->State() != IClient::STATE_ONLINE)
+		dbg_msg("demorec/record", "client is not online");
+	else
+	{
+		char aFilename[512];
+		str_format(aFilename, sizeof(aFilename), "demos/%s.demo", pResult->GetString(0));
+		pSelf->m_DemoRecorder.Start(pSelf->Storage(), aFilename, pSelf->GameClient()->NetVersion(), pSelf->m_aCurrentMap, pSelf->m_CurrentMapCrc, "client");
+	}
+}
+
+void CClient::Con_StopRecord(IConsole::IResult *pResult, void *pUserData)
+{
+	CClient *pSelf = (CClient *)pUserData;
+	pSelf->m_DemoRecorder.Stop();
+}
+
+void CClient::Con_ServerDummy(IConsole::IResult *pResult, void *pUserData)
+{
+	dbg_msg("client", "this command is not available on the client");
+}
+
+void CClient::RegisterCommands()
+{
+	m_pConsole = Kernel()->RequestInterface<IConsole>();
+	// register server dummy commands for tab completion
+	m_pConsole->Register("kick", "i", CFGFLAG_SERVER, Con_ServerDummy, this, "Kick player with specified id");
+	m_pConsole->Register("ban", "s?i", CFGFLAG_SERVER, Con_ServerDummy, this, "Ban player with ip/id for x minutes");
+	m_pConsole->Register("unban", "s", CFGFLAG_SERVER, Con_ServerDummy, this, "Unban ip");
+	m_pConsole->Register("bans", "", CFGFLAG_SERVER, Con_ServerDummy, this, "Show banlist");
+	m_pConsole->Register("status", "", CFGFLAG_SERVER, Con_ServerDummy, this, "List players");
+	m_pConsole->Register("shutdown", "", CFGFLAG_SERVER, Con_ServerDummy, this, "Shut down");
+	m_pConsole->Register("record", "s", CFGFLAG_SERVER, Con_ServerDummy, this, "Record to a file");
+	m_pConsole->Register("stoprecord", "", CFGFLAG_SERVER, Con_ServerDummy, this, "Stop recording");
+
+	m_pConsole->Register("quit", "", CFGFLAG_CLIENT, Con_Quit, this, "Quit Teeworlds");
+	m_pConsole->Register("exit", "", CFGFLAG_CLIENT, Con_Quit, this, "Quit Teeworlds");
+	m_pConsole->Register("minimize", "", CFGFLAG_CLIENT, Con_Minimize, this, "Minimize Teeworlds");
+	m_pConsole->Register("connect", "s", CFGFLAG_CLIENT, Con_Connect, this, "Connect to the specified host/ip");
+	m_pConsole->Register("disconnect", "", CFGFLAG_CLIENT, Con_Disconnect, this, "Disconnect from the server");
+	m_pConsole->Register("ping", "", CFGFLAG_CLIENT, Con_Ping, this, "Ping the current server");
+	m_pConsole->Register("screenshot", "", CFGFLAG_CLIENT, Con_Screenshot, this, "Take a screenshot");
+	m_pConsole->Register("rcon", "r", CFGFLAG_CLIENT, Con_Rcon, this, "Send specified command to rcon");
+	m_pConsole->Register("rcon_auth", "s", CFGFLAG_CLIENT, Con_RconAuth, this, "Authenticate to rcon");
+	m_pConsole->Register("play", "r", CFGFLAG_CLIENT, Con_Play, this, "Play the file specified");
+	m_pConsole->Register("record", "s", CFGFLAG_CLIENT, Con_Record, this, "Record to the file");
+	m_pConsole->Register("stoprecord", "", CFGFLAG_CLIENT, Con_StopRecord, this, "Stop recording");
+
+	m_pConsole->Register("add_favorite", "s", CFGFLAG_CLIENT, Con_AddFavorite, this, "Add a server as a favorite");
+}
+
+static CClient m_Client;
+
+/*
+	Server Time
+	Client Mirror Time
+	Client Predicted Time
+
+	Snapshot Latency
+		Downstream latency
+
+	Prediction Latency
+		Upstream latency
+*/
+
+#if defined(CONF_PLATFORM_MACOSX)
+int SDL_main(int argc, const char **argv) // ignore_convention
+#else
+int main(int argc, const char **argv) // ignore_convention
+#endif
+{
+	// init the engine
+	dbg_msg("client", "starting...");
+	m_Client.InitEngine("Teeworlds");
+
+	IKernel *pKernel = IKernel::Create();
+	pKernel->RegisterInterface(&m_Client);
+	m_Client.RegisterInterfaces();
+
+	// create the components
+	IConsole *pConsole = CreateConsole();
+	IStorage *pStorage = CreateStorage("Teeworlds", argv[0]); // ignore_convention
+	IConfig *pConfig = CreateConfig();
+	IEngineGraphics *pEngineGraphics = CreateEngineGraphics();
+	IEngineSound *pEngineSound = CreateEngineSound();
+	IEngineInput *pEngineInput = CreateEngineInput();
+	IEngineTextRender *pEngineTextRender = CreateEngineTextRender();
+	IEngineMap *pEngineMap = CreateEngineMap();
+	IEngineMasterServer *pEngineMasterServer = CreateEngineMasterServer();
+
+	{
+		bool RegisterFail = false;
+
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IConsole*>(pConsole));
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IConfig*>(pConfig));
+
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IEngineGraphics*>(pEngineGraphics)); // register graphics as both
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IGraphics*>(pEngineGraphics));
+
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IEngineSound*>(pEngineSound)); // register as both
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<ISound*>(pEngineSound));
+
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IEngineInput*>(pEngineInput)); // register as both
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IInput*>(pEngineInput));
+
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IEngineTextRender*>(pEngineTextRender)); // register as both
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<ITextRender*>(pEngineTextRender));
+
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IEngineMap*>(pEngineMap)); // register as both
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IMap*>(pEngineMap));
+
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IEngineMasterServer*>(pEngineMasterServer)); // register as both
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IMasterServer*>(pEngineMasterServer));
+
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(CreateEditor());
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(CreateGameClient());
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(pStorage);
+
+		if(RegisterFail)
+			return -1;
+	}
+
+	pConfig->Init();
+	pEngineMasterServer->Init(m_Client.Engine());
+	pEngineMasterServer->Load();
+
+	// register all console commands
+	m_Client.RegisterCommands();
+
+	pKernel->RequestInterface<IGameClient>()->OnConsoleInit();
+
+	// init client's interfaces
+	m_Client.InitInterfaces();
+
+	// execute autoexec file
+	pConsole->ExecuteFile("autoexec.cfg");
+
+	// parse the command line arguments
+	if(argc > 1) // ignore_convention
+		pConsole->ParseArguments(argc-1, &argv[1]); // ignore_convention
+
+	// execute config file
+	pConsole->ExecuteFile("settings.cfg");
+
+	// run the client
+	m_Client.Run();
+
+	// write down the config and quit
+	pConfig->Save();
+
+	return 0;
+}
diff --git a/src/engine/client/client.h b/src/engine/client/client.h
index 64ef6d9b..c7174f85 100644
--- a/src/engine/client/client.h
+++ b/src/engine/client/client.h
@@ -1,17 +1,291 @@
+#ifndef ENGINE_CLIENT_CLIENT_H
+#define ENGINE_CLIENT_CLIENT_H
 
 
-class IEngine
+#include <engine/console.h>
+#include <engine/editor.h>
+#include <engine/graphics.h>
+#include <engine/textrender.h>
+#include <engine/client.h>
+#include <engine/config.h>
+#include <engine/serverbrowser.h>
+#include <engine/sound.h>
+#include <engine/input.h>
+#include <engine/keys.h>
+#include <engine/map.h>
+#include <engine/masterserver.h>
+#include <engine/storage.h>
+
+#include <engine/shared/engine.h>
+#include <engine/shared/protocol.h>
+#include <engine/shared/demorec.h>
+#include <engine/shared/network.h>
+
+#include "srvbrowse.h"
+
+class CGraph
 {
 public:
-	virtual ~IEngine() {}
-	virtual class IGraphics *Graphics() = 0;
+	enum
+	{
+		// restrictions: Must be power of two
+		MAX_VALUES=128,
+	};
+
+	float m_Min, m_Max;
+	float m_aValues[MAX_VALUES];
+	float m_aColors[MAX_VALUES][3];
+	int m_Index;
+
+	void Init(float Min, float Max);
+
+	void ScaleMax();
+	void ScaleMin();
+
+	void Add(float v, float r, float g, float b);
+	void Render(IGraphics *pGraphics, int Font, float x, float y, float w, float h, const char *pDescription);
 };
 
 
-class IGameClient
+class CSmoothTime
 {
+	int64 m_Snap;
+	int64 m_Current;
+	int64 m_Target;
+
+	int64 m_RLast;
+	int64 m_TLast;
+	CGraph m_Graph;
+
+	int m_SpikeCounter;
+
+	float m_aAdjustSpeed[2]; // 0 = down, 1 = up
 public:
-	virtual ~IGameClient() {}
+	void Init(int64 Target);
+	void SetAdjustSpeed(int Direction, float Value);
+
+	int64 Get(int64 Now);
+
+	void UpdateInt(int64 Target);
+	void Update(CGraph *pGraph, int64 Target, int TimeLeft, int AdjustDirection);
 };
 
-extern IGameClient *CreateGameClient(IEngine *pEngine);
+
+class CClient : public IClient, public CDemoPlayer::IListner
+{
+	// needed interfaces
+	IEditor *m_pEditor;
+	IEngineInput *m_pInput;
+	IEngineGraphics *m_pGraphics;
+	IEngineSound *m_pSound;
+	IGameClient *m_pGameClient;
+	IEngineMap *m_pMap;
+	IConsole *m_pConsole;
+	IStorage *m_pStorage;
+	IEngineMasterServer *m_pMasterServer;
+
+	enum
+	{
+		NUM_SNAPSHOT_TYPES=2,
+		PREDICTION_MARGIN=1000/50/2, // magic network prediction value
+	};
+
+	CNetClient m_NetClient;
+	CDemoPlayer m_DemoPlayer;
+	CDemoRecorder m_DemoRecorder;
+	CEngine m_Engine;
+	CServerBrowser m_ServerBrowser;
+
+	char m_aServerAddressStr[256];
+
+	unsigned m_SnapshotParts;
+	int64 m_LocalStartTime;
+
+	int m_DebugFont;
+	float m_FrameTimeLow;
+	float m_FrameTimeHigh;
+	int m_Frames;
+	NETADDR m_ServerAddress;
+	int m_WindowMustRefocus;
+	int m_SnapCrcErrors;
+
+	int m_AckGameTick;
+	int m_CurrentRecvTick;
+	int m_RconAuthed;
+
+	// version-checking
+	char m_aVersionStr[10];
+
+	// pinging
+	int64 m_PingStartTime;
+
+	//
+	char m_aCurrentMap[256];
+	int m_CurrentMapCrc;
+
+	//
+	char m_aCmdConnect[256];
+
+	// map download
+	char m_aMapdownloadFilename[256];
+	char m_aMapdownloadName[256];
+	IOHANDLE m_MapdownloadFile;
+	int m_MapdownloadChunk;
+	int m_MapdownloadCrc;
+	int m_MapdownloadAmount;
+	int m_MapdownloadTotalsize;
+
+	// time
+	CSmoothTime m_GameTime;
+	CSmoothTime m_PredictedTime;
+
+	// input
+	struct // TODO: handle input better
+	{
+		int m_aData[MAX_INPUT_SIZE]; // the input data
+		int m_Tick; // the tick that the input is for
+		int64 m_PredictedTime; // prediction latency when we sent this input
+		int64 m_Time;
+	} m_aInputs[200];
+
+	int m_CurrentInput;
+
+	// graphs
+	CGraph m_InputtimeMarginGraph;
+	CGraph m_GametimeMarginGraph;
+	CGraph m_FpsGraph;
+
+	// the game snapshots are modifiable by the game
+	CSnapshotStorage m_SnapshotStorage;
+	CSnapshotStorage::CHolder *m_aSnapshots[NUM_SNAPSHOT_TYPES];
+
+	int m_RecivedSnapshots;
+	char m_aSnapshotIncommingData[CSnapshot::MAX_SIZE];
+
+	CSnapshotStorage::CHolder m_aDemorecSnapshotHolders[NUM_SNAPSHOT_TYPES];
+	char *m_aDemorecSnapshotData[NUM_SNAPSHOT_TYPES][2][CSnapshot::MAX_SIZE];
+
+	CSnapshotDelta m_SnapshotDelta;
+
+	//
+	CServerInfo m_CurrentServerInfo;
+	int64 m_CurrentServerInfoRequestTime; // >= 0 should request, == -1 got info
+
+	// version info
+	struct
+	{
+		int m_State;
+		CHostLookup m_VersionServeraddr;
+	} m_VersionInfo;
+public:
+	IEngineGraphics *Graphics() { return m_pGraphics; }
+	IEngineInput *Input() { return m_pInput; }
+	IEngineSound *Sound() { return m_pSound; }
+	IGameClient *GameClient() { return m_pGameClient; }
+	IEngineMasterServer *MasterServer() { return m_pMasterServer; }
+	IStorage *Storage() { return m_pStorage; }
+
+	CClient();
+
+	// ----- send functions -----
+	virtual int SendMsg(CMsgPacker *pMsg, int Flags);
+
+	int SendMsgEx(CMsgPacker *pMsg, int Flags, bool System=true);
+	void SendInfo();
+	void SendEnterGame();
+	void SendReady();
+
+	virtual bool RconAuthed();
+	void RconAuth(const char *pName, const char *pPassword);
+	virtual void Rcon(const char *pCmd);
+
+	virtual bool ConnectionProblems();
+
+	void DirectInput(int *pInput, int Size);
+	void SendInput();
+
+	// TODO: OPT: do this alot smarter!
+	virtual int *GetInput(int Tick);
+
+	const char *LatestVersion();
+	void VersionUpdate();
+
+	// ------ state handling -----
+	void SetState(int s);
+
+	// called when the map is loaded and we should init for a new round
+	void OnEnterGame();
+	virtual void EnterGame();
+
+	virtual void Connect(const char *pAddress);
+	void DisconnectWithReason(const char *pReason);
+	virtual void Disconnect();
+
+
+	virtual void GetServerInfo(CServerInfo *pServerInfo);
+	void ServerInfoRequest();
+
+	int LoadData();
+
+	// ---
+
+	void *SnapGetItem(int SnapId, int Index, CSnapItem *pItem);
+	void SnapInvalidateItem(int SnapId, int Index);
+	void *SnapFindItem(int SnapId, int Type, int Id);
+	int SnapNumItems(int SnapId);
+	void SnapSetStaticsize(int ItemType, int Size);
+
+	void Render();
+	void DebugRender();
+
+	virtual void Quit();
+
+	virtual const char *ErrorString();
+
+	const char *LoadMap(const char *pName, const char *pFilename, unsigned WantedCrc);
+	const char *LoadMapSearch(const char *pMapName, int WantedCrc);
+
+	static int PlayerScoreComp(const void *a, const void *b);
+
+	void ProcessPacket(CNetChunk *pPacket);
+
+	virtual int MapDownloadAmount() { return m_MapdownloadAmount; }
+	virtual int MapDownloadTotalsize() { return m_MapdownloadTotalsize; }
+
+	void PumpNetwork();
+
+	virtual void OnDemoPlayerSnapshot(void *pData, int Size);
+	virtual void OnDemoPlayerMessage(void *pData, int Size);
+
+	void Update();
+
+	virtual const char *UserDirectory();
+
+	void InitEngine(const char *pAppname);
+	void RegisterInterfaces();
+	void InitInterfaces();
+
+	void Run();
+
+
+	static void Con_Connect(IConsole::IResult *pResult, void *pUserData);
+	static void Con_Disconnect(IConsole::IResult *pResult, void *pUserData);
+	static void Con_Quit(IConsole::IResult *pResult, void *pUserData);
+	static void Con_Minimize(IConsole::IResult *pResult, void *pUserData);
+	static void Con_Ping(IConsole::IResult *pResult, void *pUserData);
+	static void Con_Screenshot(IConsole::IResult *pResult, void *pUserData);
+	static void Con_Rcon(IConsole::IResult *pResult, void *pUserData);
+	static void Con_RconAuth(IConsole::IResult *pResult, void *pUserData);
+	static void Con_AddFavorite(IConsole::IResult *pResult, void *pUserData);
+	static void Con_Play(IConsole::IResult *pResult, void *pUserData);
+	static void Con_Record(IConsole::IResult *pResult, void *pUserData);
+	static void Con_StopRecord(IConsole::IResult *pResult, void *pUserData);
+	static void Con_ServerDummy(IConsole::IResult *pResult, void *pUserData);
+
+	void RegisterCommands();
+
+	const char *DemoPlayer_Play(const char *pFilename);
+
+	virtual class CEngine *Engine() { return &m_Engine; }
+};
+#endif
diff --git a/src/engine/client/ec_client.cpp b/src/engine/client/ec_client.cpp
deleted file mode 100644
index 7ba0a2bb..00000000
--- a/src/engine/client/ec_client.cpp
+++ /dev/null
@@ -1,2087 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-
-#include <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-
-#include <base/system.h>
-#include <engine/e_engine.h>
-#include <engine/e_client_interface.h>
-
-#include <engine/e_protocol.h>
-#include <engine/e_snapshot.h>
-#include <engine/e_compression.h>
-#include <engine/e_network.h>
-#include <engine/e_config.h>
-#include <engine/e_packer.h>
-#include <engine/e_memheap.h>
-#include <engine/e_datafile.h>
-#include <engine/e_console.h>
-#include <engine/e_ringbuffer.h>
-
-#include <engine/e_huffman.h>
-
-#include <engine/e_demorec.h>
-
-#include <mastersrv/mastersrv.h>
-#include <versionsrv/versionsrv.h>
-
-#include "editor.h"
-#include "graphics.h"
-#include "client.h"
-
-static IEditor *m_pEditor = 0;
-static IEngineGraphics *m_pGraphics = 0;
-IEngineGraphics *Graphics() { return m_pGraphics; }
-
-static IGameClient *m_pGameClient = 0;
-
-
-class CClient : public IEngine
-{
-public:
-	virtual class IGraphics *Graphics()
-	{
-		return m_pGraphics;
-	}
-};
-
-static CClient m_Client;
-
-const int prediction_margin = 1000/50/2; /* magic network prediction value */
-
-/*
-	Server Time
-	Client Mirror Time
-	Client Predicted Time
-	
-	Snapshot Latency
-		Downstream latency
-	
-	Prediction Latency
-		Upstream latency
-*/
-
-/* network client, must be accessible from other parts like the server browser */
-CNetClient m_NetClient;
-
-/* TODO: ugly, fix me */
-extern void client_serverbrowse_set(NETADDR *addr, int request, int token, SERVER_INFO *info);
-extern void client_serverbrowse_save();
-
-static unsigned snapshot_parts;
-static int64 local_start_time;
-
-static int debug_font;
-static float frametime = 0.0001f;
-static float frametime_low = 1.0f;
-static float frametime_high = 0.0f;
-static int frames = 0;
-static NETADDR server_address;
-static int window_must_refocus = 0;
-static int snapcrcerrors = 0;
-
-static int ack_game_tick = -1;
-static int current_recv_tick = 0;
-static int rcon_authed = 0;
-
-/* version-checking */
-static char versionstr[10] = "0";
-
-/* pinging */
-static int64 ping_start_time = 0;
-
-/* */
-static char current_map[256] = {0};
-static int current_map_crc = 0;
-
-/* */
-static char cmd_connect[256] = {0};
-
-/* map download */
-static char mapdownload_filename[256] = {0};
-static char mapdownload_name[256] = {0};
-static IOHANDLE mapdownload_file = 0;
-static int mapdownload_chunk = 0;
-static int mapdownload_crc = 0;
-static int mapdownload_amount = -1;
-static int mapdownload_totalsize = -1;
-
-/* */
-static SERVER_INFO current_server_info = {0};
-static int64 current_server_info_requesttime = -1; /* >= 0 should request, == -1 got info */
-
-/* current time */
-static int current_tick = 0;
-static float intratick = 0;
-static float ticktime = 0;
-static int prev_tick = 0;
-
-/* */
-/*static int predictiontime_pingspikecounter = 0;
-static int gametime_pingspikecounter = 0;*/
-
-/* predicted time */
-static int current_predtick = 0;
-static float predintratick = 0;
-static int last_input_timeleft = 0;
-
-static struct /* TODO: handle input better */
-{
-	int data[MAX_INPUT_SIZE]; /* the input data */
-	int tick; /* the tick that the input is for */
-	int64 predicted_time; /* prediction latency when we sent this input */
-	int64 time;
-} inputs[200];
-static int current_input = 0;
-
-enum
-{
-	GRAPH_MAX=128
-};
-
-typedef struct
-{
-	float min, max;
-	float values[GRAPH_MAX];
-	float colors[GRAPH_MAX][3];
-	int index;
-} GRAPH;
-
-static void graph_init(GRAPH *g, float min, float max)
-{
-	g->min = min;
-	g->max = max;
-	g->index = 0;
-}
-
-static void graph_scale_max(GRAPH *g)
-{
-	int i = 0;
-	g->max = 0;
-	for(i = 0; i < GRAPH_MAX; i++)
-	{
-		if(g->values[i] > g->max)
-			g->max = g->values[i];
-	}
-}
-
-static void graph_scale_min(GRAPH *g)
-{
-	int i = 0;
-	g->min = g->max;
-	for(i = 0; i < GRAPH_MAX; i++)
-	{
-		if(g->values[i] < g->min)
-			g->min = g->values[i];
-	}
-}
-
-static void graph_add(GRAPH *graph, float v, float r, float g, float b)
-{
-	graph->index = (graph->index+1)&(GRAPH_MAX-1);
-	graph->values[graph->index] = v;
-	graph->colors[graph->index][0] = r;
-	graph->colors[graph->index][1] = g;
-	graph->colors[graph->index][2] = b;
-}
-
-static void graph_render(GRAPH *g, float x, float y, float w, float h, const char *description)
-{
-	char buf[32];
-	int i;
-
-	//m_pGraphics->BlendNormal();
-
-	
-	Graphics()->TextureSet(-1);
-	
-	m_pGraphics->QuadsBegin();
-	Graphics()->SetColor(0, 0, 0, 0.75f);
-	Graphics()->QuadsDrawTL(x, y, w, h);
-	m_pGraphics->QuadsEnd();
-		
-	Graphics()->LinesBegin();
-	Graphics()->SetColor(0.95f, 0.95f, 0.95f, 1.00f);
-	Graphics()->LinesDraw(x, y+h/2, x+w, y+h/2);
-	Graphics()->SetColor(0.5f, 0.5f, 0.5f, 0.75f);
-	Graphics()->LinesDraw(x, y+(h*3)/4, x+w, y+(h*3)/4);
-	Graphics()->LinesDraw(x, y+h/4, x+w, y+h/4);
-	for(i = 1; i < GRAPH_MAX; i++)
-	{
-		float a0 = (i-1)/(float)GRAPH_MAX;
-		float a1 = i/(float)GRAPH_MAX;
-		int i0 = (g->index+i-1)&(GRAPH_MAX-1);
-		int i1 = (g->index+i)&(GRAPH_MAX-1);
-		
-		float v0 = (g->values[i0]-g->min) / (g->max-g->min);
-		float v1 = (g->values[i1]-g->min) / (g->max-g->min);
-		
-		Graphics()->SetColorVertex(0, g->colors[i0][0], g->colors[i0][1], g->colors[i0][2], 0.75f);
-		Graphics()->SetColorVertex(1, g->colors[i1][0], g->colors[i1][1], g->colors[i1][2], 0.75f);
-		Graphics()->LinesDraw(x+a0*w, y+h-v0*h, x+a1*w, y+h-v1*h);
-
-	}
-	Graphics()->LinesEnd();
-	
-
-	Graphics()->TextureSet(debug_font);	
-	Graphics()->QuadsText(x+2, y+h-16, 16, 1,1,1,1, description);
-
-	str_format(buf, sizeof(buf), "%.2f", g->max);
-	Graphics()->QuadsText(x+w-8*strlen(buf)-8, y+2, 16, 1,1,1,1, buf);
-	
-	str_format(buf, sizeof(buf), "%.2f", g->min);
-	Graphics()->QuadsText(x+w-8*strlen(buf)-8, y+h-16, 16, 1,1,1,1, buf);
-	
-}
-
-typedef struct
-{
-	int64 snap;
-	int64 current;
-	int64 target;
-	
-	int64 rlast;
-	int64 tlast;
-	GRAPH graph;
-	
-	int spikecounter;
-	
-	float adjustspeed[2]; /* 0 = down, 1 = up */
-} SMOOTHTIME;
-
-static void st_init(SMOOTHTIME *st, int64 target)
-{
-	st->snap = time_get();
-	st->current = target;
-	st->target = target;
-	st->adjustspeed[0] = 0.3f;
-	st->adjustspeed[1] = 0.3f;
-	graph_init(&st->graph, 0.0f, 0.5f);
-}
-
-static int64 st_get(SMOOTHTIME *st, int64 now)
-{
-	float adjust_speed, a;
-	int64 c = st->current + (now - st->snap);
-	int64 t = st->target + (now - st->snap);
-	int64 r;
-	
-	/* it's faster to adjust upward instead of downward */
-	/* we might need to adjust these abit */
-
-	adjust_speed = st->adjustspeed[0];
-	if(t > c)
-		adjust_speed = st->adjustspeed[1];
-	
-	a = ((now-st->snap)/(float)time_freq()) * adjust_speed;
-	if(a > 1.0f)
-		a = 1.0f;
-		
-	r = c + (int64)((t-c)*a);
-	
-	graph_add(&st->graph, a+0.5f,1,1,1);
-	
-	return r;
-}
-
-static void st_update_int(SMOOTHTIME *st, int64 target)
-{
-	int64 now = time_get();
-	st->current = st_get(st, now);
-	st->snap = now;
-	st->target = target;
-}
-
-static void st_update(SMOOTHTIME *st, GRAPH *graph, int64 target, int time_left, int adjust_direction)
-{
-	int update_timer = 1;
-	
-	if(time_left < 0)
-	{
-		int is_spike = 0;
-		if(time_left < -50)
-		{
-			is_spike = 1;
-			
-			st->spikecounter += 5;
-			if(st->spikecounter > 50)
-				st->spikecounter = 50;
-		}
-		
-		if(is_spike && st->spikecounter < 15)
-		{
-			/* ignore this ping spike */
-			update_timer = 0;
-			graph_add(graph, time_left, 1,1,0);
-		}
-		else
-		{
-			graph_add(graph, time_left, 1,0,0);
-			if(st->adjustspeed[adjust_direction] < 30.0f)
-				st->adjustspeed[adjust_direction] *= 2.0f;
-		}
-	}
-	else
-	{
-		if(st->spikecounter)
-			st->spikecounter--;
-			
-		graph_add(graph, time_left, 0,1,0);
-		
-		st->adjustspeed[adjust_direction] *= 0.95f;
-		if(st->adjustspeed[adjust_direction] < 2.0f)
-			st->adjustspeed[adjust_direction] = 2.0f;
-	}
-	
-	last_input_timeleft = time_left;
-	
-	if(update_timer)
-		st_update_int(st, target);
-}
-
-static SMOOTHTIME game_time;
-static SMOOTHTIME predicted_time;
-
-/* graphs */
-static GRAPH inputtime_margin_graph;
-static GRAPH gametime_margin_graph;
-static GRAPH fps_graph;
-
-/* -- snapshot handling --- */
-enum
-{
-	NUM_SNAPSHOT_TYPES=2
-};
-
-/* the game snapshots are modifiable by the game */
-CSnapshotStorage snapshot_storage;
-static CSnapshotStorage::CHolder *snapshots[NUM_SNAPSHOT_TYPES] = {0, 0};
-
-static int recived_snapshots = 0;
-static char snapshot_incomming_data[CSnapshot::MAX_SIZE];
-
-static CSnapshotStorage::CHolder demorec_snapshotholders[NUM_SNAPSHOT_TYPES];
-static char *demorec_snapshotdata[NUM_SNAPSHOT_TYPES][2][CSnapshot::MAX_SIZE];
-
-/* --- */
-
-void *snap_get_item(int snapid, int index, SNAP_ITEM *item)
-{
-	CSnapshotItem *i;
-	dbg_assert(snapid >= 0 && snapid < NUM_SNAPSHOT_TYPES, "invalid snapid");
-	i = snapshots[snapid]->m_pAltSnap->GetItem(index);
-	item->datasize = snapshots[snapid]->m_pAltSnap->GetItemSize(index);
-	item->type = i->Type();
-	item->id = i->ID();
-	return (void *)i->Data();
-}
-
-void snap_invalidate_item(int snapid, int index)
-{
-	CSnapshotItem *i;
-	dbg_assert(snapid >= 0 && snapid < NUM_SNAPSHOT_TYPES, "invalid snapid");
-	i = snapshots[snapid]->m_pAltSnap->GetItem(index);
-	if(i)
-	{
-		if((char *)i < (char *)snapshots[snapid]->m_pAltSnap || (char *)i > (char *)snapshots[snapid]->m_pAltSnap + snapshots[snapid]->m_SnapSize)
-			dbg_msg("ASDFASDFASdf", "ASDFASDFASDF");
-		if((char *)i >= (char *)snapshots[snapid]->m_pSnap && (char *)i < (char *)snapshots[snapid]->m_pSnap + snapshots[snapid]->m_SnapSize)
-			dbg_msg("ASDFASDFASdf", "ASDFASDFASDF");
-		i->m_TypeAndID = -1;
-	}
-}
-
-void *snap_find_item(int snapid, int type, int id)
-{
-	/* TODO: linear search. should be fixed. */
-	int i;
-	
-	if(!snapshots[snapid])
-		return 0x0;
-	
-	for(i = 0; i < snapshots[snapid]->m_pSnap->m_NumItems; i++)
-	{
-		CSnapshotItem *itm = snapshots[snapid]->m_pAltSnap->GetItem(i);
-		if(itm->Type() == type && itm->ID() == id)
-			return (void *)itm->Data();
-	}
-	return 0x0;
-}
-
-int snap_num_items(int snapid)
-{
-	dbg_assert(snapid >= 0 && snapid < NUM_SNAPSHOT_TYPES, "invalid snapid");
-	if(!snapshots[snapid])
-		return 0;
-	return snapshots[snapid]->m_pSnap->m_NumItems;
-}
-
-/* ------ time functions ------ */
-float client_intratick() { return intratick; }
-float client_predintratick() { return predintratick; }
-float client_ticktime() { return ticktime; }
-int client_tick() { return current_tick; }
-int client_prevtick() { return prev_tick; }
-int client_predtick() { return current_predtick; }
-int client_tickspeed() { return SERVER_TICK_SPEED; }
-float client_frametime() { return frametime; }
-float client_localtime() { return (time_get()-local_start_time)/(float)(time_freq()); }
-
-/* ----- send functions ----- */
-int client_send_msg()
-{
-	const MSG_INFO *pInfo = msg_get_info();
-	CNetChunk Packet;
-	
-	if(!pInfo)
-		return -1;
-
-	if(client_state() == CLIENTSTATE_OFFLINE)
-		return 0;
-	
-	mem_zero(&Packet, sizeof(CNetChunk));
-	
-	Packet.m_ClientID = 0;
-	Packet.m_pData = pInfo->data;
-	Packet.m_DataSize = pInfo->size;
-
-	if(pInfo->flags&MSGFLAG_VITAL)
-		Packet.m_Flags |= NETSENDFLAG_VITAL;
-	if(pInfo->flags&MSGFLAG_FLUSH)
-		Packet.m_Flags |= NETSENDFLAG_FLUSH;
-		
-	if(pInfo->flags&MSGFLAG_RECORD)
-	{
-		if(demorec_isrecording())
-			demorec_record_message(Packet.m_pData, Packet.m_DataSize);
-	}
-
-	if(!(pInfo->flags&MSGFLAG_NOSEND))
-		m_NetClient.Send(&Packet);
-	return 0;
-}
-
-static void client_send_info()
-{
-	msg_pack_start_system(NETMSG_INFO, MSGFLAG_VITAL|MSGFLAG_FLUSH);
-	msg_pack_string(modc_net_version(), 128);
-	msg_pack_string(config.player_name, 128);
-	msg_pack_string(config.clan_name, 128);
-	msg_pack_string(config.password, 128);
-	msg_pack_end();
-	client_send_msg();
-}
-
-
-static void client_send_entergame()
-{
-	msg_pack_start_system(NETMSG_ENTERGAME, MSGFLAG_VITAL|MSGFLAG_FLUSH);
-	msg_pack_end();
-	client_send_msg();
-}
-
-static void client_send_ready()
-{
-	msg_pack_start_system(NETMSG_READY, MSGFLAG_VITAL|MSGFLAG_FLUSH);
-	msg_pack_end();
-	client_send_msg();
-}
-
-int client_rcon_authed()
-{
-	return rcon_authed;
-}
-
-void client_rcon_auth(const char *name, const char *password)
-{
-	msg_pack_start_system(NETMSG_RCON_AUTH, MSGFLAG_VITAL);
-	msg_pack_string(name, 32);
-	msg_pack_string(password, 32);
-	msg_pack_end();
-	client_send_msg();
-}
-
-void client_rcon(const char *cmd)
-{
-	msg_pack_start_system(NETMSG_RCON_CMD, MSGFLAG_VITAL);
-	msg_pack_string(cmd, 256);
-	msg_pack_end();
-	client_send_msg();
-}
-
-int client_connection_problems()
-{
-	return m_NetClient.GotProblems();
-}
-
-void client_direct_input(int *input, int size)
-{
-	int i;
-	msg_pack_start_system(NETMSG_INPUT, 0);
-	msg_pack_int(ack_game_tick);
-	msg_pack_int(current_predtick);
-	msg_pack_int(size);
-	
-	for(i = 0; i < size/4; i++)
-		msg_pack_int(input[i]);	
-		
-	msg_pack_end();
-	client_send_msg();
-}
-
-
-static void client_send_input()
-{
-	int64 now = time_get();	
-	int i, size;
-
-	if(current_predtick <= 0)
-		return;
-	 
-	/* fetch input */
-	size = modc_snap_input(inputs[current_input].data);
-	
-	if(!size)
-		return;
-	
-	/* pack input */
-	msg_pack_start_system(NETMSG_INPUT, MSGFLAG_FLUSH);
-	msg_pack_int(ack_game_tick);
-	msg_pack_int(current_predtick);
-	msg_pack_int(size);
-
-	inputs[current_input].tick = current_predtick;
-	inputs[current_input].predicted_time = st_get(&predicted_time, now);
-	inputs[current_input].time = now;
-
-	/* pack it */	
-	for(i = 0; i < size/4; i++)
-		msg_pack_int(inputs[current_input].data[i]);
-	
-	current_input++;
-	current_input%=200;
-	
-	msg_pack_end();
-	client_send_msg();
-}
-
-const char *client_latestversion()
-{
-	return versionstr;
-}
-
-/* TODO: OPT: do this alot smarter! */
-int *client_get_input(int tick)
-{
-	int i;
-	int best = -1;
-	for(i = 0; i < 200; i++)
-	{
-		if(inputs[i].tick <= tick && (best == -1 || inputs[best].tick < inputs[i].tick))
-			best = i;
-	}
-	
-	if(best != -1)
-		return (int *)inputs[best].data;
-	return 0;
-}
-
-/* ------ state handling ----- */
-static int state = CLIENTSTATE_OFFLINE;
-int client_state() { return state; }
-static void client_set_state(int s)
-{
-	int old = state;
-	if(config.debug)
-		dbg_msg("client", "state change. last=%d current=%d", state, s);
-	state = s;
-	if(old != s)
-		modc_statechange(state, old);
-}
-
-/* called when the map is loaded and we should init for a new round */
-static void client_on_enter_game()
-{
-	/* reset input */
-	int i;
-	for(i = 0; i < 200; i++)
-		inputs[i].tick = -1;
-	current_input = 0;
-
-	/* reset snapshots */
-	snapshots[SNAP_CURRENT] = 0;
-	snapshots[SNAP_PREV] = 0;
-	snapshot_storage.PurgeAll();
-	recived_snapshots = 0;
-	snapshot_parts = 0;
-	current_predtick = 0;
-	current_recv_tick = 0;
-}
-
-void client_entergame()
-{
-	if(state == CLIENTSTATE_DEMOPLAYBACK)
-		return;
-		
-	/* now we will wait for two snapshots */
-	/* to finish the connection */
-	client_send_entergame();
-	client_on_enter_game();
-}
-
-void client_connect(const char *server_address_str)
-{
-	char buf[512];
-	const char *port_str = 0;
-	int k;
-	int port = 8303;
-	
-	client_disconnect();
-
-	dbg_msg("client", "connecting to '%s'", server_address_str);
-
-	//client_serverinfo_request();
-	str_copy(buf, server_address_str, sizeof(buf));
-
-	for(k = 0; buf[k]; k++)
-	{
-		if(buf[k] == ':')
-		{
-			port_str = &(buf[k+1]);
-			buf[k] = 0;
-			break;
-		}
-	}
-	
-	if(port_str)
-		port = atoi(port_str);
-	
-	/* TODO: IPv6 support */
-	if(net_host_lookup(buf, &server_address, NETTYPE_IPV4) != 0)
-		dbg_msg("client", "could not find the address of %s, connecting to localhost", buf);
-	
-	rcon_authed = 0;
-	server_address.port = port;
-	m_NetClient.Connect(&server_address);
-	client_set_state(CLIENTSTATE_CONNECTING);
-	
-	graph_init(&inputtime_margin_graph, -150.0f, 150.0f);
-	graph_init(&gametime_margin_graph, -150.0f, 150.0f);
-}
-
-void client_disconnect_with_reason(const char *reason)
-{
-	/* stop demo playback */
-	demorec_playback_stop();
-	
-	/* */
-	rcon_authed = 0;
-	m_NetClient.Disconnect(reason);
-	client_set_state(CLIENTSTATE_OFFLINE);
-	map_unload();
-	
-	/* disable all downloads */
-	mapdownload_chunk = 0;
-	if(mapdownload_file)
-		io_close(mapdownload_file);
-	mapdownload_file = 0;
-	mapdownload_crc = 0;
-	mapdownload_totalsize = -1;
-	mapdownload_amount = 0;
-
-	/* clear the current server info */
-	mem_zero(&current_server_info, sizeof(current_server_info));
-	mem_zero(&server_address, sizeof(server_address));
-	
-	/* clear snapshots */
-	snapshots[SNAP_CURRENT] = 0;
-	snapshots[SNAP_PREV] = 0;
-	recived_snapshots = 0;
-}
-
-void client_disconnect()
-{
-	client_disconnect_with_reason(0);
-}
-
-
-void client_serverinfo(SERVER_INFO *serverinfo)
-{
-	mem_copy(serverinfo, &current_server_info, sizeof(current_server_info));
-}
-
-void client_serverinfo_request()
-{
-	mem_zero(&current_server_info, sizeof(current_server_info));
-	current_server_info_requesttime = 0;
-}
-
-static int client_load_data()
-{
-	debug_font = Graphics()->LoadTexture("debug_font.png", IMG_AUTO, TEXLOAD_NORESAMPLE);
-	return 1;
-}
-
-extern int snapshot_data_rate[0xffff];
-extern int snapshot_data_updates[0xffff];
-
-const char *modc_getitemname(int type);
-
-static void client_debug_render()
-{
-	static NETSTATS prev, current;
-	static int64 last_snap = 0;
-	static float frametime_avg = 0;
-	int64 now = time_get();
-	char buffer[512];
-	
-	if(!config.debug)
-		return;
-	
-	//m_pGraphics->BlendNormal();
-	Graphics()->TextureSet(debug_font);
-	Graphics()->MapScreen(0,0,Graphics()->ScreenWidth(),Graphics()->ScreenHeight());
-	
-	if(time_get()-last_snap > time_freq())
-	{
-		last_snap = time_get();
-		prev = current;
-		net_stats(&current);
-	}
-	
-	/*
-		eth = 14
-		ip = 20
-		udp = 8
-		total = 42
-	*/
-	frametime_avg = frametime_avg*0.9f + frametime*0.1f;
-	str_format(buffer, sizeof(buffer), "ticks: %8d %8d mem %dk %d  gfxmem: N/A  fps: %3d",
-		current_tick, current_predtick,
-		mem_stats()->allocated/1024,
-		mem_stats()->total_allocations,
-		/*gfx_memory_usage()/1024, */ // TODO: Refactor: Reenable this
-		(int)(1.0f/frametime_avg));
-	Graphics()->QuadsText(2, 2, 16, 1,1,1,1, buffer);
-
-	
-	{
-		int send_packets = (current.sent_packets-prev.sent_packets);
-		int send_bytes = (current.sent_bytes-prev.sent_bytes);
-		int send_total = send_bytes + send_packets*42;
-		int recv_packets = (current.recv_packets-prev.recv_packets);
-		int recv_bytes = (current.recv_bytes-prev.recv_bytes);
-		int recv_total = recv_bytes + recv_packets*42;
-		
-		if(!send_packets) send_packets++;
-		if(!recv_packets) recv_packets++;
-		str_format(buffer, sizeof(buffer), "send: %3d %5d+%4d=%5d (%3d kbps) avg: %5d\nrecv: %3d %5d+%4d=%5d (%3d kbps) avg: %5d",
-			send_packets, send_bytes, send_packets*42, send_total, (send_total*8)/1024, send_bytes/send_packets,
-			recv_packets, recv_bytes, recv_packets*42, recv_total, (recv_total*8)/1024, recv_bytes/recv_packets);
-		Graphics()->QuadsText(2, 14, 16, 1,1,1,1, buffer);
-	}
-	
-	/* render rates */
-	{
-		int y = 0;
-		int i;
-		for(i = 0; i < 256; i++)
-		{
-			if(snapshot_data_rate[i])
-			{
-				str_format(buffer, sizeof(buffer), "%4d %20s: %8d %8d %8d", i, modc_getitemname(i), snapshot_data_rate[i]/8, snapshot_data_updates[i],
-					(snapshot_data_rate[i]/snapshot_data_updates[i])/8);
-				Graphics()->QuadsText(2, 100+y*12, 16, 1,1,1,1, buffer);
-				y++;
-			}
-		}
-	}
-
-	str_format(buffer, sizeof(buffer), "pred: %d ms  %3.2f", 
-		(int)((st_get(&predicted_time, now)-st_get(&game_time, now))*1000/(float)time_freq()),
-		predicted_time.adjustspeed[1]);
-	Graphics()->QuadsText(2, 70, 16, 1,1,1,1, buffer);
-	
-	/* render graphs */
-	if(config.dbg_graphs)
-	{
-		//Graphics()->MapScreen(0,0,400.0f,300.0f);
-		float w = Graphics()->ScreenWidth()/4.0f;
-		float h = Graphics()->ScreenHeight()/6.0f;
-		float sp = Graphics()->ScreenWidth()/100.0f;
-		float x = Graphics()->ScreenWidth()-w-sp;
-
-		graph_scale_max(&fps_graph);
-		graph_scale_min(&fps_graph);
-		graph_render(&fps_graph, x, sp*5, w, h, "FPS");
-		graph_render(&inputtime_margin_graph, x, sp*5+h+sp, w, h, "Prediction Margin");
-		graph_render(&gametime_margin_graph, x, sp*5+h+sp+h+sp, w, h, "Gametime Margin");
-	}
-}
-
-void client_quit()
-{
-	client_set_state(CLIENTSTATE_QUITING);
-}
-
-const char *client_error_string()
-{
-	return m_NetClient.ErrorString();
-}
-
-static void client_render()
-{
-	if(config.gfx_clear)	
-		Graphics()->Clear(1,1,0);
-
-	modc_render();
-	client_debug_render();
-}
-
-static const char *client_load_map(const char *name, const char *filename, int wanted_crc)
-{
-	static char errormsg[128];
-	DATAFILE *df;
-	int crc;
-	
-	client_set_state(CLIENTSTATE_LOADING);
-	
-	df = datafile_load(filename);
-	if(!df)
-	{
-		str_format(errormsg, sizeof(errormsg), "map '%s' not found", filename);
-		return errormsg;
-	}
-	
-	/* get the crc of the map */
-	crc = datafile_crc(filename);
-	if(crc != wanted_crc)
-	{
-		datafile_unload(df);
-		str_format(errormsg, sizeof(errormsg), "map differs from the server. %08x != %08x", crc, wanted_crc);
-		return errormsg;
-	}
-	
-	// stop demo recording if we loaded a new map
-	demorec_record_stop();
-	
-	dbg_msg("client", "loaded map '%s'", filename);
-	recived_snapshots = 0;
-	map_set(df);
-	
-	str_copy(current_map, name, sizeof(current_map));
-	current_map_crc = crc;
-	
-	return NULL;
-}
-
-static const char *client_load_map_search(const char *mapname, int wanted_crc)
-{
-	const char *error = 0;
-	char buf[512];
-	dbg_msg("client", "loading map, map=%s wanted crc=%08x", mapname, wanted_crc);
-	client_set_state(CLIENTSTATE_LOADING);
-	
-	/* try the normal maps folder */
-	str_format(buf, sizeof(buf), "maps/%s.map", mapname);
-	error = client_load_map(mapname, buf, wanted_crc);
-	if(!error)
-		return error;
-
-	/* try the downloaded maps */
-	str_format(buf, sizeof(buf), "downloadedmaps/%s_%8x.map", mapname, wanted_crc);
-	error = client_load_map(mapname, buf, wanted_crc);
-	return error;
-}
-
-static int player_score_comp(const void *a, const void *b)
-{
-	SERVER_INFO_PLAYER *p0 = (SERVER_INFO_PLAYER *)a;
-	SERVER_INFO_PLAYER *p1 = (SERVER_INFO_PLAYER *)b;
-	if(p0->score == p1->score)
-		return 0;
-	if(p0->score < p1->score)
-		return 1;
-	return -1;
-}
-
-static void client_process_packet(CNetChunk *pPacket)
-{
-	if(pPacket->m_ClientID == -1)
-	{
-		/* connectionlesss */
-		if(pPacket->m_DataSize == (int)(sizeof(VERSIONSRV_VERSION) + sizeof(VERSION_DATA)) &&
-			memcmp(pPacket->m_pData, VERSIONSRV_VERSION, sizeof(VERSIONSRV_VERSION)) == 0)
-		{
-			unsigned char *versiondata = (unsigned char*)pPacket->m_pData + sizeof(VERSIONSRV_VERSION);
-			int version_match = !memcmp(versiondata, VERSION_DATA, sizeof(VERSION_DATA));
-			
-			dbg_msg("client/version", "version does %s (%d.%d.%d)",
-				version_match ? "match" : "NOT match",
-				versiondata[1], versiondata[2], versiondata[3]);
-			
-			/* assume version is out of date when version-data doesn't match */
-			if (!version_match)
-			{
-				sprintf(versionstr, "%d.%d.%d", versiondata[1], versiondata[2], versiondata[3]);
-			}
-		}
-		
-		if(pPacket->m_DataSize >= (int)sizeof(SERVERBROWSE_LIST) &&
-			memcmp(pPacket->m_pData, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST)) == 0)
-		{
-			int size = pPacket->m_DataSize-sizeof(SERVERBROWSE_LIST);
-			int num = size/sizeof(MASTERSRV_ADDR);
-			MASTERSRV_ADDR *addrs = (MASTERSRV_ADDR *)((char*)pPacket->m_pData+sizeof(SERVERBROWSE_LIST));
-			int i;
-
-			for(i = 0; i < num; i++)
-			{
-				NETADDR addr;
-				
-				/* convert address */
-				mem_zero(&addr, sizeof(addr));
-				addr.type = NETTYPE_IPV4;
-				addr.ip[0] = addrs[i].ip[0];
-				addr.ip[1] = addrs[i].ip[1];
-				addr.ip[2] = addrs[i].ip[2];
-				addr.ip[3] = addrs[i].ip[3];
-				addr.port = (addrs[i].port[1]<<8) | addrs[i].port[0];
-				
-				client_serverbrowse_set(&addr, BROWSESET_MASTER_ADD, -1, NULL);
-			}
-		}
-
-		{
-			int packet_type = 0;
-			if(pPacket->m_DataSize >= (int)sizeof(SERVERBROWSE_INFO) && memcmp(pPacket->m_pData, SERVERBROWSE_INFO, sizeof(SERVERBROWSE_INFO)) == 0)
-				packet_type = 2;
-
-			if(pPacket->m_DataSize >= (int)sizeof(SERVERBROWSE_OLD_INFO) && memcmp(pPacket->m_pData, SERVERBROWSE_OLD_INFO, sizeof(SERVERBROWSE_OLD_INFO)) == 0)
-				packet_type = 1;
-			
-			if(packet_type)
-			{
-				/* we got ze info */
-				CUnpacker up;
-				SERVER_INFO info = {0};
-				int i;
-				int token = -1;
-				
-				up.Reset((unsigned char*)pPacket->m_pData+sizeof(SERVERBROWSE_INFO), pPacket->m_DataSize-sizeof(SERVERBROWSE_INFO));
-				if(packet_type >= 2)
-					token = atol(up.GetString());
-				str_copy(info.version, up.GetString(), sizeof(info.version));
-				str_copy(info.name, up.GetString(), sizeof(info.name));
-				str_copy(info.map, up.GetString(), sizeof(info.map));
-				str_copy(info.gametype, up.GetString(), sizeof(info.gametype));
-				info.flags = atol(up.GetString());
-				info.progression = atol(up.GetString());
-				info.num_players = atol(up.GetString());
-				info.max_players = atol(up.GetString());
-				str_format(info.address, sizeof(info.address), "%d.%d.%d.%d:%d",
-					pPacket->m_Address.ip[0], pPacket->m_Address.ip[1], pPacket->m_Address.ip[2],
-					pPacket->m_Address.ip[3], pPacket->m_Address.port);
-				
-				for(i = 0; i < info.num_players; i++)
-				{
-					str_copy(info.players[i].name, up.GetString(), sizeof(info.players[i].name));
-					info.players[i].score = atol(up.GetString());
-				}
-				
-				if(!up.Error())
-				{
-					/* sort players */
-					qsort(info.players, info.num_players, sizeof(*info.players), player_score_comp);
-					
-					if(net_addr_comp(&server_address, &pPacket->m_Address) == 0)
-					{
-						mem_copy(&current_server_info, &info, sizeof(current_server_info));
-						current_server_info.netaddr = server_address;
-						current_server_info_requesttime = -1;
-					}
-					else
-					{
-						if(packet_type == 2)
-							client_serverbrowse_set(&pPacket->m_Address, BROWSESET_TOKEN, token, &info);
-						else
-							client_serverbrowse_set(&pPacket->m_Address, BROWSESET_OLD_INTERNET, -1, &info);
-					}
-				}
-			}
-		}
-	}
-	else
-	{
-		int sys;
-		int msg = msg_unpack_start(pPacket->m_pData, pPacket->m_DataSize, &sys);
-		
-		if(sys)
-		{
-			/* system message */
-			if(msg == NETMSG_MAP_CHANGE)
-			{
-				const char *map = msg_unpack_string();
-				int map_crc = msg_unpack_int();
-				const char *error = 0;
-				int i;
-
-				if(msg_unpack_error())
-					return;
-				
-				for(i = 0; map[i]; i++) /* protect the player from nasty map names */
-				{
-					if(map[i] == '/' || map[i] == '\\')
-						error = "strange character in map name";
-				}
-				
-				if(error)
-					client_disconnect_with_reason(error);
-				else
-				{
-					error = client_load_map_search(map, map_crc);
-
-					if(!error)
-					{
-						dbg_msg("client/network", "loading done");
-						client_send_ready();
-						modc_connected();
-					}
-					else
-					{
-						str_format(mapdownload_filename, sizeof(mapdownload_filename), "downloadedmaps/%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 = engine_openfile(mapdownload_filename, IOFLAG_WRITE);
-						mapdownload_crc = map_crc;
-						mapdownload_totalsize = -1;
-						mapdownload_amount = 0;
-						
-						msg_pack_start_system(NETMSG_REQUEST_MAP_DATA, MSGFLAG_VITAL|MSGFLAG_FLUSH);
-						msg_pack_int(mapdownload_chunk);
-						msg_pack_end();
-						client_send_msg();
-										
-						if(config.debug)
-							dbg_msg("client/network", "requested chunk %d", mapdownload_chunk);
-					}
-				}
-			}
-			else if(msg == NETMSG_MAP_DATA)
-			{
-				int last = msg_unpack_int();
-				int total_size = msg_unpack_int();
-				int size = msg_unpack_int();
-				const unsigned char *data = msg_unpack_raw(size);
-				
-				/* check fior errors */
-				if(msg_unpack_error() || size <= 0 || total_size <= 0 || !mapdownload_file)
-					return;
-				
-				io_write(mapdownload_file, data, size);
-				
-				mapdownload_totalsize = total_size;
-				mapdownload_amount += size;
-				
-				if(last)
-				{
-					const char *error;
-					dbg_msg("client/network", "download complete, loading map");
-					
-					io_close(mapdownload_file);
-					mapdownload_file = 0;
-					mapdownload_amount = 0;
-					mapdownload_totalsize = -1;
-					
-					/* load map */
-					error = client_load_map(mapdownload_name, mapdownload_filename, mapdownload_crc);
-					if(!error)
-					{
-						dbg_msg("client/network", "loading done");
-						client_send_ready();
-						modc_connected();
-					}
-					else
-						client_disconnect_with_reason(error);
-				}
-				else
-				{
-					/* request new chunk */
-					mapdownload_chunk++;
-					msg_pack_start_system(NETMSG_REQUEST_MAP_DATA, MSGFLAG_VITAL|MSGFLAG_FLUSH);
-					msg_pack_int(mapdownload_chunk);
-					msg_pack_end();
-					client_send_msg();
-
-					if(config.debug)
-						dbg_msg("client/network", "requested chunk %d", mapdownload_chunk);
-				}
-			}
-			else if(msg == NETMSG_PING)
-			{
-				msg_pack_start_system(NETMSG_PING_REPLY, 0);
-				msg_pack_end();
-				client_send_msg();
-			}
-			else if(msg == NETMSG_RCON_AUTH_STATUS)
-			{
-				int result = msg_unpack_int();
-				if(msg_unpack_error() == 0)
-					rcon_authed = result;
-			}
-			else if(msg == NETMSG_RCON_LINE)
-			{
-				const char *line = msg_unpack_string();
-				if(msg_unpack_error() == 0)
-				{
-					/*dbg_msg("remote", "%s", line);*/
-					modc_rcon_line(line);
-				}
-			}
-			else if(msg == NETMSG_PING_REPLY)
-				dbg_msg("client/network", "latency %.2f", (time_get() - ping_start_time)*1000 / (float)time_freq());
-			else if(msg == NETMSG_INPUTTIMING)
-			{
-				int input_predtick = msg_unpack_int();
-				int time_left = msg_unpack_int();
-				
-				/* adjust our prediction time */
-				int k;
-				int64 target = 0;
-				for(k = 0; k < 200; k++)
-				{
-					if(inputs[k].tick == input_predtick)
-					{
-						target = inputs[k].predicted_time + (time_get() - inputs[k].time);
-						target = target - (int64)(((time_left-prediction_margin)/1000.0f)*time_freq());
-						//st_update(&predicted_time, );
-						break;
-					}
-				}
-				
-				if(target)
-					st_update(&predicted_time, &inputtime_margin_graph, target, time_left, 1);
-			}
-			else if(msg == NETMSG_SNAP || msg == NETMSG_SNAPSINGLE || msg == NETMSG_SNAPEMPTY)
-			{
-				/*dbg_msg("client/network", "got snapshot"); */
-				int num_parts = 1;
-				int part = 0;
-				int game_tick = msg_unpack_int();
-				int delta_tick = game_tick-msg_unpack_int();
-				int part_size = 0;
-				int crc = 0;
-				int complete_size = 0;
-				const char *data = 0;
-				
-				/* we are not allowed to process snapshot yet */
-				if(client_state() < CLIENTSTATE_LOADING)
-					return;
-				
-				if(msg == NETMSG_SNAP)
-				{
-					num_parts = msg_unpack_int();
-					part = msg_unpack_int();
-				}
-				
-				if(msg != NETMSG_SNAPEMPTY)
-				{
-					crc = msg_unpack_int();
-					part_size = msg_unpack_int();
-				}
-				
-				data = (const char *)msg_unpack_raw(part_size);
-				
-				if(msg_unpack_error())
-					return;
-					
-				if(game_tick >= current_recv_tick)
-				{
-					if(game_tick != current_recv_tick)
-					{
-						snapshot_parts = 0;
-						current_recv_tick = game_tick;
-					}
-						
-					/* TODO: clean this up abit */
-					mem_copy((char*)snapshot_incomming_data + part*MAX_SNAPSHOT_PACKSIZE, data, part_size);
-					snapshot_parts |= 1<<part;
-				
-					if(snapshot_parts == (unsigned)((1<<num_parts)-1))
-					{
-						static CSnapshot emptysnap;
-						CSnapshot *deltashot = &emptysnap;
-						int purgetick;
-						void *deltadata;
-						int deltasize;
-						unsigned char tmpbuffer2[CSnapshot::MAX_SIZE];
-						unsigned char tmpbuffer3[CSnapshot::MAX_SIZE];
-						int snapsize;
-						
-						complete_size = (num_parts-1) * MAX_SNAPSHOT_PACKSIZE + part_size;
-
-						/* reset snapshoting */
-						snapshot_parts = 0;
-						
-						/* find snapshot that we should use as delta */
-						emptysnap.m_DataSize = 0;
-						emptysnap.m_NumItems = 0;
-						
-						/* find delta */
-						if(delta_tick >= 0)
-						{
-							int deltashot_size = snapshot_storage.Get(delta_tick, 0, &deltashot, 0);
-							
-							if(deltashot_size < 0)
-							{
-								/* couldn't find the delta snapshots that the server used */
-								/* to compress this snapshot. force the server to resync */
-								if(config.debug)
-									dbg_msg("client", "error, couldn't find the delta snapshot");
-								
-								/* ack snapshot */
-								/* TODO: combine this with the input message */
-								ack_game_tick = -1;
-								return;
-							}
-						}
-
-						/* decompress snapshot */
-						deltadata = CSnapshot::EmptyDelta();
-						deltasize = sizeof(int)*3;
-
-						if(complete_size)
-						{	
-							int intsize = intpack_decompress(snapshot_incomming_data, complete_size, tmpbuffer2);
-
-							if(intsize < 0) /* failure during decompression, bail */
-								return;
-
-							deltadata = tmpbuffer2;
-							deltasize = intsize;
-						}
-						
-						/* unpack delta */
-						purgetick = delta_tick;
-						snapsize = CSnapshot::UnpackDelta(deltashot, (CSnapshot*)tmpbuffer3, deltadata, deltasize);
-						if(snapsize < 0)
-						{
-							dbg_msg("client", "delta unpack failed!");
-							return;
-						}
-						
-						if(msg != NETMSG_SNAPEMPTY && ((CSnapshot*)tmpbuffer3)->Crc() != crc)
-						{
-							if(config.debug)
-							{
-								dbg_msg("client", "snapshot crc error #%d - tick=%d wantedcrc=%d gotcrc=%d compressed_size=%d delta_tick=%d",
-									snapcrcerrors, game_tick, crc, ((CSnapshot*)tmpbuffer3)->Crc(), complete_size, delta_tick);
-							}
-								
-							snapcrcerrors++;
-							if(snapcrcerrors > 10)
-							{
-								/* to many errors, send reset */
-								ack_game_tick = -1;
-								client_send_input();
-								snapcrcerrors = 0;
-							}
-							return;
-						}
-						else
-						{
-							if(snapcrcerrors)
-								snapcrcerrors--;
-						}
-
-						/* purge old snapshots */
-						purgetick = delta_tick;
-						if(snapshots[SNAP_PREV] && snapshots[SNAP_PREV]->m_Tick < purgetick)
-							purgetick = snapshots[SNAP_PREV]->m_Tick;
-						if(snapshots[SNAP_CURRENT] && snapshots[SNAP_CURRENT]->m_Tick < purgetick)
-							purgetick = snapshots[SNAP_PREV]->m_Tick;
-						snapshot_storage.PurgeUntil(purgetick);
-						
-						/* add new */
-						snapshot_storage.Add(game_tick, time_get(), snapsize, (CSnapshot*)tmpbuffer3, 1);
-
-						/* add snapshot to demo */
-						if(demorec_isrecording())
-						{
-
-							/* write tick marker */
-							/*
-							DEMOREC_TICKMARKER marker;
-							marker.tick = game_tick;
-							swap_endian(&marker, sizeof(int), sizeof(marker)/sizeof(int));
-							demorec_record_write("TICK", sizeof(marker), &marker);
-							demorec_record_write("SNAP", snapsize, tmpbuffer3);
-							*/
-							
-							/* write snapshot */
-							demorec_record_snapshot(game_tick, tmpbuffer3, snapsize);
-						}
-						
-						/* apply snapshot, cycle pointers */
-						recived_snapshots++;
-
-						current_recv_tick = game_tick;
-						
-						/* we got two snapshots until we see us self as connected */
-						if(recived_snapshots == 2)
-						{
-							/* start at 200ms and work from there */
-							st_init(&predicted_time, game_tick*time_freq()/50);
-							predicted_time.adjustspeed[1] = 1000.0f;
-							st_init(&game_time, (game_tick-1)*time_freq()/50);
-							snapshots[SNAP_PREV] = snapshot_storage.m_pFirst;
-							snapshots[SNAP_CURRENT] = snapshot_storage.m_pLast;
-							local_start_time = time_get();
-							client_set_state(CLIENTSTATE_ONLINE);
-						}
-
-						/* adjust game time */
-						{
-							int64 now = st_get(&game_time, time_get());
-							int64 tickstart = game_tick*time_freq()/50;
-							int64 time_left = (tickstart-now)*1000 / time_freq();
-							/*st_update(&game_time, (game_tick-1)*time_freq()/50);*/
-							st_update(&game_time, &gametime_margin_graph, (game_tick-1)*time_freq()/50, time_left, 0);
-						}
-						
-						/* ack snapshot */
-						ack_game_tick = game_tick;
-					}
-				}
-			}
-		}
-		else
-		{
-			/* game message */
-			if(demorec_isrecording())
-				demorec_record_message(pPacket->m_pData, pPacket->m_DataSize);
-				/* demorec_record_write("MESG", pPacket->data_size, ); */
-
-			modc_message(msg);
-		}
-	}
-}
-
-int client_mapdownload_amount() { return mapdownload_amount; }
-int client_mapdownload_totalsize() { return mapdownload_totalsize; }
-
-static void client_pump_network()
-{
-
-	m_NetClient.Update();
-
-	if(client_state() != CLIENTSTATE_DEMOPLAYBACK)
-	{
-		/* check for errors */
-		if(client_state() != CLIENTSTATE_OFFLINE && m_NetClient.State() == NETSTATE_OFFLINE)
-		{
-			client_set_state(CLIENTSTATE_OFFLINE);
-			client_disconnect();
-			dbg_msg("client", "offline error='%s'", m_NetClient.ErrorString());
-		}
-
-		/* */
-		if(client_state() == CLIENTSTATE_CONNECTING && m_NetClient.State() == NETSTATE_ONLINE)
-		{
-			/* we switched to online */
-			dbg_msg("client", "connected, sending info");
-			client_set_state(CLIENTSTATE_LOADING);
-			client_send_info();
-		}
-	}
-	
-	/* process packets */
-	CNetChunk Packet;
-	while(m_NetClient.Recv(&Packet))
-		client_process_packet(&Packet);
-}
-
-static void client_democallback_snapshot(void *pData, int Size)
-{
-	/* update ticks, they could have changed */
-	const DEMOREC_PLAYBACKINFO *info = demorec_playback_info();			
-	CSnapshotStorage::CHolder *temp;
-	current_tick = info->current_tick;
-	prev_tick = info->previous_tick;
-	
-	/* handle snapshots */
-	temp = snapshots[SNAP_PREV];
-	snapshots[SNAP_PREV] = snapshots[SNAP_CURRENT];
-	snapshots[SNAP_CURRENT] = temp;
-	
-	mem_copy(snapshots[SNAP_CURRENT]->m_pSnap, pData, Size);
-	mem_copy(snapshots[SNAP_CURRENT]->m_pAltSnap, pData, Size);
-	
-	modc_newsnapshot();
-	/*modc_predict();*/
-}
-
-static void client_democallback_message(void *data, int size)
-{
-	int sys = 0;
-	int msg = msg_unpack_start(data, size, &sys);
-	if(!sys)
-		modc_message(msg);
-}
-
-
-const DEMOPLAYBACK_INFO *client_demoplayer_getinfo()
-{
-	static DEMOPLAYBACK_INFO ret;
-	const DEMOREC_PLAYBACKINFO *info = demorec_playback_info();
-	ret.first_tick = info->first_tick;
-	ret.last_tick = info->last_tick;
-	ret.current_tick = info->current_tick;
-	ret.paused = info->paused;
-	ret.speed = info->speed;
-	return &ret;
-}
-
-void client_demoplayer_setpos(float percent)
-{
-	demorec_playback_set(percent);
-}
-
-void client_demoplayer_setspeed(float speed)
-{
-	demorec_playback_setspeed(speed);
-}
-
-void client_demoplayer_setpause(int paused)
-{
-	if(paused)
-		demorec_playback_pause();
-	else
-		demorec_playback_unpause();
-}
-
-static void client_update()
-{
-	if(client_state() == CLIENTSTATE_DEMOPLAYBACK)
-	{
-		demorec_playback_update();
-		if(demorec_isplaying())
-		{
-			/* update timers */
-			const DEMOREC_PLAYBACKINFO *info = demorec_playback_info();			
-			current_tick = info->current_tick;
-			prev_tick = info->previous_tick;
-			intratick = info->intratick;
-			ticktime = info->ticktime;
-		}
-		else
-		{
-			/* disconnect on error */
-			client_disconnect();
-		}
-	}
-	else if(client_state() != CLIENTSTATE_OFFLINE && recived_snapshots >= 3)
-	{
-		/* switch snapshot */
-		int repredict = 0;
-		int64 freq = time_freq();
-		int64 now = st_get(&game_time, time_get());
-		int64 pred_now = st_get(&predicted_time, time_get());
-
-		while(1)
-		{
-			CSnapshotStorage::CHolder *cur = snapshots[SNAP_CURRENT];
-			int64 tickstart = (cur->m_Tick)*time_freq()/50;
-
-			if(tickstart < now)
-			{
-				CSnapshotStorage::CHolder *next = snapshots[SNAP_CURRENT]->m_pNext;
-				if(next)
-				{
-					snapshots[SNAP_PREV] = snapshots[SNAP_CURRENT];
-					snapshots[SNAP_CURRENT] = next;
-					
-					/* set ticks */
-					current_tick = snapshots[SNAP_CURRENT]->m_Tick;
-					prev_tick = snapshots[SNAP_PREV]->m_Tick;
-					
-					if(snapshots[SNAP_CURRENT] && snapshots[SNAP_PREV])
-					{
-						modc_newsnapshot();
-						repredict = 1;
-					}
-				}
-				else
-					break;
-			}
-			else
-				break;
-		}
-
-		if(snapshots[SNAP_CURRENT] && snapshots[SNAP_PREV])
-		{
-			int64 curtick_start = (snapshots[SNAP_CURRENT]->m_Tick)*time_freq()/50;
-			int64 prevtick_start = (snapshots[SNAP_PREV]->m_Tick)*time_freq()/50;
-			/*tg_add(&predicted_time_graph, pred_now, 0); */
-			int prev_pred_tick = (int)(pred_now*50/time_freq());
-			int new_pred_tick = prev_pred_tick+1;
-			static float last_predintra = 0;
-
-			intratick = (now - prevtick_start) / (float)(curtick_start-prevtick_start);
-			ticktime = (now - prevtick_start) / (float)freq; /*(float)SERVER_TICK_SPEED);*/
-
-			curtick_start = new_pred_tick*time_freq()/50;
-			prevtick_start = prev_pred_tick*time_freq()/50;
-			predintratick = (pred_now - prevtick_start) / (float)(curtick_start-prevtick_start);
-			
-			if(new_pred_tick < snapshots[SNAP_PREV]->m_Tick-SERVER_TICK_SPEED || new_pred_tick > snapshots[SNAP_PREV]->m_Tick+SERVER_TICK_SPEED)
-			{
-				dbg_msg("client", "prediction time reset!");
-				st_init(&predicted_time, snapshots[SNAP_CURRENT]->m_Tick*time_freq()/50);
-			}
-			
-			if(new_pred_tick > current_predtick)
-			{
-				last_predintra = predintratick;
-				current_predtick = new_pred_tick;
-				repredict = 1;
-				
-				/* send input */
-				client_send_input();
-			}
-			
-			last_predintra = predintratick;
-		}
-
-		/* only do sane predictions */
-		if(repredict)
-		{
-			if(current_predtick > current_tick && current_predtick < current_tick+50)
-				modc_predict();
-		}
-		
-		/* fetch server info if we don't have it */
-		if(client_state() >= CLIENTSTATE_LOADING &&
-			current_server_info_requesttime >= 0 &&
-			time_get() > current_server_info_requesttime)
-		{
-			client_serverbrowse_request(&server_address);
-			current_server_info_requesttime = time_get()+time_freq()*2;
-		}
-	}
-
-	/* STRESS TEST: join the server again */
-	if(config.dbg_stress)
-	{
-		static int64 action_taken = 0;
-		int64 now = time_get();
-		if(client_state() == CLIENTSTATE_OFFLINE)
-		{
-			if(now > action_taken+time_freq()*2)
-			{
-				dbg_msg("stress", "reconnecting!");
-				client_connect(config.dbg_stress_server);
-				action_taken = now;
-			}
-		}
-		else
-		{
-			/*if(now > action_taken+time_freq()*(10+config.dbg_stress))
-			{
-				dbg_msg("stress", "disconnecting!");
-				client_disconnect();
-				action_taken = now;
-			}*/
-		}
-	}
-	
-	/* pump the network */
-	client_pump_network();
-	
-	/* update the maser server registry */
-	mastersrv_update();
-	
-	/* update the server browser */
-	client_serverbrowse_update();
-}
-
-
-static void client_versionupdate()
-{
-	static int state = 0;
-	static HOSTLOOKUP version_serveraddr;
-	
-	if(state == 0)
-	{
-		engine_hostlookup(&version_serveraddr, config.cl_version_server);
-		state++;
-	}
-	else if(state == 1)
-	{
-		if(jobs_status(&version_serveraddr.job) == JOBSTATUS_DONE)
-		{
-			CNetChunk Packet;
-			
-			mem_zero(&Packet, sizeof(Packet));
-			
-			version_serveraddr.addr.port = VERSIONSRV_PORT;
-			
-			Packet.m_ClientID = -1;
-			Packet.m_Address = version_serveraddr.addr;
-			Packet.m_pData = VERSIONSRV_GETVERSION;
-			Packet.m_DataSize = sizeof(VERSIONSRV_GETVERSION);
-			Packet.m_Flags = NETSENDFLAG_CONNLESS;
-			
-			m_NetClient.Send(&Packet);
-			state++;
-		}
-	}
-}
-
-static void client_run()
-{
-	NETADDR bindaddr;
-	int64 reporttime = time_get();
-	int64 reportinterval = time_freq()*1;
-
-	static PERFORMACE_INFO rootscope = {"root", 0};
-	perf_start(&rootscope);
-
-	local_start_time = time_get();
-	snapshot_parts = 0;
-	
-	/* init graphics and sound */
-	m_pGraphics = CreateEngineGraphics();
-	if(m_pGraphics->Init() != 0)
-		return;
-
-	/* start refreshing addresses while we load */
-	mastersrv_refresh_addresses();
-	
-	/* init the editor */
-	m_pEditor = CreateEditor();
-	m_pEditor->Init(m_pGraphics);
-
-	/* sound is allowed to fail */
-	snd_init();
-
-	/* load data */
-	if(!client_load_data())
-		return;
-
-	/* init the mod */
-	m_pGameClient = CreateGameClient(&m_Client);
-	modc_init();
-	dbg_msg("client", "version %s", modc_net_version());
-	
-	/* open socket */
-	mem_zero(&bindaddr, sizeof(bindaddr));
-	m_NetClient.Open(bindaddr, 0);
-	
-	/* connect to the server if wanted */
-	/*
-	if(config.cl_connect[0] != 0)
-		client_connect(config.cl_connect);
-	config.cl_connect[0] = 0;
-	*/
-
-	/* */
-	graph_init(&fps_graph, 0.0f, 200.0f);
-	
-	/* never start with the editor */
-	config.cl_editor = 0;
-		
-	inp_mouse_mode_relative();
-	
-	while (1)
-	{	
-		static PERFORMACE_INFO rootscope = {"root", 0};
-		int64 frame_start_time = time_get();
-		frames++;
-		
-		perf_start(&rootscope);
-
-		/* */
-		client_versionupdate();
-		
-		/* handle pending connects */
-		if(cmd_connect[0])
-		{
-			client_connect(cmd_connect);
-			cmd_connect[0] = 0;
-		}
-		
-		/* update input */
-		{
-			static PERFORMACE_INFO scope = {"inp_update", 0};
-			perf_start(&scope);
-			inp_update();
-			perf_end();
-		}
-
-		/* update sound */		
-		{
-			static PERFORMACE_INFO scope = {"snd_update", 0};
-			perf_start(&scope);
-			snd_update();
-			perf_end();
-		}
-		
-		/* release focus */
-		if(!Graphics()->WindowActive())
-		{
-			if(window_must_refocus == 0)
-				inp_mouse_mode_absolute();
-			window_must_refocus = 1;
-		}
-		else if (config.dbg_focus && inp_key_pressed(KEY_ESCAPE))
-		{
-			inp_mouse_mode_absolute();
-			window_must_refocus = 1;
-		}
-
-		/* refocus */
-		if(window_must_refocus && Graphics()->WindowActive())
-		{
-			if(window_must_refocus < 3)
-			{
-				inp_mouse_mode_absolute();
-				window_must_refocus++;
-			}
-
-			if(inp_key_pressed(KEY_MOUSE_1))
-			{
-				inp_mouse_mode_relative();
-				window_must_refocus = 0;
-			}
-		}
-
-		/* panic quit button */
-		if(inp_key_pressed(KEY_LCTRL) && inp_key_pressed(KEY_LSHIFT) && inp_key_pressed('q'))
-			break;
-
-		if(inp_key_pressed(KEY_LCTRL) && inp_key_pressed(KEY_LSHIFT) && inp_key_down('d'))
-			config.debug ^= 1;
-
-		if(inp_key_pressed(KEY_LCTRL) && inp_key_pressed(KEY_LSHIFT) && inp_key_down('g'))
-			config.dbg_graphs ^= 1;
-
-		if(inp_key_pressed(KEY_LCTRL) && inp_key_pressed(KEY_LSHIFT) && inp_key_down('e'))
-		{
-			config.cl_editor = config.cl_editor^1;
-			inp_mouse_mode_relative();
-		}
-		
-		/*
-		if(!gfx_window_open())
-			break;
-		*/
-			
-		/* render */
-		if(config.cl_editor)
-		{
-			client_update();
-			m_pEditor->UpdateAndRender();
-			m_pGraphics->Swap();
-		}
-		else
-		{
-			{
-				static PERFORMACE_INFO scope = {"client_update", 0};
-				perf_start(&scope);
-				client_update();
-				perf_end();
-			}
-			
-			if(config.dbg_stress)
-			{
-				if((frames%10) == 0)
-				{
-					client_render();
-					m_pGraphics->Swap();
-				}
-			}
-			else
-			{
-				{
-					static PERFORMACE_INFO scope = {"client_render", 0};
-					perf_start(&scope);
-					client_render();
-					perf_end();
-				}
-
-				{
-					static PERFORMACE_INFO scope = {"gfx_swap", 0};
-					perf_start(&scope);
-					m_pGraphics->Swap();
-					perf_end();
-				}
-			}
-		}
-
-		perf_end();
-
-		
-		/* check conditions */
-		if(client_state() == CLIENTSTATE_QUITING)
-			break;
-
-		/* be nice */
-		if(config.dbg_stress)
-			thread_sleep(5);
-		else if(config.cl_cpu_throttle || !Graphics()->WindowActive())
-			thread_sleep(1);
-			
-		if(config.dbg_hitch)
-		{
-			thread_sleep(config.dbg_hitch);
-			config.dbg_hitch = 0;
-		}
-		
-		if(reporttime < time_get())
-		{
-			if(0 && config.debug)
-			{
-				dbg_msg("client/report", "fps=%.02f (%.02f %.02f) netstate=%d",
-					frames/(float)(reportinterval/time_freq()),
-					1.0f/frametime_high,
-					1.0f/frametime_low,
-					m_NetClient.State());
-			}
-			frametime_low = 1;
-			frametime_high = 0;
-			frames = 0;
-			reporttime += reportinterval;
-			perf_next();
-			
-			if(config.dbg_pref)
-				perf_dump(&rootscope);
-		}
-		
-		/* update frametime */
-		frametime = (time_get()-frame_start_time)/(float)time_freq();
-		if(frametime < frametime_low)
-			frametime_low = frametime;
-		if(frametime > frametime_high)
-			frametime_high = frametime;
-		
-		graph_add(&fps_graph, 1.0f/frametime, 1,1,1);
-	}
-	
-	modc_shutdown();
-	client_disconnect();
-
-	m_pGraphics->Shutdown();
-	snd_shutdown();
-}
-
-void gfx_swap()
-{
-	m_pGraphics->Swap();
-}
-
-static void con_connect(void *result, void *user_data)
-{
-	str_copy(cmd_connect, console_arg_string(result, 0), sizeof(cmd_connect));
-}
-
-static void con_disconnect(void *result, void *user_data)
-{
-	client_disconnect();
-}
-
-static void con_quit(void *result, void *user_data)
-{
-	client_quit();
-}
-
-static void con_ping(void *result, void *user_data)
-{
-	msg_pack_start_system(NETMSG_PING, 0);
-	msg_pack_end();
-	client_send_msg();
-	ping_start_time = time_get();
-}
-
-static void con_screenshot(void *result, void *user_data)
-{
-	Graphics()->TakeScreenshot();
-}
-
-static void con_rcon(void *result, void *user_data)
-{
-	client_rcon(console_arg_string(result, 0));
-}
-
-static void con_rcon_auth(void *result, void *user_data)
-{
-	client_rcon_auth("", console_arg_string(result, 0));
-}
-
-static void con_addfavorite(void *result, void *user_data)
-{
-	NETADDR addr;
-	if(net_addr_from_str(&addr, console_arg_string(result, 0)) == 0)
-		client_serverbrowse_addfavorite(addr);
-}
-
-const char *client_demoplayer_play(const char *filename)
-{
-	int crc;
-	const char *error;
-	client_disconnect();
-	m_NetClient.ResetErrorString();
-	
-	/* try to start playback */
-	demorec_playback_registercallbacks(client_democallback_snapshot, client_democallback_message);
-	
-	if(demorec_playback_load(filename))
-		return "error loading demo";
-	
-	/* load map */
-	crc = (demorec_playback_info()->header.crc[0]<<24)|
-		(demorec_playback_info()->header.crc[1]<<16)|
-		(demorec_playback_info()->header.crc[2]<<8)|
-		(demorec_playback_info()->header.crc[3]);
-	error = client_load_map_search(demorec_playback_info()->header.map, crc);
-	if(error)
-	{
-		client_disconnect_with_reason(error);	
-		return error;
-	}
-	
-	modc_connected();
-	
-	/* setup buffers */	
-	mem_zero(demorec_snapshotdata, sizeof(demorec_snapshotdata));
-
-	snapshots[SNAP_CURRENT] = &demorec_snapshotholders[SNAP_CURRENT];
-	snapshots[SNAP_PREV] = &demorec_snapshotholders[SNAP_PREV];
-	
-	snapshots[SNAP_CURRENT]->m_pSnap = (CSnapshot *)demorec_snapshotdata[SNAP_CURRENT][0];
-	snapshots[SNAP_CURRENT]->m_pAltSnap = (CSnapshot *)demorec_snapshotdata[SNAP_CURRENT][1];
-	snapshots[SNAP_CURRENT]->m_SnapSize = 0;
-	snapshots[SNAP_CURRENT]->m_Tick = -1;
-	
-	snapshots[SNAP_PREV]->m_pSnap = (CSnapshot *)demorec_snapshotdata[SNAP_PREV][0];
-	snapshots[SNAP_PREV]->m_pAltSnap = (CSnapshot *)demorec_snapshotdata[SNAP_PREV][1];
-	snapshots[SNAP_PREV]->m_SnapSize = 0;
-	snapshots[SNAP_PREV]->m_Tick = -1;
-
-	/* enter demo playback state */
-	client_set_state(CLIENTSTATE_DEMOPLAYBACK);
-	
-	demorec_playback_play();
-	modc_entergame();
-	
-	return 0;
-}
-
-static void con_play(void *result, void *user_data)
-{
-	client_demoplayer_play(console_arg_string(result, 0));
-}
-
-static void con_record(void *result, void *user_data)
-{
-	if(state != CLIENTSTATE_ONLINE)
-		dbg_msg("demorec/record", "client is not online");
-	else
-	{
-		char filename[512];
-		str_format(filename, sizeof(filename), "demos/%s.demo", console_arg_string(result, 0));
-		demorec_record_start(filename, modc_net_version(), current_map, current_map_crc, "client");
-	}
-}
-
-static void con_stoprecord(void *result, void *user_data)
-{
-	demorec_record_stop();
-}
-
-static void con_serverdummy(void *result, void *user_data)
-{
-	dbg_msg("client", "this command is not available on the client");
-}
-
-static void client_register_commands()
-{
-	MACRO_REGISTER_COMMAND("quit", "", CFGFLAG_CLIENT, con_quit, 0x0, "Quit Teeworlds");
-	MACRO_REGISTER_COMMAND("exit", "", CFGFLAG_CLIENT, con_quit, 0x0, "Quit Teeworlds");
-	MACRO_REGISTER_COMMAND("connect", "s", CFGFLAG_CLIENT, con_connect, 0x0, "Connect to the specified host/ip");
-	MACRO_REGISTER_COMMAND("disconnect", "", CFGFLAG_CLIENT, con_disconnect, 0x0, "Disconnect from the server");
-	MACRO_REGISTER_COMMAND("ping", "", CFGFLAG_CLIENT, con_ping, 0x0, "Ping the current server");
-	MACRO_REGISTER_COMMAND("screenshot", "", CFGFLAG_CLIENT, con_screenshot, 0x0, "Take a screenshot");
-	MACRO_REGISTER_COMMAND("rcon", "r", CFGFLAG_CLIENT, con_rcon, 0x0, "Send specified command to rcon");
-	MACRO_REGISTER_COMMAND("rcon_auth", "s", CFGFLAG_CLIENT, con_rcon_auth, 0x0, "Authenticate to rcon");
-
-	MACRO_REGISTER_COMMAND("play", "r", CFGFLAG_CLIENT, con_play, 0x0, "Play the file specified");
-	MACRO_REGISTER_COMMAND("record", "s", CFGFLAG_CLIENT, con_record, 0, "Record to the file");
-	MACRO_REGISTER_COMMAND("stoprecord", "", CFGFLAG_CLIENT, con_stoprecord, 0, "Stop recording");
-
-	MACRO_REGISTER_COMMAND("add_favorite", "s", CFGFLAG_CLIENT, con_addfavorite, 0x0, "Add a server as a favorite");
-	
-	/* register server dummy commands for tab completion */
-	MACRO_REGISTER_COMMAND("kick", "i", CFGFLAG_SERVER, con_serverdummy, 0, "Kick player with specified id");
-	MACRO_REGISTER_COMMAND("ban", "s?i", CFGFLAG_SERVER, con_serverdummy, 0, "Ban player with ip/id for x minutes");
-	MACRO_REGISTER_COMMAND("unban", "s", CFGFLAG_SERVER, con_serverdummy, 0, "Unban ip");
-	MACRO_REGISTER_COMMAND("bans", "", CFGFLAG_SERVER, con_serverdummy, 0, "Show banlist");
-	MACRO_REGISTER_COMMAND("status", "", CFGFLAG_SERVER, con_serverdummy, 0, "List players");
-	MACRO_REGISTER_COMMAND("shutdown", "", CFGFLAG_SERVER, con_serverdummy, 0, "Shut down");
-	/*MACRO_REGISTER_COMMAND("record", "", CFGFLAG_SERVER, con_serverdummy, 0);
-	MACRO_REGISTER_COMMAND("stoprecord", "", CFGFLAG_SERVER, con_serverdummy, 0);*/
-}
-
-void client_save_line(const char *line)
-{
-	engine_config_write_line(line);	
-}
-
-const char *client_user_directory()
-{
-	static char path[1024] = {0};
-	fs_storage_path("Teeworlds", path, sizeof(path));
-	return path;
-}
-
-#if defined(CONF_PLATFORM_MACOSX)
-int SDL_main(int argc, char **argv)
-#else
-int main(int argc, char **argv)
-#endif
-{
-	/* init the engine */
-	dbg_msg("client", "starting...");
-	engine_init("Teeworlds");
-	
-	/* register all console commands */
-	client_register_commands();
-	modc_console_init();
-	
-	/* parse the command line arguments */
-	engine_parse_arguments(argc, argv);
-
-	/* execute config file */
-	console_execute_file("settings.cfg");
-	
-	/* run the client*/
-	client_run();
-	
-	/* write down the config and quit */
-	if(engine_config_write_start() == 0)
-	{
-		config_save();
-		client_serverbrowse_save();
-		modc_save_config();
-		engine_config_write_stop();
-	}
-	
-	return 0;
-}
diff --git a/src/engine/client/ec_gfx.cpp b/src/engine/client/ec_gfx.cpp
deleted file mode 100644
index 5632581a..00000000
--- a/src/engine/client/ec_gfx.cpp
+++ /dev/null
@@ -1,992 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-
-#include <base/detect.h>
-
-#include "SDL.h"
-
-#ifdef CONF_FAMILY_WINDOWS
-	#define WIN32_LEAN_AND_MEAN
-	#include <windows.h>
-#endif
-
-#ifdef CONF_PLATFORM_MACOSX
-	#include <OpenGL/gl.h>
-	#include <OpenGL/glu.h>
-#else
-	#include <GL/gl.h>
-	#include <GL/glu.h>
-#endif
-
-#include <base/system.h>
-#include <engine/external/pnglite/pnglite.h>
-
-#include <engine/e_client_interface.h>
-#include <engine/e_engine.h>
-#include <engine/e_config.h>
-#include <engine/e_keys.h>
-
-#include <string.h>
-#include <stdio.h>
-#include <math.h>
-
-/* compressed textures */
-#define GL_COMPRESSED_RGB_ARB 0x84ED
-#define GL_COMPRESSED_RGBA_ARB 0x84EE
-#define GL_COMPRESSED_ALPHA_ARB 0x84E9
-
-#define TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
-
-
-void gfx_font_init();
-
-VIDEO_MODE fakemodes[] = {
-	{320,240,8,8,8}, {400,300,8,8,8}, {640,480,8,8,8},
-	{720,400,8,8,8}, {768,576,8,8,8}, {800,600,8,8,8},
-	{1024,600,8,8,8}, {1024,768,8,8,8}, {1152,864,8,8,8},
-	{1280,768,8,8,8}, {1280,800,8,8,8}, {1280,960,8,8,8},
-	{1280,1024,8,8,8}, {1368,768,8,8,8}, {1400,1050,8,8,8},
-	{1440,900,8,8,8}, {1440,1050,8,8,8}, {1600,1000,8,8,8},
-	{1600,1200,8,8,8}, {1680,1050,8,8,8}, {1792,1344,8,8,8},
-	{1800,1440,8,8,8}, {1856,1392,8,8,8}, {1920,1080,8,8,8},
-	{1920,1200,8,8,8}, {1920,1440,8,8,8}, {1920,2400,8,8,8},
-	{2048,1536,8,8,8},
-		
-	{320,240,5,6,5}, {400,300,5,6,5}, {640,480,5,6,5},
-	{720,400,5,6,5}, {768,576,5,6,5}, {800,600,5,6,5},
-	{1024,600,5,6,5}, {1024,768,5,6,5}, {1152,864,5,6,5},
-	{1280,768,5,6,5}, {1280,800,5,6,5}, {1280,960,5,6,5},
-	{1280,1024,5,6,5}, {1368,768,5,6,5}, {1400,1050,5,6,5},
-	{1440,900,5,6,5}, {1440,1050,5,6,5}, {1600,1000,5,6,5},
-	{1600,1200,5,6,5}, {1680,1050,5,6,5}, {1792,1344,5,6,5},
-	{1800,1440,5,6,5}, {1856,1392,5,6,5}, {1920,1080,5,6,5},
-	{1920,1200,5,6,5}, {1920,1440,5,6,5}, {1920,2400,5,6,5},
-	{2048,1536,5,6,5}
-};
-
-int gfx_get_video_modes(VIDEO_MODE *list, int maxcount)
-{
-	int num_modes = sizeof(fakemodes)/sizeof(VIDEO_MODE);
-	SDL_Rect **modes;
-
-	if(config.gfx_display_all_modes)
-	{
-		int count = sizeof(fakemodes)/sizeof(VIDEO_MODE);
-		mem_copy(list, fakemodes, sizeof(fakemodes));
-		if(maxcount < count)
-			count = maxcount;
-		return count;
-	}
-	
-	/* TODO: fix this code on osx or windows */
-		
-	modes = SDL_ListModes(NULL, SDL_OPENGL|SDL_GL_DOUBLEBUFFER|SDL_FULLSCREEN);
-	if(modes == NULL)
-	{
-		/* no modes */
-		num_modes = 0;
-	}
-	else if(modes == (SDL_Rect**)-1)
-	{
-		/* all modes */
-	}
-	else
-	{
-		int i;
-		num_modes = 0;
-		for(i = 0; modes[i]; ++i)
-		{
-			if(num_modes == maxcount)
-				break;
-			list[num_modes].width = modes[i]->w;
-			list[num_modes].height = modes[i]->h;
-			list[num_modes].red = 8;
-			list[num_modes].green = 8;
-			list[num_modes].blue = 8;
-			num_modes++;
-		}
-	}
-	
-	return num_modes;
-}
-
-
-#include "graphics.h"
-
-class CGraphics_OpenGL : public IEngineGraphics
-{
-protected:
-	/* */
-	typedef struct { float x, y, z; } CPoint;
-	typedef struct { float u, v; } CTexCoord;
-	typedef struct { float r, g, b, a; } CColor;
-
-	typedef struct
-	{
-		CPoint m_Pos;
-		CTexCoord m_Tex;
-		CColor m_Color;
-	} CVertex;
-	
-	enum
-	{
-		MAX_VERTICES = 32*1024,
-		MAX_TEXTURES = 1024*4,
-		
-		DRAWING_QUADS=1,
-		DRAWING_LINES=2		
-	};
-
-	CVertex m_aVertices[MAX_VERTICES];
-	int m_NumVertices;
-
-	CColor m_aColor[4];
-	CTexCoord m_aTexture[4];
-
-	bool m_RenderEnable;
-
-	float m_Rotation;
-	int m_Drawing;
-	bool m_DoScreenshot;
-
-	float m_ScreenX0;
-	float m_ScreenY0;
-	float m_ScreenX1;
-	float m_ScreenY1;
-
-	int m_InvalidTexture;
-
-	struct CTexture
-	{
-		GLuint tex;
-		int memsize;
-		int flags;
-		int next;
-	};
-
-	enum
-	{
-		
-	};
-
-	CTexture m_aTextures[MAX_TEXTURES];
-	int m_FirstFreeTexture;
-	int m_TextureMemoryUsage;
-
-
-	void Flush()
-	{
-		if(m_NumVertices == 0)
-			return;
-			
-		//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
-		//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
-		glVertexPointer(3, GL_FLOAT,
-				sizeof(CVertex),
-				(char*)m_aVertices);
-		glTexCoordPointer(2, GL_FLOAT,
-				sizeof(CVertex),
-				(char*)m_aVertices + sizeof(float)*3);
-		glColorPointer(4, GL_FLOAT,
-				sizeof(CVertex),
-				(char*)m_aVertices + sizeof(float)*5);
-		glEnableClientState(GL_VERTEX_ARRAY);
-		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-		glEnableClientState(GL_COLOR_ARRAY);
-		
-		if(m_RenderEnable)
-		{
-			if(m_Drawing == DRAWING_QUADS)
-				glDrawArrays(GL_QUADS, 0, m_NumVertices);
-			else if(m_Drawing == DRAWING_LINES)
-				glDrawArrays(GL_LINES, 0, m_NumVertices);
-		}
-		
-		/* Reset pointer */
-		m_NumVertices = 0;
-	}
-
-	void AddVertices(int count)
-	{
-		m_NumVertices += count;
-		if((m_NumVertices + count) >= MAX_VERTICES)
-			Flush();
-	}
-	
-	void Rotate(CPoint *pCenter, CPoint *pPoint)
-	{
-		float x = pPoint->x - pCenter->x;
-		float y = pPoint->y - pCenter->y;
-		pPoint->x = x * cosf(m_Rotation) - y * sinf(m_Rotation) + pCenter->x;
-		pPoint->y = x * sinf(m_Rotation) + y * cosf(m_Rotation) + pCenter->y;
-	}
-	
-	
-
-
-	static unsigned char sample(int w, int h, const unsigned char *data, int u, int v, int offset)
-	{
-		return (data[(v*w+u)*4+offset]+
-		data[(v*w+u+1)*4+offset]+
-		data[((v+1)*w+u)*4+offset]+
-		data[((v+1)*w+u+1)*4+offset])/4;
-	}	
-public:
-	CGraphics_OpenGL()
-	{
-		m_NumVertices = 0;
-		
-		m_ScreenX0 = 0;
-		m_ScreenY0 = 0;
-		m_ScreenX1 = 0;
-		m_ScreenY1 = 0;
-		
-		m_ScreenWidth = -1;
-		m_ScreenHeight = -1;
-		
-		m_Rotation = 0;
-		m_Drawing = 0;
-		m_InvalidTexture = 0;
-		
-		m_TextureMemoryUsage = 0;
-		
-		m_RenderEnable = true;
-		m_DoScreenshot = false;
-	}
-	
-
-	virtual void ClipEnable(int x, int y, int w, int h)
-	{
-		//if(no_gfx) return;
-		glScissor(x, ScreenHeight()-(y+h), w, h);
-		glEnable(GL_SCISSOR_TEST);
-	}
-
-	virtual void ClipDisable()
-	{
-		//if(no_gfx) return;
-		glDisable(GL_SCISSOR_TEST);
-	}
-		
-
-	virtual void BlendNone()
-	{
-		glDisable(GL_BLEND);
-	}
-
-	virtual void BlendNormal()
-	{
-		glEnable(GL_BLEND);
-		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-	}
-
-	virtual void BlendAdditive()
-	{
-		glEnable(GL_BLEND);
-		glBlendFunc(GL_SRC_ALPHA, GL_ONE);
-	}
-
-	//int gfx_memory_usage() { return m_MemoryUsage; }	
-		
-	virtual void MapScreen(float tl_x, float tl_y, float br_x, float br_y)
-	{
-		m_ScreenX0 = tl_x;
-		m_ScreenY0 = tl_y;
-		m_ScreenX1 = br_x;
-		m_ScreenY1 = br_y;
-		glMatrixMode(GL_PROJECTION);
-		glLoadIdentity();
-		glOrtho(tl_x, br_x, br_y, tl_y, 1.0f, 10.f);
-	}
-
-	virtual void GetScreen(float *tl_x, float *tl_y, float *br_x, float *br_y)
-	{
-		*tl_x = m_ScreenX0;
-		*tl_y = m_ScreenY0;
-		*br_x = m_ScreenX1;
-		*br_y = m_ScreenY1;
-	}
-
-	virtual void LinesBegin()
-	{
-		dbg_assert(m_Drawing == 0, "called begin twice");
-		m_Drawing = DRAWING_LINES;
-		SetColor(1,1,1,1);
-	}
-
-	virtual void LinesEnd()
-	{
-		dbg_assert(m_Drawing == DRAWING_LINES, "called end without begin");
-		Flush();
-		m_Drawing = 0;
-	}
-
-	virtual void LinesDraw(float x0, float y0, float x1, float y1)
-	{
-		dbg_assert(m_Drawing == DRAWING_LINES, "called draw without begin");
-		
-		m_aVertices[m_NumVertices].m_Pos.x = x0;
-		m_aVertices[m_NumVertices].m_Pos.y = y0;
-		m_aVertices[m_NumVertices].m_Tex = m_aTexture[0];
-		m_aVertices[m_NumVertices].m_Color = m_aColor[0];
-
-		m_aVertices[m_NumVertices + 1].m_Pos.x = x1;
-		m_aVertices[m_NumVertices + 1].m_Pos.y = y1;
-		m_aVertices[m_NumVertices + 1].m_Tex = m_aTexture[1];
-		m_aVertices[m_NumVertices + 1].m_Color = m_aColor[1];
-		
-		AddVertices(2);
-	}
-	
-
-	
-	virtual int UnloadTexture(int Index)
-	{
-		if(Index == m_InvalidTexture)
-			return 0;
-			
-		if(Index < 0)
-			return 0;
-			
-		glDeleteTextures(1, &m_aTextures[Index].tex);
-		m_aTextures[Index].next = m_FirstFreeTexture;
-		m_TextureMemoryUsage -= m_aTextures[Index].memsize;
-		m_FirstFreeTexture = Index;
-		return 0;
-	}
-
-
-	virtual int LoadTextureRaw(int Width, int Height, int Format, const void *pData, int StoreFormat, int Flags)
-	{
-		int mipmap = 1;
-		unsigned char *texdata = (unsigned char *)pData;
-		unsigned char *tmpdata = 0;
-		int oglformat = 0;
-		int store_oglformat = 0;
-		int tex = 0;
-		
-		/* don't waste memory on texture if we are stress testing */
-		if(config.dbg_stress)
-			return 	m_InvalidTexture;
-		
-		/* grab texture */
-		tex = m_FirstFreeTexture;
-		m_FirstFreeTexture = m_aTextures[tex].next;
-		m_aTextures[tex].next = -1;
-		
-		/* resample if needed */
-		if(!(Flags&TEXLOAD_NORESAMPLE) && config.gfx_texture_quality==0)
-		{
-			if(Width > 16 && Height > 16 && Format == IMG_RGBA)
-			{
-				unsigned char *tmpdata;
-				int c = 0;
-				int x, y;
-
-				tmpdata = (unsigned char *)mem_alloc(Width*Height*4, 1);
-
-				Width/=2;
-				Height/=2;
-
-				for(y = 0; y < Height; y++)
-					for(x = 0; x < Width; x++, c++)
-					{
-						tmpdata[c*4] = sample(Width*2, Height*2, texdata, x*2,y*2, 0);
-						tmpdata[c*4+1] = sample(Width*2, Height*2, texdata, x*2,y*2, 1);
-						tmpdata[c*4+2] = sample(Width*2, Height*2, texdata, x*2,y*2, 2);
-						tmpdata[c*4+3] = sample(Width*2, Height*2, texdata, x*2,y*2, 3);
-					}
-				texdata = tmpdata;
-			}
-		}
-		
-		oglformat = GL_RGBA;
-		if(Format == IMG_RGB)
-			oglformat = GL_RGB;
-		else if(Format == IMG_ALPHA)
-			oglformat = GL_ALPHA;
-		
-		/* upload texture */
-		if(config.gfx_texture_compression)
-		{
-			store_oglformat = GL_COMPRESSED_RGBA_ARB;
-			if(StoreFormat == IMG_RGB)
-				store_oglformat = GL_COMPRESSED_RGB_ARB;
-			else if(StoreFormat == IMG_ALPHA)
-				store_oglformat = GL_COMPRESSED_ALPHA_ARB;
-		}
-		else
-		{
-			store_oglformat = GL_RGBA;
-			if(StoreFormat == IMG_RGB)
-				store_oglformat = GL_RGB;
-			else if(StoreFormat == IMG_ALPHA)
-				store_oglformat = GL_ALPHA;
-		}
-			
-		glGenTextures(1, &m_aTextures[tex].tex);
-		glBindTexture(GL_TEXTURE_2D, m_aTextures[tex].tex);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
-		gluBuild2DMipmaps(GL_TEXTURE_2D, store_oglformat, Width, Height, oglformat, GL_UNSIGNED_BYTE, texdata);
-		
-		/* calculate memory usage */
-		{
-			int pixel_size = 4;
-			if(StoreFormat == IMG_RGB)
-				pixel_size = 3;
-			else if(StoreFormat == IMG_ALPHA)
-				pixel_size = 1;
-
-			m_aTextures[tex].memsize = Width*Height*pixel_size;
-			if(mipmap)
-			{
-				while(Width > 2 && Height > 2)
-				{
-					Width>>=1;
-					Height>>=1;
-					m_aTextures[tex].memsize += Width*Height*pixel_size;
-				}
-			}
-		}
-		
-		m_TextureMemoryUsage += m_aTextures[tex].memsize;
-		mem_free(tmpdata);
-		return tex;
-	}
-
-	/* simple uncompressed RGBA loaders */
-	virtual int LoadTexture(const char *pFilename, int StoreFormat, int Flags)
-	{
-		int l = strlen(pFilename);
-		int id;
-		IMAGE_INFO img;
-		
-		if(l < 3)
-			return -1;
-		if(LoadPNG(&img, pFilename))
-		{
-			if (StoreFormat == IMG_AUTO)
-				StoreFormat = img.format;
-
-			id = LoadTextureRaw(img.width, img.height, img.format, img.data, StoreFormat, Flags);
-			mem_free(img.data);
-			return id;
-		}
-		
-		return m_InvalidTexture;
-	}
-
-	virtual int LoadPNG(IMAGE_INFO *pImg, const char *pFilename)
-	{
-		char aCompleteFilename[512];
-		unsigned char *pBuffer;
-		png_t png;
-		
-		/* open file for reading */
-		png_init(0,0);
-
-		engine_getpath(aCompleteFilename, sizeof(aCompleteFilename), pFilename, IOFLAG_READ);
-		
-		if(png_open_file(&png, aCompleteFilename) != PNG_NO_ERROR)
-		{
-			dbg_msg("game/png", "failed to open file. filename='%s'", aCompleteFilename);
-			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'", aCompleteFilename);
-			png_close_file(&png);
-			return 0;
-		}
-			
-		pBuffer = (unsigned char *)mem_alloc(png.width * png.height * png.bpp, 1);
-		png_get_data(&png, pBuffer);
-		png_close_file(&png);
-		
-		pImg->width = png.width;
-		pImg->height = png.height;
-		if(png.color_type == PNG_TRUECOLOR)
-			pImg->format = IMG_RGB;
-		else if(png.color_type == PNG_TRUECOLOR_ALPHA)
-			pImg->format = IMG_RGBA;
-		pImg->data = pBuffer;
-		return 1;
-	}
-
-	void ScreenshotDirect(const char *filename)
-	{
-		/* fetch image data */
-		int y;
-		int w = m_ScreenWidth;
-		int h = m_ScreenHeight;
-		unsigned char *pixel_data = (unsigned char *)mem_alloc(w*(h+1)*4, 1);
-		unsigned char *temp_row = pixel_data+w*h*4;
-		glReadPixels(0,0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixel_data);
-		
-		/* flip the pixel because opengl works from bottom left corner */
-		for(y = 0; y < h/2; y++)
-		{
-			mem_copy(temp_row, pixel_data+y*w*4, w*4);
-			mem_copy(pixel_data+y*w*4, pixel_data+(h-y-1)*w*4, w*4);
-			mem_copy(pixel_data+(h-y-1)*w*4, temp_row,w*4);
-		}
-		
-		/* find filename */
-		{
-			char wholepath[1024];
-			png_t png;
-
-			engine_savepath(filename, wholepath, sizeof(wholepath));
-		
-			/* save png */
-			dbg_msg("client", "saved screenshot to '%s'", wholepath);
-			png_open_file_write(&png, wholepath);
-			png_set_data(&png, w, h, 8, PNG_TRUECOLOR_ALPHA, (unsigned char *)pixel_data);
-			png_close_file(&png);
-		}
-
-		/* clean up */
-		mem_free(pixel_data);
-	}
-
-	virtual void TextureSet(int TextureID)
-	{
-		dbg_assert(m_Drawing == 0, "called Graphics()->TextureSet within begin");
-		if(TextureID == -1)
-		{
-			glDisable(GL_TEXTURE_2D);
-		}
-		else
-		{
-			glEnable(GL_TEXTURE_2D);
-			glBindTexture(GL_TEXTURE_2D, m_aTextures[TextureID].tex);
-		}
-	}
-
-	virtual void Clear(float r, float g, float b)
-	{
-		glClearColor(r,g,b,0.0f);
-		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-	}
-
-	virtual void QuadsBegin()
-	{
-		dbg_assert(m_Drawing == 0, "called quads_begin twice");
-		m_Drawing = DRAWING_QUADS;
-		
-		QuadsSetSubset(0,0,1,1);
-		QuadsSetRotation(0);
-		SetColor(1,1,1,1);
-	}
-
-	virtual void QuadsEnd()
-	{
-		dbg_assert(m_Drawing == DRAWING_QUADS, "called quads_end without begin");
-		Flush();
-		m_Drawing = 0;
-	}
-
-	virtual void QuadsSetRotation(float Angle)
-	{
-		dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsSetRotation without begin");
-		m_Rotation = Angle;
-	}
-
-	virtual void SetColorVertex(int i, float r, float g, float b, float a)
-	{
-		dbg_assert(m_Drawing != 0, "called gfx_quads_setcolorvertex without begin");
-		m_aColor[i].r = r;
-		m_aColor[i].g = g;
-		m_aColor[i].b = b;
-		m_aColor[i].a = a;
-	}
-
-	virtual void SetColor(float r, float g, float b, float a)
-	{
-		dbg_assert(m_Drawing != 0, "called gfx_quads_setcolor without begin");
-		SetColorVertex(0, r, g, b, a);
-		SetColorVertex(1, r, g, b, a);
-		SetColorVertex(2, r, g, b, a);
-		SetColorVertex(3, r, g, b, a);
-	}
-
-	virtual void QuadsSetSubset(float tl_u, float tl_v, float br_u, float br_v)
-	{
-		dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsSetSubset without begin");
-
-		m_aTexture[0].u = tl_u;	m_aTexture[1].u = br_u;
-		m_aTexture[0].v = tl_v;	m_aTexture[1].v = tl_v;
-
-		m_aTexture[3].u = tl_u;	m_aTexture[2].u = br_u;
-		m_aTexture[3].v = br_v;	m_aTexture[2].v = br_v;
-	}
-
-	virtual void QuadsSetSubsetFree(
-		float x0, float y0, float x1, float y1,
-		float x2, float y2, float x3, float y3)
-	{
-		m_aTexture[0].u = x0; m_aTexture[0].v = y0;
-		m_aTexture[1].u = x1; m_aTexture[1].v = y1;
-		m_aTexture[2].u = x2; m_aTexture[2].v = y2;
-		m_aTexture[3].u = x3; m_aTexture[3].v = y3;
-	}
-
-	virtual void QuadsDraw(float x, float y, float w, float h)
-	{
-		QuadsDrawTL(x-w/2, y-h/2,w,h);
-	}
-
-	virtual void QuadsDrawTL(float x, float y, float w, float h)
-	{
-		CPoint Center;
-
-		dbg_assert(m_Drawing == DRAWING_QUADS, "called quads_draw without begin");
-
-		Center.x = x + w/2;
-		Center.y = y + h/2;
-		Center.z = 0;
-		
-		m_aVertices[m_NumVertices].m_Pos.x = x;
-		m_aVertices[m_NumVertices].m_Pos.y = y;
-		m_aVertices[m_NumVertices].m_Tex = m_aTexture[0];
-		m_aVertices[m_NumVertices].m_Color = m_aColor[0];
-		Rotate(&Center, &m_aVertices[m_NumVertices].m_Pos);
-
-		m_aVertices[m_NumVertices + 1].m_Pos.x = x+w;
-		m_aVertices[m_NumVertices + 1].m_Pos.y = y;
-		m_aVertices[m_NumVertices + 1].m_Tex = m_aTexture[1];
-		m_aVertices[m_NumVertices + 1].m_Color = m_aColor[1];
-		Rotate(&Center, &m_aVertices[m_NumVertices + 1].m_Pos);
-
-		m_aVertices[m_NumVertices + 2].m_Pos.x = x + w;
-		m_aVertices[m_NumVertices + 2].m_Pos.y = y+h;
-		m_aVertices[m_NumVertices + 2].m_Tex = m_aTexture[2];
-		m_aVertices[m_NumVertices + 2].m_Color = m_aColor[2];
-		Rotate(&Center, &m_aVertices[m_NumVertices + 2].m_Pos);
-
-		m_aVertices[m_NumVertices + 3].m_Pos.x = x;
-		m_aVertices[m_NumVertices + 3].m_Pos.y = y+h;
-		m_aVertices[m_NumVertices + 3].m_Tex = m_aTexture[3];
-		m_aVertices[m_NumVertices + 3].m_Color = m_aColor[3];
-		Rotate(&Center, &m_aVertices[m_NumVertices + 3].m_Pos);
-		
-		AddVertices(4);
-	}
-
-	void QuadsDrawFreeform(
-		float x0, float y0, float x1, float y1,
-		float x2, float y2, float x3, float y3)
-	{
-		dbg_assert(m_Drawing == DRAWING_QUADS, "called quads_draw_freeform without begin");
-		
-		m_aVertices[m_NumVertices].m_Pos.x = x0;
-		m_aVertices[m_NumVertices].m_Pos.y = y0;
-		m_aVertices[m_NumVertices].m_Tex = m_aTexture[0];
-		m_aVertices[m_NumVertices].m_Color = m_aColor[0];
-
-		m_aVertices[m_NumVertices + 1].m_Pos.x = x1;
-		m_aVertices[m_NumVertices + 1].m_Pos.y = y1;
-		m_aVertices[m_NumVertices + 1].m_Tex = m_aTexture[1];
-		m_aVertices[m_NumVertices + 1].m_Color = m_aColor[1];
-
-		m_aVertices[m_NumVertices + 2].m_Pos.x = x3;
-		m_aVertices[m_NumVertices + 2].m_Pos.y = y3;
-		m_aVertices[m_NumVertices + 2].m_Tex = m_aTexture[3];
-		m_aVertices[m_NumVertices + 2].m_Color = m_aColor[3];
-
-		m_aVertices[m_NumVertices + 3].m_Pos.x = x2;
-		m_aVertices[m_NumVertices + 3].m_Pos.y = y2;
-		m_aVertices[m_NumVertices + 3].m_Tex = m_aTexture[2];
-		m_aVertices[m_NumVertices + 3].m_Color = m_aColor[2];
-		
-		AddVertices(4);
-	}
-
-	virtual void QuadsText(float x, float y, float Size, float r, float g, float b, float a, const char *pText)
-	{
-		float startx = x;
-
-		QuadsBegin();
-		SetColor(r,g,b,a);
-
-		while(*pText)
-		{
-			char c = *pText;
-			pText++;
-			
-			if(c == '\n')
-			{
-				x = startx;
-				y += Size;
-			}
-			else
-			{
-				QuadsSetSubset(
-					(c%16)/16.0f,
-					(c/16)/16.0f,
-					(c%16)/16.0f+1.0f/16.0f,
-					(c/16)/16.0f+1.0f/16.0f);
-				
-				QuadsDrawTL(x,y,Size,Size);
-				x += Size/2;
-			}
-		}
-		
-		QuadsEnd();
-	}
-	
-	virtual bool Init()
-	{
-		/* Set all z to -5.0f */
-		for(int i = 0; i < MAX_VERTICES; i++)
-			m_aVertices[i].m_Pos.z = -5.0f;
-
-		/* init textures */
-		m_FirstFreeTexture = 0;
-		for(int i = 0; i < MAX_TEXTURES; i++)
-			m_aTextures[i].next = i+1;
-		m_aTextures[MAX_TEXTURES-1].next = -1;
-
-		/* set some default settings */	
-		glEnable(GL_BLEND);
-		glDisable(GL_CULL_FACE);
-		glDisable(GL_DEPTH_TEST);
-		glMatrixMode(GL_MODELVIEW);
-		glLoadIdentity();
-		
-		glAlphaFunc(GL_GREATER, 0);
-		glEnable(GL_ALPHA_TEST);
-		glDepthMask(0);
-
-		/* create null texture, will get id=0 */
-		static const unsigned char aNullTextureData[] = {
-			0xff,0x00,0x00,0xff, 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0xff,0x00,0xff, 
-			0xff,0x00,0x00,0xff, 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0xff,0x00,0xff, 
-			0x00,0x00,0xff,0xff, 0x00,0x00,0xff,0xff, 0xff,0xff,0x00,0xff, 0xff,0xff,0x00,0xff, 
-			0x00,0x00,0xff,0xff, 0x00,0x00,0xff,0xff, 0xff,0xff,0x00,0xff, 0xff,0xff,0x00,0xff, 
-		};
-		
-		m_InvalidTexture = LoadTextureRaw(4,4,IMG_RGBA,aNullTextureData,IMG_RGBA,TEXLOAD_NORESAMPLE);
-		dbg_msg("", "invalid texture id: %d %d", m_InvalidTexture, m_aTextures[m_InvalidTexture].tex);
-		
-		return true;
-	}
-};
-
-class CGraphics_SDL : public CGraphics_OpenGL
-{
-	SDL_Surface *m_pScreenSurface;	
-	
-	int TryInit()
-	{
-		const SDL_VideoInfo *pInfo;
-		int Flags = SDL_OPENGL;
-		
-		m_ScreenWidth = config.gfx_screen_width;
-		m_ScreenHeight = config.gfx_screen_height;
-
-		pInfo = SDL_GetVideoInfo();
-
-		/* set flags */
-		Flags  = SDL_OPENGL;
-		Flags |= SDL_GL_DOUBLEBUFFER;
-		Flags |= SDL_HWPALETTE;
-		if(config.dbg_resizable)
-			Flags |= SDL_RESIZABLE;
-
-		if(pInfo->hw_available)
-			Flags |= SDL_HWSURFACE;
-		else
-			Flags |= SDL_SWSURFACE;
-
-		if(pInfo->blit_hw)
-			Flags |= SDL_HWACCEL;
-
-		if(config.gfx_fullscreen)
-			Flags |= SDL_FULLSCREEN;
-
-		/* set gl attributes */
-		if(config.gfx_fsaa_samples)
-		{
-			SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
-			SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, config.gfx_fsaa_samples);
-		}
-		else
-		{
-			SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
-			SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
-		}
-
-		SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
-		SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, config.gfx_vsync);
-
-		/* set caption */
-		SDL_WM_SetCaption("Teeworlds", "Teeworlds");
-		
-		/* create window */
-		m_pScreenSurface = SDL_SetVideoMode(m_ScreenWidth, m_ScreenHeight, 0, Flags);
-		if(m_pScreenSurface == NULL)
-		{
-			dbg_msg("gfx", "unable to set video mode: %s", SDL_GetError());
-			return -1;
-		}
-		
-		return 0;
-	}
-
-
-	int InitWindow()
-	{
-		if(TryInit() == 0)
-			return 0;
-		
-		/* try disabling fsaa */
-		while(config.gfx_fsaa_samples)
-		{
-			config.gfx_fsaa_samples--;
-			
-			if(config.gfx_fsaa_samples)
-				dbg_msg("gfx", "lowering FSAA to %d and trying again", config.gfx_fsaa_samples);
-			else
-				dbg_msg("gfx", "disabling FSAA and trying again");
-
-			if(TryInit() == 0)
-				return 0;
-		}
-
-		/* try lowering the resolution */
-		if(config.gfx_screen_width != 640 || config.gfx_screen_height != 480)
-		{
-			dbg_msg("gfx", "setting resolution to 640x480 and trying again");
-			config.gfx_screen_width = 640;
-			config.gfx_screen_height = 480;
-
-			if(TryInit() == 0)
-				return 0;
-		}
-
-		dbg_msg("gfx", "out of ideas. failed to init graphics");
-						
-		return -1;		
-	}
-
-	
-public:
-	CGraphics_SDL()
-	{
-		m_pScreenSurface = 0;
-	}
-
-	virtual bool Init()
-	{
-		{
-			int Systems = SDL_INIT_VIDEO;
-			
-			if(config.snd_enable)
-				Systems |= SDL_INIT_AUDIO;
-
-			if(config.cl_eventthread)
-				Systems |= SDL_INIT_EVENTTHREAD;
-			
-			if(SDL_Init(Systems) < 0)
-			{
-				dbg_msg("gfx", "unable to init SDL: %s", SDL_GetError());
-				return -1;
-			}
-		}
-		
-		atexit(SDL_Quit);
-
-		#ifdef CONF_FAMILY_WINDOWS
-			if(!getenv("SDL_VIDEO_WINDOW_POS") && !getenv("SDL_VIDEO_CENTERED"))
-				putenv("SDL_VIDEO_WINDOW_POS=8,27");
-		#endif
-		
-		if(InitWindow() != 0)
-			return -1;
-
-		SDL_ShowCursor(0);
-			
-		CGraphics_OpenGL::Init();
-		
-		MapScreen(0,0,config.gfx_screen_width, config.gfx_screen_height);
-
-		/* init input */
-		inp_init();
-
-		/* font init */
-		gfx_font_init();
-
-		return 0;
-	}
-	
-	virtual void Shutdown()
-	{
-		/* TODO: SDL, is this correct? */
-		SDL_Quit();
-	}
-
-	virtual void Minimize()
-	{
-		SDL_WM_IconifyWindow();
-	}
-
-	virtual void Maximize()
-	{
-		/* TODO: SDL */
-	}
-
-	virtual int WindowActive()
-	{
-		return SDL_GetAppState()&SDL_APPINPUTFOCUS;
-	}
-
-	virtual int WindowOpen()
-	{
-		return SDL_GetAppState()&SDL_APPACTIVE;
-
-	}
-	
-	virtual void TakeScreenshot()
-	{
-		m_DoScreenshot = true;
-	}
-	
-	virtual void Swap()
-	{
-		if(m_DoScreenshot)
-		{
-			/* find filename */
-			char filename[128];
-			static int index = 1;
-
-			for(; index < 1000; index++)
-			{
-				IOHANDLE io;
-				str_format(filename, sizeof(filename), "screenshots/screenshot%04d.png", index);
-				io = engine_openfile(filename, IOFLAG_READ);
-				if(io)
-					io_close(io);
-				else
-					break;
-			}
-
-			ScreenshotDirect(filename);
-			m_DoScreenshot = false;
-		}
-		
-		{
-			static PERFORMACE_INFO pscope = {"glfwSwapBuffers", 0};
-			perf_start(&pscope);
-			SDL_GL_SwapBuffers();
-			perf_end();
-		}
-		
-		if(config.gfx_finish)
-			glFinish();		
-	}
-};
-
-extern IEngineGraphics *CreateEngineGraphics() { return new CGraphics_SDL(); }
diff --git a/src/engine/client/ec_gfx_text.cpp b/src/engine/client/ec_gfx_text.cpp
deleted file mode 100644
index d17d1bed..00000000
--- a/src/engine/client/ec_gfx_text.cpp
+++ /dev/null
@@ -1,669 +0,0 @@
-#include <base/system.h>
-#include <string.h>
-#include <engine/e_client_interface.h>
-#include <engine/client/graphics.h>
-
-extern IEngineGraphics *Graphics();
-
-#ifdef CONF_PLATFORM_MACOSX
-	#include <OpenGL/gl.h>
-	#include <OpenGL/glu.h>
-#else
-	#include <GL/gl.h>
-	#include <GL/glu.h>
-#endif
-
-static int word_length(const char *text)
-{
-	int s = 1;
-	while(1)
-	{
-		if(*text == 0)
-			return s-1;
-		if(*text == '\n' || *text == '\t' || *text == ' ')
-			return s;
-		text++;
-		s++;
-	}
-}
-
-static float text_r=1;
-static float text_g=1;
-static float text_b=1;
-static float text_a=1;
-
-static struct FONT *default_font = 0;
-void gfx_text_set_default_font(struct FONT *font)
-{
-	default_font = font;
-}
-
-
-void gfx_text_set_cursor(TEXT_CURSOR *cursor, float x, float y, float font_size, int flags)
-{
-	mem_zero(cursor, sizeof(*cursor));
-	cursor->font_size = font_size;
-	cursor->start_x = x;
-	cursor->start_y = y;
-	cursor->x = x;
-	cursor->y = y;
-	cursor->line_count = 1;
-	cursor->line_width = -1;
-	cursor->flags = flags;
-	cursor->charcount = 0;
-}
-
-
-void gfx_text(void *font_set_v, float x, float y, float size, const char *text, int max_width)
-{
-	TEXT_CURSOR cursor;
-	gfx_text_set_cursor(&cursor, x, y, size, TEXTFLAG_RENDER);
-	cursor.line_width = max_width;
-	gfx_text_ex(&cursor, text, -1);
-}
-
-float gfx_text_width(void *font_set_v, float size, const char *text, int length)
-{
-	TEXT_CURSOR cursor;
-	gfx_text_set_cursor(&cursor, 0, 0, size, 0);
-	gfx_text_ex(&cursor, text, length);
-	return cursor.x;
-}
-
-void gfx_text_color(float r, float g, float b, float a)
-{
-	text_r = r;
-	text_g = g;
-	text_b = b;
-	text_a = a;
-}
-
-/* ft2 texture */
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-static FT_Library ft_library;
-
-#define MAX_CHARACTERS 64
-
-
-/* GL_LUMINANCE can be good for debugging*/
-static int font_texture_format = GL_ALPHA;
-
-
-static int font_sizes[] = {8,9,10,11,12,13,14,15,16,17,18,19,20,36};
-#define NUM_FONT_SIZES (sizeof(font_sizes)/sizeof(int))
-
-
-typedef struct FONTCHAR
-{
-	int id;
-	
-	/* these values are scaled to the font size */
-	/* width * font_size == real_size */
-	float width;
-	float height;
-	float offset_x;
-	float offset_y;
-	float advance_x;
-	
-	float uvs[4];
-	int64 touch_time;
-} FONTCHAR;
-
-typedef struct FONTSIZEDATA
-{
-	int font_size;
-	FT_Face *face;
-
-	unsigned textures[2];
-	int texture_width;
-	int texture_height;
-	
-	int num_x_chars;
-	int num_y_chars;
-	
-	int char_max_width;
-	int char_max_height;
-	
-	FONTCHAR characters[MAX_CHARACTERS*MAX_CHARACTERS];
-	
-	int current_character;	
-} FONTSIZEDATA;
-
-typedef struct FONT
-{
-	char filename[128];
-	FT_Face ft_face;
-	FONTSIZEDATA sizes[NUM_FONT_SIZES];
-} FONT;
-
-static int font_get_index(int pixelsize)
-{
-	for(unsigned i = 0; i < NUM_FONT_SIZES; i++)
-	{
-		if(font_sizes[i] >= pixelsize)
-			return i;
-	}
-	
-	return NUM_FONT_SIZES-1;
-}
-
-FONT *gfx_font_load(const char *filename)
-{
-	FONT *font = (FONT *)mem_alloc(sizeof(FONT), 1);
-	
-	mem_zero(font, sizeof(*font));
-	str_copy(font->filename, filename, sizeof(font->filename));
-	
-	if(FT_New_Face(ft_library, font->filename, 0, &font->ft_face))
-	{
-		mem_free(font);
-		return NULL;
-	}
-
-	for(unsigned i = 0; i < NUM_FONT_SIZES; i++)
-		font->sizes[i].font_size = -1;
-		
-	return font;
-};
-
-void gfx_font_destroy(FONT *font)
-{
-	mem_free(font);
-}
-
-void gfx_font_init()
-{
-	FT_Init_FreeType(&ft_library);
-}
-
-static void grow(unsigned char *in, unsigned char *out, int w, int h)
-{
-	int y, x;
-	for(y = 0; y < h; y++) 
-		for(x = 0; x < w; x++) 
-		{ 
-			int c = in[y*w+x]; 
-			int s_y, s_x;
-
-			for(s_y = -1; s_y <= 1; s_y++)
-				for(s_x = -1; s_x <= 1; s_x++)
-				{
-					int get_x = x+s_x;
-					int get_y = y+s_y;
-					if (get_x >= 0 && get_y >= 0 && get_x < w && get_y < h)
-					{
-						int index = get_y*w+get_x;
-						if(in[index] > c)
-							c = in[index]; 
-					}
-				}
-
-			out[y*w+x] = c;
-		}
-}
-
-static void font_init_texture(FONTSIZEDATA *sizedata, int charwidth, int charheight, int xchars, int ychars)
-{
-	static int font_memory_usage = 0;
-	int i;
-	int width = charwidth*xchars;
-	int height = charheight*ychars;
-	void *mem = mem_alloc(width*height, 1);
-	mem_zero(mem, width*height);
-	
-	if(sizedata->textures[0] == 0)
-		glGenTextures(2, sizedata->textures);
-	else
-		font_memory_usage -= sizedata->texture_width*sizedata->texture_height*2;
-	
-	sizedata->num_x_chars = xchars;
-	sizedata->num_y_chars = ychars;
-	sizedata->texture_width = width;
-	sizedata->texture_height = height;
-	sizedata->current_character = 0;
-	
-	for(i = 0; i < 2; i++)
-	{
-		glBindTexture(GL_TEXTURE_2D, sizedata->textures[i]);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-		glTexImage2D(GL_TEXTURE_2D, 0, font_texture_format, width, height, 0, font_texture_format, GL_UNSIGNED_BYTE, mem);
-		font_memory_usage += width*height;
-	}
-	
-	dbg_msg("", "font memory usage: %d", font_memory_usage);
-	
-	mem_free(mem);
-}
-
-static void font_increase_texture_size(FONTSIZEDATA *sizedata)
-{
-	if(sizedata->texture_width < sizedata->texture_height)
-		sizedata->num_x_chars <<= 1;
-	else
-		sizedata->num_y_chars <<= 1;
-	font_init_texture(sizedata, sizedata->char_max_width, sizedata->char_max_height, sizedata->num_x_chars, sizedata->num_y_chars);		
-}
-
-static void font_init_index(FONT *font, int index)
-{
-	int outline_thickness = 1;
-	FONTSIZEDATA *sizedata = &font->sizes[index];
-	
-	sizedata->font_size = font_sizes[index];
-	FT_Set_Pixel_Sizes(font->ft_face, 0, sizedata->font_size);
-	
-	if(sizedata->font_size >= 18)
-		outline_thickness = 2;
-		
-	{
-		unsigned glyph_index;
-		int charcode;
-		int max_h = 0;
-		int max_w = 0;
-		
-		charcode = FT_Get_First_Char(font->ft_face, &glyph_index);
-		while(glyph_index != 0)
-		{   
-			/* do stuff */
-			FT_Load_Glyph(font->ft_face, glyph_index, FT_LOAD_DEFAULT);
-			
-			if(font->ft_face->glyph->metrics.width > max_w) max_w = font->ft_face->glyph->metrics.width;
-			if(font->ft_face->glyph->metrics.height > max_h) max_h = font->ft_face->glyph->metrics.height;
-			charcode = FT_Get_Next_Char(font->ft_face, charcode, &glyph_index);
-		}
-		
-		max_w = (max_w>>6)+2+outline_thickness*2;
-		max_h = (max_h>>6)+2+outline_thickness*2;
-		
-		for(sizedata->char_max_width = 1; sizedata->char_max_width < max_w; sizedata->char_max_width <<= 1);
-		for(sizedata->char_max_height = 1; sizedata->char_max_height < max_h; sizedata->char_max_height <<= 1);
-	}
-	
-	//dbg_msg("font", "init size %d, texture size %d %d", font->sizes[index].font_size, w, h);
-	//FT_New_Face(ft_library, "data/fonts/vera.ttf", 0, &font->ft_face);
-	font_init_texture(sizedata, sizedata->char_max_width, sizedata->char_max_height, 8, 8);
-}
-
-static FONTSIZEDATA *font_get_size(FONT *font, int pixelsize)
-{
-	int index = font_get_index(pixelsize);
-	if(font->sizes[index].font_size != font_sizes[index])
-		font_init_index(font, index);
-	return &font->sizes[index];
-}
-
-
-static void font_upload_glyph(FONTSIZEDATA *sizedata, int texnum, int slot_id, int chr, const void *data)
-{
-	int x = (slot_id%sizedata->num_x_chars) * (sizedata->texture_width/sizedata->num_x_chars);
-	int y = (slot_id/sizedata->num_x_chars) * (sizedata->texture_height/sizedata->num_y_chars);
-	
-	glBindTexture(GL_TEXTURE_2D, sizedata->textures[texnum]);
-	glTexSubImage2D(GL_TEXTURE_2D, 0, x, y,
-		sizedata->texture_width/sizedata->num_x_chars,
-		sizedata->texture_height/sizedata->num_y_chars,
-		font_texture_format, GL_UNSIGNED_BYTE, data);
-}
-
-/* 8k of data used for rendering glyphs */
-static unsigned char glyphdata[(4096/64) * (4096/64)];
-static unsigned char glyphdata_outlined[(4096/64) * (4096/64)];
-
-static int font_get_slot(FONTSIZEDATA *sizedata)
-{
-	int char_count = sizedata->num_x_chars*sizedata->num_y_chars;
-	if(sizedata->current_character < char_count)
-	{
-		int i = sizedata->current_character;
-		sizedata->current_character++;
-		return i;
-	}
-
-	/* kick out the oldest */
-	/* TODO: remove this linear search */
-	{
-		int oldest = 0;
-		int i;
-		for(i = 1; i < char_count; i++)
-		{
-			if(sizedata->characters[i].touch_time < sizedata->characters[oldest].touch_time)
-				oldest = i;
-		}
-		
-		if(time_get()-sizedata->characters[oldest].touch_time < time_freq())
-		{
-			font_increase_texture_size(sizedata);
-			return font_get_slot(sizedata);
-		}
-		
-		return oldest;
-	}
-}
-
-static int font_render_glyph(FONT *font, FONTSIZEDATA *sizedata, int chr)
-{
-	FT_Bitmap *bitmap;
-	int slot_id = 0;
-	int slot_w = sizedata->texture_width / sizedata->num_x_chars;
-	int slot_h = sizedata->texture_height / sizedata->num_y_chars;
-	int slot_size = slot_w*slot_h;
-	int outline_thickness = 1;
-	int x = 1;
-	int y = 1;
-	int px, py;
-
-	FT_Set_Pixel_Sizes(font->ft_face, 0, sizedata->font_size);
-
-	if(FT_Load_Char(font->ft_face, chr, FT_LOAD_RENDER|FT_LOAD_NO_BITMAP))
-	{
-		dbg_msg("font", "error loading glyph %d", chr);
-		return -1;
-	}
-
-	bitmap = &font->ft_face->glyph->bitmap; 
-	
-	/* fetch slot */
-	slot_id = font_get_slot(sizedata);
-	if(slot_id < 0)
-		return -1;
-	
-	/* adjust spacing */
-	if(sizedata->font_size >= 18)
-		outline_thickness = 2;
-	x += outline_thickness;
-	y += outline_thickness;
-
-	/* prepare glyph data */
-	mem_zero(glyphdata, slot_size);
-
-	if(bitmap->pixel_mode == FT_PIXEL_MODE_GRAY)
-	{
-		for(py = 0; py < bitmap->rows; py++) 
-			for(px = 0; px < bitmap->width; px++) 
-				glyphdata[(py+y)*slot_w+px+x] = bitmap->buffer[py*bitmap->pitch+px];
-	}
-	else if(bitmap->pixel_mode == FT_PIXEL_MODE_MONO)
-	{
-		for(py = 0; py < bitmap->rows; py++) 
-			for(px = 0; px < bitmap->width; px++)
-			{
-				if(bitmap->buffer[py*bitmap->pitch+px/8]&(1<<(7-(px%8))))
-					glyphdata[(py+y)*slot_w+px+x] = 255;
-			}
-	}
-
-	if(0) for(py = 0; py < slot_w; py++) 
-		for(px = 0; px < slot_h; px++) 
-			glyphdata[py*slot_w+px] = 255;
-	
-	/* upload the glyph */
-	font_upload_glyph(sizedata, 0, slot_id, chr, glyphdata);
-	
-	if(outline_thickness == 1)
-	{
-		grow(glyphdata, glyphdata_outlined, slot_w, slot_h);
-		font_upload_glyph(sizedata, 1, slot_id, chr, glyphdata_outlined);
-	}
-	else
-	{
-		grow(glyphdata, glyphdata_outlined, slot_w, slot_h);
-		grow(glyphdata_outlined, glyphdata, slot_w, slot_h);
-		font_upload_glyph(sizedata, 1, slot_id, chr, glyphdata);
-	}
-	
-	/* set char info */
-	{
-		FONTCHAR *fontchr = &sizedata->characters[slot_id];
-		float scale = 1.0f/sizedata->font_size;
-		float uscale = 1.0f/sizedata->texture_width;
-		float vscale = 1.0f/sizedata->texture_height;
-		int height = bitmap->rows + outline_thickness*2 + 2;
-		int width = bitmap->width + outline_thickness*2 + 2;
-		
-		fontchr->id = chr;
-		fontchr->height = height * scale;
-		fontchr->width = width * scale;
-		fontchr->offset_x = (font->ft_face->glyph->bitmap_left-1) * scale;
-		fontchr->offset_y = (sizedata->font_size - font->ft_face->glyph->bitmap_top) * scale;
-		fontchr->advance_x = (font->ft_face->glyph->advance.x>>6) * scale;
-		
-		fontchr->uvs[0] = (slot_id%sizedata->num_x_chars) / (float)(sizedata->num_x_chars);
-		fontchr->uvs[1] = (slot_id/sizedata->num_x_chars) / (float)(sizedata->num_y_chars);
-		fontchr->uvs[2] = fontchr->uvs[0] + width*uscale;
-		fontchr->uvs[3] = fontchr->uvs[1] + height*vscale;
-	}
-	
-	return slot_id;
-}
-
-static FONTCHAR *font_get_char(FONT *font, FONTSIZEDATA *sizedata, int chr)
-{
-	FONTCHAR *fontchr = NULL;
-	
-	/* search for the character */
-	/* TODO: remove this linear search */
-	int i;
-	for(i = 0; i < sizedata->current_character; i++)
-	{
-		if(sizedata->characters[i].id == chr)
-		{
-			fontchr = &sizedata->characters[i];
-			break;
-		}
-	}
-	
-	/* check if we need to render the character */
-	if(!fontchr)
-	{
-		int index = font_render_glyph(font, sizedata, chr);
-		if(index >= 0)
-			fontchr = &sizedata->characters[index];
-	}
-	
-	/* touch the character */
-	/* TODO: don't call time_get here */
-	if(fontchr)
-		fontchr->touch_time = time_get();
-		
-	return fontchr;
-}
-
-/* must only be called from the rendering function as the font must be set to the correct size */
-static void font_render_setup(FONT *font, int size)
-{
-	FT_Set_Pixel_Sizes(font->ft_face, 0, size);
-}
-
-static float font_kerning(FONT *font, int left, int right)
-{
-	FT_Vector kerning = {0,0};
-	FT_Get_Kerning(font->ft_face, left, right, FT_KERNING_DEFAULT, &kerning);
-	return (kerning.x>>6);
-}
-
-
-void gfx_text_ex(TEXT_CURSOR *cursor, const char *text, int length)
-{
-	FONT *font = cursor->font;
-	FONTSIZEDATA *sizedata = NULL;
-
-	float screen_x0, screen_y0, screen_x1, screen_y1;
-	float fake_to_screen_x, fake_to_screen_y;
-	int actual_x, actual_y;
-
-	int actual_size;
-	int i;
-	int got_new_line = 0;
-	float draw_x, draw_y;
-	float cursor_x, cursor_y;
-	const char *end;
-
-	float size = cursor->font_size;
-
-	/* to correct coords, convert to screen coords, round, and convert back */
-	Graphics()->GetScreen(&screen_x0, &screen_y0, &screen_x1, &screen_y1);
-	
-	fake_to_screen_x = (Graphics()->ScreenWidth()/(screen_x1-screen_x0));
-	fake_to_screen_y = (Graphics()->ScreenHeight()/(screen_y1-screen_y0));
-	actual_x = cursor->x * fake_to_screen_x;
-	actual_y = cursor->y * fake_to_screen_y;
-
-	cursor_x = actual_x / fake_to_screen_x;
-	cursor_y = actual_y / fake_to_screen_y;
-
-	/* same with size */
-	actual_size = size * fake_to_screen_y;
-	size = actual_size / fake_to_screen_y;
-
-	/* fetch font data */
-	if(!font)
-		font = default_font;
-	
-	if(!font)
-		return;
-
-	sizedata = font_get_size(font, actual_size);
-	font_render_setup(font, actual_size);
-	
-	/* set length */
-	if(length < 0)
-		length = strlen(text);
-		
-	end = text + length;
-
-	/* if we don't want to render, we can just skip the first outline pass */
-	i = 1;
-	if(cursor->flags&TEXTFLAG_RENDER)
-		i = 0;
-
-	for(;i < 2; i++)
-	{
-		const char *current = (char *)text;
-		const char *end = current+length;
-		draw_x = cursor_x;
-		draw_y = cursor_y;
-
-		if(cursor->flags&TEXTFLAG_RENDER)
-		{
-			// TODO: Make this better
-			glEnable(GL_TEXTURE_2D);
-			if (i == 0)
-				glBindTexture(GL_TEXTURE_2D, sizedata->textures[1]);
-			else
-				glBindTexture(GL_TEXTURE_2D, sizedata->textures[0]);
-
-			Graphics()->QuadsBegin();
-			if (i == 0)
-				Graphics()->SetColor(0.0f, 0.0f, 0.0f, 0.3f*text_a);
-			else
-				Graphics()->SetColor(text_r, text_g, text_b, text_a);
-		}
-
-		while(current < end)
-		{
-			int new_line = 0;
-			const char *batch_end = end;
-			if(cursor->line_width > 0 && !(cursor->flags&TEXTFLAG_STOP_AT_END))
-			{
-				int wlen = word_length((char *)current);
-				TEXT_CURSOR compare = *cursor;
-				compare.x = draw_x;
-				compare.y = draw_y;
-				compare.flags &= ~TEXTFLAG_RENDER;
-				compare.line_width = -1;
-				gfx_text_ex(&compare, text, wlen);
-				
-				if(compare.x-draw_x > cursor->line_width)
-				{
-					/* word can't be fitted in one line, cut it */
-					TEXT_CURSOR cutter = *cursor;
-					cutter.charcount = 0;
-					cutter.x = draw_x;
-					cutter.y = draw_y;
-					cutter.flags &= ~TEXTFLAG_RENDER;
-					cutter.flags |= TEXTFLAG_STOP_AT_END;
-					
-					gfx_text_ex(&cutter, (const char *)current, wlen);
-					wlen = cutter.charcount;
-					new_line = 1;
-					
-					if(wlen <= 3) /* if we can't place 3 chars of the word on this line, take the next */
-						wlen = 0;
-				}
-				else if(compare.x-cursor->start_x > cursor->line_width)
-				{
-					new_line = 1;
-					wlen = 0;
-				}
-				
-				batch_end = current + wlen;
-			}
-			
-			while(current < batch_end)
-			{
-				const char *tmp;
-				float advance = 0;
-				int character = 0;
-				int nextcharacter = 0;
-				FONTCHAR *chr;
-
-				// TODO: UTF-8 decode
-				character = str_utf8_decode(&current);
-				tmp = current;
-				nextcharacter = str_utf8_decode(&tmp);
-				
-				if(character == '\n')
-				{
-					draw_x = cursor->start_x;
-					draw_y += size;
-					draw_x = (int)(draw_x * fake_to_screen_x) / fake_to_screen_x; /* realign */
-					draw_y = (int)(draw_y * fake_to_screen_y) / fake_to_screen_y;
-					continue;
-				}
-
-				chr = font_get_char(font, sizedata, character);
-
-				if(chr)
-				{
-					if(cursor->flags&TEXTFLAG_RENDER)
-					{
-						Graphics()->QuadsSetSubset(chr->uvs[0], chr->uvs[1], chr->uvs[2], chr->uvs[3]);
-						Graphics()->QuadsDrawTL(draw_x+chr->offset_x*size, draw_y+chr->offset_y*size, chr->width*size, chr->height*size);
-					}
-
-					advance = chr->advance_x + font_kerning(font, character, nextcharacter)/size;
-				}
-								
-				if(cursor->flags&TEXTFLAG_STOP_AT_END && draw_x+advance*size-cursor->start_x > cursor->line_width)
-				{
-					/* we hit the end of the line, no more to render or count */
-					current = end;
-					break;
-				}
-
-				draw_x += advance*size;
-				cursor->charcount++;
-			}
-			
-			if(new_line)
-			{
-				draw_x = cursor->start_x;
-				draw_y += size;
-				got_new_line = 1;
-				draw_x = (int)(draw_x * fake_to_screen_x) / fake_to_screen_x; /* realign */
-				draw_y = (int)(draw_y * fake_to_screen_y) / fake_to_screen_y;				
-			}
-		}
-
-		if(cursor->flags&TEXTFLAG_RENDER)
-			Graphics()->QuadsEnd();
-	}
-
-	cursor->x = draw_x;
-	
-	if(got_new_line)
-		cursor->y = draw_y;
-}
diff --git a/src/engine/client/ec_inp.cpp b/src/engine/client/ec_inp.cpp
deleted file mode 100644
index cf956471..00000000
--- a/src/engine/client/ec_inp.cpp
+++ /dev/null
@@ -1,234 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <string.h>
-#include "SDL.h"
-
-#include <base/system.h>
-#include <engine/e_client_interface.h>
-#include <engine/e_config.h>
-#include <engine/client/graphics.h>
-
-static struct
-{
-	unsigned char presses;
-	unsigned char releases;
-} input_count[2][1024] = {{{0}}, {{0}}};
-
-static unsigned char input_state[2][1024] = {{0}, {0}};
-
-static int input_current = 0;
-static int input_grabbed = 0;
-
-static unsigned int last_release = 0;
-static unsigned int release_delta = -1;
-
-// TODO: Refactor: Remove this
-extern IEngineGraphics *Graphics();
-
-void inp_mouse_relative(int *x, int *y)
-{
-	int nx = 0, ny = 0;
-	float sens = config.inp_mousesens/100.0f;
-	
-	if(config.inp_grab)
-		SDL_GetRelativeMouseState(&nx, &ny);
-	else
-	{
-		if(input_grabbed)
-		{
-			SDL_GetMouseState(&nx,&ny);
-			SDL_WarpMouse(Graphics()->ScreenWidth()/2,Graphics()->ScreenHeight()/2);
-			nx -= Graphics()->ScreenWidth()/2; ny -= Graphics()->ScreenHeight()/2;
-		}
-	}
-
-	*x = nx*sens;
-	*y = ny*sens;
-}
-
-enum
-{
-	INPUT_BUFFER_SIZE=32
-};
-
-static INPUT_EVENT input_events[INPUT_BUFFER_SIZE];
-static int num_events = 0;
-
-static void add_event(int unicode, int key, int flags)
-{
-	if(num_events != INPUT_BUFFER_SIZE)
-	{
-		input_events[num_events].unicode = unicode;
-		input_events[num_events].key = key;
-		input_events[num_events].flags = flags;
-		num_events++;
-	}
-}
-
-int inp_num_events()
-{
-	return num_events;
-}
-
-void inp_clear_events()
-{
-	num_events = 0;
-}
-
-INPUT_EVENT inp_get_event(int index)
-{
-	if(index < 0 || index >= num_events)
-	{
-		INPUT_EVENT e = {0,0};
-		return e;
-	}
-	
-	return input_events[index];
-}
-
-void inp_init()
-{
-	SDL_EnableUNICODE(1);
-	SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); 
-}
-
-void inp_mouse_mode_absolute()
-{
-	SDL_ShowCursor(1);
-	input_grabbed = 0;
-	if(config.inp_grab)
-		SDL_WM_GrabInput(SDL_GRAB_OFF);
-}
-
-void inp_mouse_mode_relative()
-{
-	SDL_ShowCursor(0);
-	input_grabbed = 1;
-	if(config.inp_grab)
-		SDL_WM_GrabInput(SDL_GRAB_ON);
-}
-
-int inp_mouse_doubleclick()
-{
-	return release_delta < (time_freq() >> 2);
-}
-
-void inp_clear_key_states()
-{
-	mem_zero(input_state, sizeof(input_state));
-	mem_zero(input_count, sizeof(input_count));
-}
-
-int inp_key_presses(int key)
-{
-	return input_count[input_current][key].presses;
-}
-
-int inp_key_releases(int key)
-{
-	return input_count[input_current][key].releases;
-}
-
-int inp_key_state(int key)
-{
-	return input_state[input_current][key];
-}
-
-int inp_key_pressed(int key) { return input_state[input_current][key]; }
-int inp_key_was_pressed(int key) { return input_state[input_current^1][key]; }
-int inp_key_down(int key) { return inp_key_pressed(key)&&!inp_key_was_pressed(key); }
-int inp_button_pressed(int button) { return input_state[input_current][button]; }
-
-void inp_update()
-{
-	int i;
-	
-	if(input_grabbed && !Graphics()->WindowActive())
-		inp_mouse_mode_absolute();
-
-	/*if(!input_grabbed && Graphics()->WindowActive())
-		inp_mouse_mode_relative();*/
-	
-	/* clear and begin count on the other one */
-	input_current^=1;
-	mem_zero(&input_count[input_current], sizeof(input_count[input_current]));
-	mem_zero(&input_state[input_current], sizeof(input_state[input_current]));
-	
-	{
-		Uint8 *state = SDL_GetKeyState(&i);
-		if(i >= KEY_LAST)
-			i = KEY_LAST-1;
-		mem_copy(input_state[input_current], state, i);
-	}
-	
-	/* these states must always be updated manually because they are not in the GetKeyState from SDL */
-	i = SDL_GetMouseState(NULL, NULL);
-	if(i&SDL_BUTTON(1)) input_state[input_current][KEY_MOUSE_1] = 1; /* 1 is left */ 
-	if(i&SDL_BUTTON(3)) input_state[input_current][KEY_MOUSE_2] = 1; /* 3 is right */ 
-	if(i&SDL_BUTTON(2)) input_state[input_current][KEY_MOUSE_3] = 1; /* 2 is middle */ 
-	if(i&SDL_BUTTON(4)) input_state[input_current][KEY_MOUSE_4] = 1; 
-	if(i&SDL_BUTTON(5)) input_state[input_current][KEY_MOUSE_5] = 1; 
-	if(i&SDL_BUTTON(6)) input_state[input_current][KEY_MOUSE_6] = 1; 
-	if(i&SDL_BUTTON(7)) input_state[input_current][KEY_MOUSE_7] = 1; 
-	if(i&SDL_BUTTON(8)) input_state[input_current][KEY_MOUSE_8] = 1; 	
-	
-	{
-		SDL_Event event;
-	
-		while(SDL_PollEvent(&event))
-		{
-			int key = -1;
-			int action = INPFLAG_PRESS;
-			switch (event.type)
-			{
-				/* handle keys */
-				case SDL_KEYDOWN:
-					/*if(event.key.keysym.unicode < 255) */
-					add_event(event.key.keysym.unicode, 0, 0);
-					key = event.key.keysym.sym;
-					break;
-				case SDL_KEYUP:
-					action = INPFLAG_RELEASE;
-					key = event.key.keysym.sym;
-					break;
-				
-				/* handle mouse buttons */
-				case SDL_MOUSEBUTTONUP:
-					action = INPFLAG_RELEASE;
-					
-					if(event.button.button == 1)
-					{
-						release_delta = time_get() - last_release;
-						last_release = time_get();
-					}
-					
-					/* fall through */
-				case SDL_MOUSEBUTTONDOWN:
-					if(event.button.button == SDL_BUTTON_LEFT) key = KEY_MOUSE_1;
-					if(event.button.button == SDL_BUTTON_RIGHT) key = KEY_MOUSE_2;
-					if(event.button.button == SDL_BUTTON_MIDDLE) key = KEY_MOUSE_3;
-					if(event.button.button == SDL_BUTTON_WHEELUP) key = KEY_MOUSE_WHEEL_UP;
-					if(event.button.button == SDL_BUTTON_WHEELDOWN) key = KEY_MOUSE_WHEEL_DOWN;
-					if(event.button.button == 6) key = KEY_MOUSE_6;
-					if(event.button.button == 7) key = KEY_MOUSE_7;
-					if(event.button.button == 8) key = KEY_MOUSE_8;
-					break;
-					
-				/* other messages */
-				case SDL_QUIT:
-					/* TODO: cleaner exit */
-					exit(0);
-					break;
-			}
-			
-			/* */
-			if(key != -1)
-			{
-				input_count[input_current][key].presses++;
-				if(action == INPFLAG_PRESS)
-					input_state[input_current][key] = 1;
-				add_event(0, key, action);
-			}
-
-		}
-	}
-}
diff --git a/src/engine/client/ec_snd.cpp b/src/engine/client/ec_snd.cpp
deleted file mode 100644
index 3baea982..00000000
--- a/src/engine/client/ec_snd.cpp
+++ /dev/null
@@ -1,471 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <base/system.h>
-#include <engine/e_client_interface.h>
-#include <engine/client/graphics.h>
-#include <engine/e_config.h>
-#include <engine/e_engine.h>
-
-#include "SDL.h"
-
-extern "C" { // wavpack
-	#include <engine/external/wavpack/wavpack.h>
-}
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-enum
-{
-	NUM_SAMPLES = 512,
-	NUM_VOICES = 64,
-	NUM_CHANNELS = 16,
-	
-	MAX_FRAMES = 1024
-};
-
-typedef struct
-{
-	short *data;
-	int num_frames;
-	int rate;
-	int channels;
-	int loop_start;
-	int loop_end;
-} SAMPLE;
-
-typedef struct
-{
-	int vol;
-	int pan;
-} CHANNEL;
-
-typedef struct
-{
-	SAMPLE *snd;
-	CHANNEL *channel;
-	int tick;
-	int vol; /* 0 - 255 */
-	int flags;
-	int x, y;
-} VOICE;
-
-static SAMPLE samples[NUM_SAMPLES] = { {0} };
-static VOICE voices[NUM_VOICES] = { {0} };
-static CHANNEL channels[NUM_CHANNELS] = { {255, 0} };
-
-static LOCK sound_lock = 0;
-static int sound_enabled = 0;
-
-static int center_x = 0;
-static int center_y = 0;
-
-static int mixing_rate = 48000;
-static volatile int sound_volume = 100;
-
-static int next_voice = 0;
-
-void snd_set_channel(int cid, float vol, float pan)
-{
-	channels[cid].vol = (int)(vol*255.0f);
-	channels[cid].pan = (int)(pan*255.0f); /* TODO: this is only on and off right now */
-}
-
-static int play(int cid, int sid, int flags, float x, float y)
-{
-	int vid = -1;
-	int i;
-	
-	lock_wait(sound_lock);
-	
-	/* search for voice */
-	for(i = 0; i < NUM_VOICES; i++)
-	{
-		int id = (next_voice + i) % NUM_VOICES;
-		if(!voices[id].snd)
-		{
-			vid = id;
-			next_voice = id+1;
-			break;
-		}
-	}
-	
-	/* voice found, use it */
-	if(vid != -1)
-	{
-		voices[vid].snd = &samples[sid];
-		voices[vid].channel = &channels[cid];
-		voices[vid].tick = 0;
-		voices[vid].vol = 255;
-		voices[vid].flags = flags;
-		voices[vid].x = (int)x;
-		voices[vid].y = (int)y;
-	}
-	
-	lock_release(sound_lock);
-	return vid;
-}
-
-int snd_play_at(int cid, int sid, int flags, float x, float y)
-{
-	return play(cid, sid, flags|SNDFLAG_POS, x, y);
-}
-
-int snd_play(int cid, int sid, int flags)
-{
-	return play(cid, sid, flags, 0, 0);
-}
-
-void snd_stop(int vid)
-{
-	/* TODO: a nice fade out */
-	lock_wait(sound_lock);
-	voices[vid].snd = 0;
-	lock_release(sound_lock);
-}
-
-/* TODO: there should be a faster way todo this */
-static short int2short(int i)
-{
-	if(i > 0x7fff)
-		return 0x7fff;
-	else if(i < -0x7fff)
-		return -0x7fff;
-	return i;
-}
-
-static int iabs(int i)
-{
-	if(i<0)
-		return -i;
-	return i;
-}
-
-static void mix(short *final_out, unsigned frames)
-{
-	int mix_buffer[MAX_FRAMES*2] = {0};
-	int master_vol;
-
-	/* aquire lock while we are mixing */
-	lock_wait(sound_lock);
-	
-	master_vol = sound_volume;
-	
-	for(unsigned i = 0; i < NUM_VOICES; i++)
-	{
-		if(voices[i].snd)
-		{
-			/* mix voice */
-			VOICE *v = &voices[i];
-			int *out = mix_buffer;
-
-			int step = v->snd->channels; /* setup input sources */
-			short *in_l = &v->snd->data[v->tick*step];
-			short *in_r = &v->snd->data[v->tick*step+1];
-			
-			unsigned end = v->snd->num_frames-v->tick;
-
-			int rvol = v->channel->vol;
-			int lvol = v->channel->vol;
-
-			/* make sure that we don't go outside the sound data */
-			if(frames < end)
-				end = frames;
-			
-			/* check if we have a mono sound */
-			if(v->snd->channels == 1)
-				in_r = in_l;
-
-			/* volume calculation */
-			if(v->flags&SNDFLAG_POS && v->channel->pan)
-			{
-				/* TODO: we should respect the channel panning value */
-				const int range = 1500; /* magic value, remove */
-				int dx = v->x - center_x;
-				int dy = v->y - center_y;
-				int dist = sqrt(dx*dx+dy*dy); /* double here. nasty */
-				int p = iabs(dx);
-				if(dist < range)
-				{
-					/* panning */
-					if(dx > 0)
-						lvol = ((range-p)*lvol)/range;
-					else
-						rvol = ((range-p)*rvol)/range;
-					
-					/* falloff */
-					lvol = (lvol*(range-dist))/range;
-					rvol = (rvol*(range-dist))/range;
-				}
-				else
-				{
-					lvol = 0;
-					rvol = 0;
-				}
-			}
-
-			/* process all frames */
-			for(unsigned s = 0; s < end; s++)
-			{
-				*out++ += (*in_l)*lvol;
-				*out++ += (*in_r)*rvol;
-				in_l += step;
-				in_r += step;
-				v->tick++;
-			}
-			
-			/* free voice if not used any more */
-			if(v->tick == v->snd->num_frames)
-				v->snd = 0;
-			
-		}
-	}
-	
-	
-	/* release the lock */
-	lock_release(sound_lock);
-
-	{
-		/* clamp accumulated values */
-		/* TODO: this seams slow */
-		for(unsigned i = 0; i < frames; i++)
-		{
-			int j = i<<1;
-			int vl = ((mix_buffer[j]*master_vol)/101)>>8;
-			int vr = ((mix_buffer[j+1]*master_vol)/101)>>8;
-
-			final_out[j] = int2short(vl);
-			final_out[j+1] = int2short(vr);
-		}
-	}
-
-#if defined(CONF_ARCH_ENDIAN_BIG)
-	swap_endian(final_out, sizeof(short), frames * 2);
-#endif
-}
-
-static void sdlcallback(void *unused, Uint8 *stream, int len)
-{
-	mix((short *)stream, len/2/2);
-}
-
-int snd_init()
-{
-    SDL_AudioSpec format;
-	
-	sound_lock = lock_create();
-	
-	if(!config.snd_enable)
-		return 0;
-	
-	mixing_rate = config.snd_rate;
-
-    /* Set 16-bit stereo audio at 22Khz */
-    format.freq = config.snd_rate;
-    format.format = AUDIO_S16;
-    format.channels = 2;
-    format.samples = config.snd_buffer_size;
-    format.callback = sdlcallback;
-    format.userdata = NULL;
-
-    /* Open the audio device and start playing sound! */
-    if(SDL_OpenAudio(&format, NULL) < 0)
-	{
-        dbg_msg("client/sound", "unable to open audio: %s", SDL_GetError());
-		return -1;
-    }
-	else
-        dbg_msg("client/sound", "sound init successful");
-
-	SDL_PauseAudio(0);
-	
-	sound_enabled = 1;
-	snd_update(); /* update the volume */
-	return 0;
-}
-
-// TODO: Refactor: Remove this
-extern IEngineGraphics *Graphics();
-
-
-int snd_update()
-{
-	/* update volume */
-	int wanted_volume = config.snd_volume;
-	
-	if(!Graphics()->WindowActive() && config.snd_nonactive_mute)
-		wanted_volume = 0;
-	
-	if(wanted_volume != sound_volume)
-	{
-		lock_wait(sound_lock);
-		sound_volume = wanted_volume;
-		lock_release(sound_lock);
-	}
-	
-	return 0;
-}
-
-int snd_shutdown()
-{
-	SDL_CloseAudio();
-	lock_destroy(sound_lock);
-	return 0;
-}
-
-int snd_alloc_id()
-{
-	/* TODO: linear search, get rid of it */
-	unsigned sid;
-	for(sid = 0; sid < NUM_SAMPLES; sid++)
-	{
-		if(samples[sid].data == 0x0)
-			return sid;
-	}
-
-	return -1;
-}
-
-static void rate_convert(int sid)
-{
-	SAMPLE *snd = &samples[sid];
-	int num_frames = 0;
-	short *new_data = 0;
-	int i;
-	
-	/* make sure that we need to convert this sound */
-	if(!snd->data || snd->rate == mixing_rate)
-		return;
-
-	/* allocate new data */
-	num_frames = (int)((snd->num_frames/(float)snd->rate)*mixing_rate);
-	new_data = (short *)mem_alloc(num_frames*snd->channels*sizeof(short), 1);
-	
-	for(i = 0; i < num_frames; i++)
-	{
-		/* resample TODO: this should be done better, like linear atleast */
-		float a = i/(float)num_frames;
-		int f = (int)(a*snd->num_frames);
-		if(f >= snd->num_frames)
-			f = snd->num_frames-1;
-		
-		/* set new data */
-		if(snd->channels == 1)
-			new_data[i] = snd->data[f];
-		else if(snd->channels == 2)
-		{
-			new_data[i*2] = snd->data[f*2];
-			new_data[i*2+1] = snd->data[f*2+1];
-		}
-	}
-	
-	/* free old data and apply new */
-	mem_free(snd->data);
-	snd->data = new_data;
-	snd->num_frames = num_frames;
-}
-
-
-static IOHANDLE file = NULL;
-
-static int read_data(void *buffer, int size)
-{
-	return io_read(file, buffer, size);
-}
-
-int snd_load_wv(const char *filename)
-{
-	SAMPLE *snd;
-	int sid = -1;
-	char error[100];
-	WavpackContext *context;
-	
-	/* don't waste memory on sound when we are stress testing */
-	if(config.dbg_stress)
-		return -1;
-		
-	/* no need to load sound when we are running with no sound */
-	if(!sound_enabled)
-		return 1;
-
-	file = engine_openfile(filename, IOFLAG_READ); /* TODO: use system.h stuff for this */
-	if(!file)
-	{
-		dbg_msg("sound/wv", "failed to open %s", filename);
-		return -1;
-	}
-
-	sid = snd_alloc_id();
-	if(sid < 0)
-		return -1;
-	snd = &samples[sid];
-
-	context = WavpackOpenFileInput(read_data, error);
-	if (context)
-	{
-		int samples = WavpackGetNumSamples(context);
-		int bitspersample = WavpackGetBitsPerSample(context);
-		unsigned int samplerate = WavpackGetSampleRate(context);
-		int channels = WavpackGetNumChannels(context);
-		int *data;
-		int *src;
-		short *dst;
-		int i;
-
-		snd->channels = channels;
-		snd->rate = samplerate;
-
-		if(snd->channels > 2)
-		{
-			dbg_msg("sound/wv", "file is not mono or stereo. filename='%s'", filename);
-			return -1;
-		}
-
-		/*
-		if(snd->rate != 44100)
-		{
-			dbg_msg("sound/wv", "file is %d Hz, not 44100 Hz. filename='%s'", snd->rate, filename);
-			return -1;
-		}*/
-		
-		if(bitspersample != 16)
-		{
-			dbg_msg("sound/wv", "bps is %d, not 16, filname='%s'", bitspersample, filename);
-			return -1;
-		}
-
-		data = (int *)mem_alloc(4*samples*channels, 1);
-		WavpackUnpackSamples(context, data, samples); /* TODO: check return value */
-		src = data;
-		
-		snd->data = (short *)mem_alloc(2*samples*channels, 1);
-		dst = snd->data;
-
-		for (i = 0; i < samples*channels; i++)
-			*dst++ = (short)*src++;
-
-		mem_free(data);
-
-		snd->num_frames = samples;
-		snd->loop_start = -1;
-		snd->loop_end = -1;
-	}
-	else
-	{
-		dbg_msg("sound/wv", "failed to open %s: %s", filename, error);
-	}
-
-	io_close(file);
-	file = NULL;
-
-	if(config.debug)
-		dbg_msg("sound/wv", "loaded %s", filename);
-
-	rate_convert(sid);
-	return sid;
-}
-
-void snd_set_listener_pos(float x, float y)
-{
-	center_x = (int)x;
-	center_y = (int)y;
-}
diff --git a/src/engine/client/ec_srvbrowse.cpp b/src/engine/client/ec_srvbrowse.cpp
deleted file mode 100644
index 1b04937a..00000000
--- a/src/engine/client/ec_srvbrowse.cpp
+++ /dev/null
@@ -1,736 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <base/system.h>
-#include <engine/e_network.h>
-#include <engine/e_client_interface.h>
-#include <engine/e_config.h>
-#include <engine/e_memheap.h>
-#include <engine/e_engine.h>
-
-#include <mastersrv/mastersrv.h>
-
-#include <string.h>
-#include <stdlib.h>
-
-extern CNetClient m_NetClient;
-
-
-/* ------ server browse ---- */
-/* TODO: move all this to a separate file */
-
-typedef struct SERVERENTRY_t SERVERENTRY;
-struct SERVERENTRY_t
-{
-	NETADDR addr;
-	int64 request_time;
-	int got_info;
-	SERVER_INFO info;
-	
-	SERVERENTRY *next_ip; /* ip hashed list */
-	
-	SERVERENTRY *prev_req; /* request list */
-	SERVERENTRY *next_req;
-};
-
-static HEAP *serverlist_heap = 0;
-static SERVERENTRY **serverlist = 0;
-static int *sorted_serverlist = 0;
-
-enum
-{
-	MAX_FAVORITES=256
-};
-
-static NETADDR favorite_servers[MAX_FAVORITES];
-static int num_favorite_servers = 0;
-
-static SERVERENTRY *serverlist_ip[256] = {0}; /* ip hash list */
-
-static SERVERENTRY *first_req_server = 0; /* request list */
-static SERVERENTRY *last_req_server = 0;
-static int num_requests = 0;
-
-static int need_refresh = 0;
-
-static int num_sorted_servers = 0;
-static int num_sorted_servers_capacity = 0;
-static int num_servers = 0;
-static int num_server_capacity = 0;
-
-static int sorthash = 0;
-static char filterstring[64] = {0};
-static char filtergametypestring[128] = {0};
-
-/* the token is to keep server refresh separated from each other */
-static int current_token = 1;
-
-static int serverlist_type = 0;
-static int64 broadcast_time = 0;
-
-int client_serverbrowse_lan() { return serverlist_type == BROWSETYPE_LAN; }
-int client_serverbrowse_num() { return num_servers; }
-
-SERVER_INFO *client_serverbrowse_get(int index)
-{
-	if(index < 0 || index >= num_servers)
-		return 0;
-	return &serverlist[index]->info;
-}
-
-int client_serverbrowse_sorted_num() { return num_sorted_servers; }
-
-SERVER_INFO *client_serverbrowse_sorted_get(int index)
-{
-	if(index < 0 || index >= num_sorted_servers)
-		return 0;
-	return &serverlist[sorted_serverlist[index]]->info;
-}
-
-
-int client_serverbrowse_num_requests()
-{
-	return num_requests;
-}
-
-static int client_serverbrowse_sort_compare_name(const void *ai, const void *bi)
-{
-	SERVERENTRY *a = serverlist[*(const int*)ai];
-	SERVERENTRY *b = serverlist[*(const int*)bi];
-	return strcmp(a->info.name, b->info.name);
-}
-
-static int client_serverbrowse_sort_compare_map(const void *ai, const void *bi)
-{
-	SERVERENTRY *a = serverlist[*(const int*)ai];
-	SERVERENTRY *b = serverlist[*(const int*)bi];
-	return strcmp(a->info.map, b->info.map);
-}
-
-static int client_serverbrowse_sort_compare_ping(const void *ai, const void *bi)
-{
-	SERVERENTRY *a = serverlist[*(const int*)ai];
-	SERVERENTRY *b = serverlist[*(const int*)bi];
-	if(a->info.latency > b->info.latency) return 1;
-	if(a->info.latency < b->info.latency) return -1;
-	return 0;
-}
-
-static int client_serverbrowse_sort_compare_gametype(const void *ai, const void *bi)
-{
-	SERVERENTRY *a = serverlist[*(const int*)ai];
-	SERVERENTRY *b = serverlist[*(const int*)bi];
-	return strcmp(a->info.gametype, b->info.gametype);
-}
-
-static int client_serverbrowse_sort_compare_progression(const void *ai, const void *bi)
-{
-	SERVERENTRY *a = serverlist[*(const int*)ai];
-	SERVERENTRY *b = serverlist[*(const int*)bi];
-	if(a->info.progression > b->info.progression) return 1;
-	if(a->info.progression < b->info.progression) return -1;
-	return 0;
-}
-
-static int client_serverbrowse_sort_compare_numplayers(const void *ai, const void *bi)
-{
-	SERVERENTRY *a = serverlist[*(const int*)ai];
-	SERVERENTRY *b = serverlist[*(const int*)bi];
-	if(a->info.num_players > b->info.num_players) return 1;
-	if(a->info.num_players < b->info.num_players) return -1;
-	return 0;
-}
-
-static void client_serverbrowse_filter()
-{
-	int i = 0, p = 0;
-	num_sorted_servers = 0;
-
-	/* allocate the sorted list */	
-	if(num_sorted_servers_capacity < num_servers)
-	{
-		if(sorted_serverlist)
-			mem_free(sorted_serverlist);
-		num_sorted_servers_capacity = num_servers;
-		sorted_serverlist = (int *)mem_alloc(num_sorted_servers_capacity*sizeof(int), 1);
-	}
-	
-	/* filter the servers */
-	for(i = 0; i < num_servers; i++)
-	{
-		int filtered = 0;
-
-		if(config.b_filter_empty && serverlist[i]->info.num_players == 0)
-			filtered = 1;
-		else if(config.b_filter_full && serverlist[i]->info.num_players == serverlist[i]->info.max_players)
-			filtered = 1;
-		else if(config.b_filter_pw && serverlist[i]->info.flags&SRVFLAG_PASSWORD)
-			filtered = 1;
-		else if(config.b_filter_pure && (strcmp(serverlist[i]->info.gametype, "DM") != 0 && strcmp(serverlist[i]->info.gametype, "TDM") != 0 && strcmp(serverlist[i]->info.gametype, "CTF") != 0))
-			filtered = 1;
-		else if(config.b_filter_pure_map &&
-			!(strcmp(serverlist[i]->info.map, "dm1") == 0 ||
-			strcmp(serverlist[i]->info.map, "dm2") == 0 ||
-			strcmp(serverlist[i]->info.map, "dm6") == 0 ||
-			strcmp(serverlist[i]->info.map, "dm7") == 0 ||
-			strcmp(serverlist[i]->info.map, "dm8") == 0 ||
-			strcmp(serverlist[i]->info.map, "dm9") == 0 ||
-			strcmp(serverlist[i]->info.map, "ctf1") == 0 ||
-			strcmp(serverlist[i]->info.map, "ctf2") == 0 ||
-			strcmp(serverlist[i]->info.map, "ctf3") == 0 ||
-			strcmp(serverlist[i]->info.map, "ctf4") == 0 ||
-			strcmp(serverlist[i]->info.map, "ctf5") == 0)
-		)
-		{
-			filtered = 1;
-		}
-		else if(config.b_filter_ping < serverlist[i]->info.latency)
-			filtered = 1;
-		else if(config.b_filter_compatversion && strncmp(serverlist[i]->info.version, modc_net_version(), 3) != 0)
-			filtered = 1;
-		else 
-		{
-			if(config.b_filter_string[0] != 0)
-			{
-				int matchfound = 0;
-				
-				serverlist[i]->info.quicksearch_hit = 0;
-
-				/* match against server name */
-				if(str_find_nocase(serverlist[i]->info.name, config.b_filter_string))
-				{
-					matchfound = 1;
-					serverlist[i]->info.quicksearch_hit |= BROWSEQUICK_SERVERNAME;
-				}
-
-				/* match against players */				
-				for(p = 0; p < serverlist[i]->info.num_players; p++)
-				{
-					if(str_find_nocase(serverlist[i]->info.players[p].name, config.b_filter_string))
-					{
-						matchfound = 1;
-						serverlist[i]->info.quicksearch_hit |= BROWSEQUICK_PLAYERNAME;
-						break;
-					}
-				}
-				
-				/* match against map */
-				if(str_find_nocase(serverlist[i]->info.map, config.b_filter_string))
-				{
-					matchfound = 1;
-					serverlist[i]->info.quicksearch_hit |= BROWSEQUICK_MAPNAME;
-				}
-				
-				if(!matchfound)
-					filtered = 1;
-			}
-			
-			if(!filtered && config.b_filter_gametype[0] != 0)
-			{
-				/* match against game type */
-				if(!str_find_nocase(serverlist[i]->info.gametype, config.b_filter_gametype))
-					filtered = 1;
-			}
-		}
-
-		if(filtered == 0)
-			sorted_serverlist[num_sorted_servers++] = i;
-	}
-}
-
-static int client_serverbrowse_sorthash()
-{
-	int i = config.b_sort&0xf;
-	i |= config.b_filter_empty<<4;
-	i |= config.b_filter_full<<5;
-	i |= config.b_filter_pw<<6;
-	i |= config.b_sort_order<<7;
-	i |= config.b_filter_compatversion<<8;
-	i |= config.b_filter_pure<<9;
-	i |= config.b_filter_pure_map<<10;
-	i |= config.b_filter_ping<<16;
-	return i;
-}
-
-static void client_serverbrowse_sort()
-{
-	int i;
-	
-	/* create filtered list */
-	client_serverbrowse_filter();
-	
-	/* sort */
-	if(config.b_sort == BROWSESORT_NAME)
-		qsort(sorted_serverlist, num_sorted_servers, sizeof(int), client_serverbrowse_sort_compare_name);
-	else if(config.b_sort == BROWSESORT_PING)
-		qsort(sorted_serverlist, num_sorted_servers, sizeof(int), client_serverbrowse_sort_compare_ping);
-	else if(config.b_sort == BROWSESORT_MAP)
-		qsort(sorted_serverlist, num_sorted_servers, sizeof(int), client_serverbrowse_sort_compare_map);
-	else if(config.b_sort == BROWSESORT_NUMPLAYERS)
-		qsort(sorted_serverlist, num_sorted_servers, sizeof(int), client_serverbrowse_sort_compare_numplayers);
-	else if(config.b_sort == BROWSESORT_GAMETYPE)
-		qsort(sorted_serverlist, num_sorted_servers, sizeof(int), client_serverbrowse_sort_compare_gametype);
-	else if(config.b_sort == BROWSESORT_PROGRESSION)
-		qsort(sorted_serverlist, num_sorted_servers, sizeof(int), client_serverbrowse_sort_compare_progression);
-	
-	/* invert the list if requested */
-	if(config.b_sort_order)
-	{
-		for(i = 0; i < num_sorted_servers/2; i++)
-		{
-			int temp = sorted_serverlist[i];
-			sorted_serverlist[i] = sorted_serverlist[num_sorted_servers-i-1];
-			sorted_serverlist[num_sorted_servers-i-1] = temp;
-		}
-	}
-	
-	/* set indexes */
-	for(i = 0; i < num_sorted_servers; i++)
-		serverlist[sorted_serverlist[i]]->info.sorted_index = i;
-	
-	str_copy(filtergametypestring, config.b_filter_gametype, sizeof(filtergametypestring)); 
-	str_copy(filterstring, config.b_filter_string, sizeof(filterstring)); 
-	sorthash = client_serverbrowse_sorthash();
-}
-
-static void client_serverbrowse_remove_request(SERVERENTRY *entry)
-{
-	if(entry->prev_req || entry->next_req || first_req_server == entry)
-	{
-		if(entry->prev_req)
-			entry->prev_req->next_req = entry->next_req;
-		else
-			first_req_server = entry->next_req;
-			
-		if(entry->next_req)
-			entry->next_req->prev_req = entry->prev_req;
-		else
-			last_req_server = entry->prev_req;
-			
-		entry->prev_req = 0;
-		entry->next_req = 0;
-		num_requests--;
-	}
-}
-
-static SERVERENTRY *client_serverbrowse_find(NETADDR *addr)
-{
-	SERVERENTRY *entry = serverlist_ip[addr->ip[0]];
-	
-	for(; entry; entry = entry->next_ip)
-	{
-		if(net_addr_comp(&entry->addr, addr) == 0)
-			return entry;
-	}
-	return (SERVERENTRY*)0;
-}
-
-void client_serverbrowse_queuerequest(SERVERENTRY *entry)
-{
-	/* add it to the list of servers that we should request info from */
-	entry->prev_req = last_req_server;
-	if(last_req_server)
-		last_req_server->next_req = entry;
-	else
-		first_req_server = entry;
-	last_req_server = entry;
-	
-	num_requests++;
-}
-
-void client_serverbrowse_setinfo(SERVERENTRY *entry, SERVER_INFO *info)
-{
-	int fav = entry->info.favorite;
-	entry->info = *info;
-	entry->info.favorite = fav;
-	entry->info.netaddr = entry->addr;
-	
-	// all these are just for nice compability
-	if(entry->info.gametype[0] == '0' && entry->info.gametype[1] == 0)
-		str_copy(entry->info.gametype, "DM", sizeof(entry->info.gametype));
-	else if(entry->info.gametype[0] == '1' && entry->info.gametype[1] == 0)
-		str_copy(entry->info.gametype, "TDM", sizeof(entry->info.gametype));
-	else if(entry->info.gametype[0] == '2' && entry->info.gametype[1] == 0)
-		str_copy(entry->info.gametype, "CTF", sizeof(entry->info.gametype));
-
-	/*if(!request)
-	{
-		entry->info.latency = (time_get()-entry->request_time)*1000/time_freq();
-		client_serverbrowse_remove_request(entry);
-	}*/
-	
-	entry->got_info = 1;
-	client_serverbrowse_sort();	
-}
-
-SERVERENTRY *client_serverbrowse_add(NETADDR *addr)
-{
-	int hash = addr->ip[0];
-	SERVERENTRY *entry = 0;
-	int i;
-
-	/* create new entry */
-	entry = (SERVERENTRY *)memheap_allocate(serverlist_heap, sizeof(SERVERENTRY));
-	mem_zero(entry, sizeof(SERVERENTRY));
-	
-	/* set the info */
-	entry->addr = *addr;
-	entry->info.netaddr = *addr;
-	
-	entry->info.latency = 999;
-	str_format(entry->info.address, sizeof(entry->info.address), "%d.%d.%d.%d:%d",
-		addr->ip[0], addr->ip[1], addr->ip[2],
-		addr->ip[3], addr->port);
-	str_format(entry->info.name, sizeof(entry->info.name), "\255%d.%d.%d.%d:%d", /* the \255 is to make sure that it's sorted last */
-		addr->ip[0], addr->ip[1], addr->ip[2],
-		addr->ip[3], addr->port);	
-	
-	/*if(serverlist_type == BROWSETYPE_LAN)
-		entry->info.latency = (time_get()-broadcast_time)*1000/time_freq();*/
-
-	/* check if it's a favorite */
-	for(i = 0; i < num_favorite_servers; i++)
-	{
-		if(net_addr_comp(addr, &favorite_servers[i]) == 0)
-			entry->info.favorite = 1;
-	}
-	
-	/* add to the hash list */	
-	entry->next_ip = serverlist_ip[hash];
-	serverlist_ip[hash] = entry;
-	
-	if(num_servers == num_server_capacity)
-	{
-		SERVERENTRY **newlist;
-		num_server_capacity += 100;
-		newlist = (SERVERENTRY **)mem_alloc(num_server_capacity*sizeof(SERVERENTRY*), 1);
-		mem_copy(newlist, serverlist, num_servers*sizeof(SERVERENTRY*));
-		mem_free(serverlist);
-		serverlist = newlist;
-	}
-	
-	/* add to list */
-	serverlist[num_servers] = entry;
-	entry->info.server_index = num_servers;
-	num_servers++;
-	
-	return entry;
-}
-
-void client_serverbrowse_set(NETADDR *addr, int type, int token, SERVER_INFO *info)
-{
-	SERVERENTRY *entry = 0;
-	if(type == BROWSESET_MASTER_ADD)
-	{
-		if(serverlist_type != BROWSETYPE_INTERNET)
-			return;
-			
-		if(!client_serverbrowse_find(addr))
-		{
-			entry = client_serverbrowse_add(addr);
-			client_serverbrowse_queuerequest(entry);
-		}
-	}
-	else if(type == BROWSESET_FAV_ADD)
-	{
-		if(serverlist_type != BROWSETYPE_FAVORITES)
-			return;
-			
-		if(!client_serverbrowse_find(addr))
-		{
-			entry = client_serverbrowse_add(addr);
-			client_serverbrowse_queuerequest(entry);
-		}
-	}
-	else if(type == BROWSESET_TOKEN)
-	{
-		if(token != current_token)
-			return;
-			
-		entry = client_serverbrowse_find(addr);
-		if(!entry)
-			entry = client_serverbrowse_add(addr);
-		if(entry)
-		{
-			client_serverbrowse_setinfo(entry, info);
-			if(serverlist_type == BROWSETYPE_LAN)
-				entry->info.latency = (time_get()-broadcast_time)*1000/time_freq();
-			else
-				entry->info.latency = (time_get()-entry->request_time)*1000/time_freq();
-			client_serverbrowse_remove_request(entry);				
-		}
-	}
-	else if(type == BROWSESET_OLD_INTERNET)
-	{
-		entry = client_serverbrowse_find(addr);
-		if(entry)
-		{
-			client_serverbrowse_setinfo(entry, info);
-			
-			if(serverlist_type == BROWSETYPE_LAN)
-				entry->info.latency = (time_get()-broadcast_time)*1000/time_freq();
-			else
-				entry->info.latency = (time_get()-entry->request_time)*1000/time_freq();
-			client_serverbrowse_remove_request(entry);				
-		}
-	}
-	else if(type == BROWSESET_OLD_LAN)
-	{
-		entry = client_serverbrowse_find(addr);
-		if(entry)
-		if(!entry)
-			entry = client_serverbrowse_add(addr);
-		if(entry)
-			client_serverbrowse_setinfo(entry, info);
-	}
-	
-	client_serverbrowse_sort();
-}
-
-void client_serverbrowse_refresh(int type)
-{
-	/* clear out everything */
-	if(serverlist_heap)
-		memheap_destroy(serverlist_heap);
-	serverlist_heap = memheap_create();
-	num_servers = 0;
-	num_sorted_servers = 0;
-	mem_zero(serverlist_ip, sizeof(serverlist_ip));
-	first_req_server = 0;
-	last_req_server = 0;
-	num_requests = 0;
-	
-	/* next token */
-	current_token = (current_token+1)&0xff;
-	
-	/* */
-	serverlist_type = type;
-
-	if(type == BROWSETYPE_LAN)
-	{
-		unsigned char Buffer[sizeof(SERVERBROWSE_GETINFO)+1];
-		CNetChunk Packet;
-		int i;
-		
-		mem_copy(Buffer, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO));
-		Buffer[sizeof(SERVERBROWSE_GETINFO)] = current_token;
-			
-		Packet.m_ClientID = -1;
-		mem_zero(&Packet, sizeof(Packet));
-		Packet.m_Address.ip[0] = 255;
-		Packet.m_Address.ip[1] = 255;
-		Packet.m_Address.ip[2] = 255;
-		Packet.m_Address.ip[3] = 255;
-		Packet.m_Flags = NETSENDFLAG_CONNLESS;
-		Packet.m_DataSize = sizeof(Buffer);
-		Packet.m_pData = Buffer;
-		broadcast_time = time_get();
-
-		for(i = 8303; i <= 8310; i++)
-		{
-			Packet.m_Address.port = i;
-			m_NetClient.Send(&Packet);
-		}
-
-		if(config.debug)
-			dbg_msg("client", "broadcasting for servers");
-	}
-	else if(type == BROWSETYPE_INTERNET)
-		need_refresh = 1;
-	else if(type == BROWSETYPE_FAVORITES)
-	{
-		for(int i = 0; i < num_favorite_servers; i++)
-			client_serverbrowse_set(&favorite_servers[i], BROWSESET_FAV_ADD, -1, 0);
-	}
-}
-
-static void client_serverbrowse_request_impl(NETADDR *addr, SERVERENTRY *entry)
-{
-	/*unsigned char buffer[sizeof(SERVERBROWSE_GETINFO)+1];*/
-	CNetChunk Packet;
-
-	if(config.debug)
-	{
-		dbg_msg("client", "requesting server info from %d.%d.%d.%d:%d",
-			addr->ip[0], addr->ip[1], addr->ip[2],
-			addr->ip[3], addr->port);
-	}
-	
-	/*mem_copy(buffer, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO));
-	buffer[sizeof(SERVERBROWSE_GETINFO)] = current_token;*/
-	
-	Packet.m_ClientID = -1;
-	Packet.m_Address = *addr;
-	Packet.m_Flags = NETSENDFLAG_CONNLESS;
-	/*p.data_size = sizeof(buffer);
-	p.data = buffer;
-	netclient_send(net, &p);*/
-
-	/* send old requtest style aswell */	
-	Packet.m_DataSize = sizeof(SERVERBROWSE_OLD_GETINFO);
-	Packet.m_pData = SERVERBROWSE_OLD_GETINFO;
-	m_NetClient.Send(&Packet);
-	
-	if(entry)
-		entry->request_time = time_get();
-}
-
-void client_serverbrowse_request(NETADDR *addr)
-{
-	client_serverbrowse_request_impl(addr, 0);
-}
-
-
-void client_serverbrowse_update()
-{
-	int64 timeout = time_freq();
-	int64 now = time_get();
-	int count;
-	SERVERENTRY *entry, *next;
-	
-	/* do server list requests */
-	if(need_refresh && !mastersrv_refreshing())
-	{
-		NETADDR addr;
-		CNetChunk Packet;
-		int i;
-		
-		need_refresh = 0;
-		
-		mem_zero(&Packet, sizeof(Packet));
-		Packet.m_ClientID = -1;
-		Packet.m_Flags = NETSENDFLAG_CONNLESS;
-		Packet.m_DataSize = sizeof(SERVERBROWSE_GETLIST);
-		Packet.m_pData = SERVERBROWSE_GETLIST;
-		
-		for(i = 0; i < MAX_MASTERSERVERS; i++)
-		{
-			addr = mastersrv_get(i);
-			if(!addr.ip[0] && !addr.ip[1] && !addr.ip[2] && !addr.ip[3])
-				continue;
-			
-			Packet.m_Address = addr;
-			m_NetClient.Send(&Packet);
-		}
-
-		if(config.debug)
-			dbg_msg("client", "requesting server list");
-	}
-	
-	/* do timeouts */
-	entry = first_req_server;
-	while(1)
-	{
-		if(!entry) /* no more entries */
-			break;
-			
-		next = entry->next_req;
-		
-		if(entry->request_time && entry->request_time+timeout < now)
-		{
-			/* timeout */
-			client_serverbrowse_remove_request(entry);
-			num_requests--;
-		}
-			
-		entry = next;
-	}
-
-	/* do timeouts */
-	entry = first_req_server;
-	count = 0;
-	while(1)
-	{
-		if(!entry) /* no more entries */
-			break;
-		
-		/* no more then 10 concurrent requests */
-		if(count == config.b_max_requests)
-			break;
-			
-		if(entry->request_time == 0)
-			client_serverbrowse_request_impl(&entry->addr, entry);
-		
-		count++;
-		entry = entry->next_req;
-	}
-	
-	/* check if we need to resort */
-	/* TODO: remove the strcmp */
-	if(sorthash != client_serverbrowse_sorthash() || strcmp(filterstring, config.b_filter_string) != 0 || strcmp(filtergametypestring, config.b_filter_gametype) != 0)
-		client_serverbrowse_sort();
-}
-
-
-int client_serverbrowse_isfavorite(NETADDR addr)
-{
-	/* search for the address */
-	int i;
-	for(i = 0; i < num_favorite_servers; i++)
-	{
-		if(net_addr_comp(&addr, &favorite_servers[i]) == 0)
-			return 1;
-	}
-	return 0;
-}
-
-void client_serverbrowse_addfavorite(NETADDR addr)
-{
-	int i;
-	SERVERENTRY *entry;
-	
-	if(num_favorite_servers == MAX_FAVORITES)
-		return;
-
-	/* make sure that we don't already have the server in our list */
-	for(i = 0; i < num_favorite_servers; i++)
-	{
-		if(net_addr_comp(&addr, &favorite_servers[i]) == 0)
-			return;
-	}
-	
-	/* add the server to the list */
-	favorite_servers[num_favorite_servers++] = addr;
-	entry = client_serverbrowse_find(&addr);
-	if(entry)
-		entry->info.favorite = 1;
-	dbg_msg("", "added fav, %p", entry);
-}
-
-void client_serverbrowse_removefavorite(NETADDR addr)
-{
-	int i;
-	SERVERENTRY *entry;
-	
-	for(i = 0; i < num_favorite_servers; i++)
-	{
-		if(net_addr_comp(&addr, &favorite_servers[i]) == 0)
-		{
-			mem_move(&favorite_servers[i], &favorite_servers[i+1], num_favorite_servers-(i+1));
-			num_favorite_servers--;
-
-			entry = client_serverbrowse_find(&addr);
-			if(entry)
-				entry->info.favorite = 0;
-
-			return;
-		}
-	}
-}
-
-void client_serverbrowse_save()
-{
-	int i;
-	char addrstr[128];
-	char buffer[256];
-	for(i = 0; i < num_favorite_servers; i++)
-	{
-		net_addr_str(&favorite_servers[i], addrstr, sizeof(addrstr));
-		str_format(buffer, sizeof(buffer), "add_favorite %s", addrstr);
-		engine_config_write_line(buffer);
-	}
-}
-
-
-int client_serverbrowse_refreshingmasters()
-{
-	return mastersrv_refreshing();
-}
diff --git a/src/engine/client/editor.h b/src/engine/client/editor.h
deleted file mode 100644
index 336a46d4..00000000
--- a/src/engine/client/editor.h
+++ /dev/null
@@ -1,10 +0,0 @@
-
-class IEditor
-{
-public:
-	virtual ~IEditor() {}
-	virtual void Init(class IGraphics *pGraphics) = 0;
-	virtual void UpdateAndRender() = 0;
-};
-
-extern IEditor *CreateEditor();
diff --git a/src/engine/client/graphics.cpp b/src/engine/client/graphics.cpp
new file mode 100644
index 00000000..7c355fb8
--- /dev/null
+++ b/src/engine/client/graphics.cpp
@@ -0,0 +1,938 @@
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+
+#include <base/detect.h>
+
+#include "SDL.h"
+
+#ifdef CONF_FAMILY_WINDOWS
+	#define WIN32_LEAN_AND_MEAN
+	#include <windows.h>
+#endif
+
+#ifdef CONF_PLATFORM_MACOSX
+	#include <OpenGL/gl.h>
+	#include <OpenGL/glu.h>
+#else
+	#include <GL/gl.h>
+	#include <GL/glu.h>
+#endif
+
+#include <base/system.h>
+#include <engine/external/pnglite/pnglite.h>
+
+#include <engine/shared/engine.h>
+#include <engine/shared/config.h>
+#include <engine/graphics.h>
+#include <engine/storage.h>
+#include <engine/keys.h>
+
+#include <math.h>
+
+#include "graphics.h"
+
+// compressed textures
+#define GL_COMPRESSED_RGB_ARB 0x84ED
+#define GL_COMPRESSED_RGBA_ARB 0x84EE
+#define GL_COMPRESSED_ALPHA_ARB 0x84E9
+
+#define TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+
+
+static CVideoMode g_aFakeModes[] = {
+	{320,240,8,8,8}, {400,300,8,8,8}, {640,480,8,8,8},
+	{720,400,8,8,8}, {768,576,8,8,8}, {800,600,8,8,8},
+	{1024,600,8,8,8}, {1024,768,8,8,8}, {1152,864,8,8,8},
+	{1280,768,8,8,8}, {1280,800,8,8,8}, {1280,960,8,8,8},
+	{1280,1024,8,8,8}, {1368,768,8,8,8}, {1400,1050,8,8,8},
+	{1440,900,8,8,8}, {1440,1050,8,8,8}, {1600,1000,8,8,8},
+	{1600,1200,8,8,8}, {1680,1050,8,8,8}, {1792,1344,8,8,8},
+	{1800,1440,8,8,8}, {1856,1392,8,8,8}, {1920,1080,8,8,8},
+	{1920,1200,8,8,8}, {1920,1440,8,8,8}, {1920,2400,8,8,8},
+	{2048,1536,8,8,8},
+		
+	{320,240,5,6,5}, {400,300,5,6,5}, {640,480,5,6,5},
+	{720,400,5,6,5}, {768,576,5,6,5}, {800,600,5,6,5},
+	{1024,600,5,6,5}, {1024,768,5,6,5}, {1152,864,5,6,5},
+	{1280,768,5,6,5}, {1280,800,5,6,5}, {1280,960,5,6,5},
+	{1280,1024,5,6,5}, {1368,768,5,6,5}, {1400,1050,5,6,5},
+	{1440,900,5,6,5}, {1440,1050,5,6,5}, {1600,1000,5,6,5},
+	{1600,1200,5,6,5}, {1680,1050,5,6,5}, {1792,1344,5,6,5},
+	{1800,1440,5,6,5}, {1856,1392,5,6,5}, {1920,1080,5,6,5},
+	{1920,1200,5,6,5}, {1920,1440,5,6,5}, {1920,2400,5,6,5},
+	{2048,1536,5,6,5}
+};
+
+void CGraphics_OpenGL::Flush()
+{
+	if(m_NumVertices == 0)
+		return;
+		
+	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+	glVertexPointer(3, GL_FLOAT,
+			sizeof(CVertex),
+			(char*)m_aVertices);
+	glTexCoordPointer(2, GL_FLOAT,
+			sizeof(CVertex),
+			(char*)m_aVertices + sizeof(float)*3);
+	glColorPointer(4, GL_FLOAT,
+			sizeof(CVertex),
+			(char*)m_aVertices + sizeof(float)*5);
+	glEnableClientState(GL_VERTEX_ARRAY);
+	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+	glEnableClientState(GL_COLOR_ARRAY);
+	
+	if(m_RenderEnable)
+	{
+		if(m_Drawing == DRAWING_QUADS)
+			glDrawArrays(GL_QUADS, 0, m_NumVertices);
+		else if(m_Drawing == DRAWING_LINES)
+			glDrawArrays(GL_LINES, 0, m_NumVertices);
+	}
+	
+	// Reset pointer
+	m_NumVertices = 0;
+}
+
+void CGraphics_OpenGL::AddVertices(int Count)
+{
+	m_NumVertices += Count;
+	if((m_NumVertices + Count) >= MAX_VERTICES)
+		Flush();
+}
+
+void CGraphics_OpenGL::Rotate4(CPoint *pCenter, CVertex *pPoints)
+{
+	float c = cosf(m_Rotation);
+	float s = sinf(m_Rotation);
+	float x, y;
+	int i;
+
+	for(i = 0; i < 4; i++)
+	{
+		x = pPoints[i].m_Pos.x - pCenter->x;
+		y = pPoints[i].m_Pos.y - pCenter->y;
+		pPoints[i].m_Pos.x = x * c - y * s + pCenter->x;
+		pPoints[i].m_Pos.y = x * s + y * c + pCenter->y;
+	}
+}
+
+unsigned char CGraphics_OpenGL::Sample(int w, int h, const unsigned char *pData, int u, int v, int Offset)
+{
+	return (pData[(v*w+u)*4+Offset]+
+	pData[(v*w+u+1)*4+Offset]+
+	pData[((v+1)*w+u)*4+Offset]+
+	pData[((v+1)*w+u+1)*4+Offset])/4;
+}	
+
+CGraphics_OpenGL::CGraphics_OpenGL()
+{
+	m_NumVertices = 0;
+	
+	m_ScreenX0 = 0;
+	m_ScreenY0 = 0;
+	m_ScreenX1 = 0;
+	m_ScreenY1 = 0;
+	
+	m_ScreenWidth = -1;
+	m_ScreenHeight = -1;
+	
+	m_Rotation = 0;
+	m_Drawing = 0;
+	m_InvalidTexture = 0;
+	
+	m_TextureMemoryUsage = 0;
+	
+	m_RenderEnable = true;
+	m_DoScreenshot = false;
+}
+
+void CGraphics_OpenGL::ClipEnable(int x, int y, int w, int h)
+{
+	//if(no_gfx) return;
+	glScissor(x, ScreenHeight()-(y+h), w, h);
+	glEnable(GL_SCISSOR_TEST);
+}
+
+void CGraphics_OpenGL::ClipDisable()
+{
+	//if(no_gfx) return;
+	glDisable(GL_SCISSOR_TEST);
+}
+	
+void CGraphics_OpenGL::BlendNone()
+{
+	glDisable(GL_BLEND);
+}
+
+void CGraphics_OpenGL::BlendNormal()
+{
+	glEnable(GL_BLEND);
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+}
+
+void CGraphics_OpenGL::BlendAdditive()
+{
+	glEnable(GL_BLEND);
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+}
+
+int CGraphics_OpenGL::MemoryUsage() const
+{ 
+	return m_TextureMemoryUsage;
+}	
+	
+void CGraphics_OpenGL::MapScreen(float TopLeftX, float TopLeftY, float BottomRightX, float BottomRightY)
+{
+	m_ScreenX0 = TopLeftX;
+	m_ScreenY0 = TopLeftY;
+	m_ScreenX1 = BottomRightX;
+	m_ScreenY1 = BottomRightY;
+	glMatrixMode(GL_PROJECTION);
+	glLoadIdentity();
+	glOrtho(TopLeftX, BottomRightX, BottomRightY, TopLeftY, 1.0f, 10.f);
+}
+
+void CGraphics_OpenGL::GetScreen(float *pTopLeftX, float *pTopLeftY, float *pBottomRightX, float *pBottomRightY)
+{
+	*pTopLeftX = m_ScreenX0;
+	*pTopLeftY = m_ScreenY0;
+	*pBottomRightX = m_ScreenX1;
+	*pBottomRightY = m_ScreenY1;
+}
+
+void CGraphics_OpenGL::LinesBegin()
+{
+	dbg_assert(m_Drawing == 0, "called begin twice");
+	m_Drawing = DRAWING_LINES;
+	SetColor(1,1,1,1);
+}
+
+void CGraphics_OpenGL::LinesEnd()
+{
+	dbg_assert(m_Drawing == DRAWING_LINES, "called end without begin");
+	Flush();
+	m_Drawing = 0;
+}
+
+void CGraphics_OpenGL::LinesDraw(const CLineItem *pArray, int Num)
+{
+	dbg_assert(m_Drawing == DRAWING_LINES, "called draw without begin");
+	
+	for(int i = 0; i < Num; ++i)
+	{
+		m_aVertices[m_NumVertices + 2*i].m_Pos.x = pArray[i].m_X0;
+		m_aVertices[m_NumVertices + 2*i].m_Pos.y = pArray[i].m_Y0;
+		m_aVertices[m_NumVertices + 2*i].m_Tex = m_aTexture[0];
+		m_aVertices[m_NumVertices + 2*i].m_Color = m_aColor[0];
+
+		m_aVertices[m_NumVertices + 2*i + 1].m_Pos.x = pArray[i].m_X1;
+		m_aVertices[m_NumVertices + 2*i + 1].m_Pos.y = pArray[i].m_Y1;
+		m_aVertices[m_NumVertices + 2*i + 1].m_Tex = m_aTexture[1];
+		m_aVertices[m_NumVertices + 2*i + 1].m_Color = m_aColor[1];
+	}
+
+	AddVertices(2*Num);
+}
+
+int CGraphics_OpenGL::UnloadTexture(int Index)
+{
+	if(Index == m_InvalidTexture)
+		return 0;
+		
+	if(Index < 0)
+		return 0;
+		
+	glDeleteTextures(1, &m_aTextures[Index].m_Tex);
+	m_aTextures[Index].m_Next = m_FirstFreeTexture;
+	m_TextureMemoryUsage -= m_aTextures[Index].m_MemSize;
+	m_FirstFreeTexture = Index;
+	return 0;
+}
+
+
+int CGraphics_OpenGL::LoadTextureRaw(int Width, int Height, int Format, const void *pData, int StoreFormat, int Flags)
+{
+	int Mipmap = 1;
+	unsigned char *pTexData = (unsigned char *)pData;
+	unsigned char *pTmpData = 0;
+	int Oglformat = 0;
+	int StoreOglformat = 0;
+	int Tex = 0;
+	
+	// don't waste memory on texture if we are stress testing
+	if(g_Config.m_DbgStress)
+		return 	m_InvalidTexture;
+	
+	// grab texture
+	Tex = m_FirstFreeTexture;
+	m_FirstFreeTexture = m_aTextures[Tex].m_Next;
+	m_aTextures[Tex].m_Next = -1;
+	
+	// resample if needed
+	if(!(Flags&TEXLOAD_NORESAMPLE) && g_Config.m_GfxTextureQuality==0)
+	{
+		if(Width > 16 && Height > 16 && Format == CImageInfo::FORMAT_RGBA)
+		{
+			unsigned char *pTmpData;
+			int c = 0;
+			int x, y;
+
+			pTmpData = (unsigned char *)mem_alloc(Width*Height*4, 1);
+
+			Width/=2;
+			Height/=2;
+
+			for(y = 0; y < Height; y++)
+				for(x = 0; x < Width; x++, c++)
+				{
+					pTmpData[c*4] = Sample(Width*2, Height*2, pTexData, x*2,y*2, 0);
+					pTmpData[c*4+1] = Sample(Width*2, Height*2, pTexData, x*2,y*2, 1);
+					pTmpData[c*4+2] = Sample(Width*2, Height*2, pTexData, x*2,y*2, 2);
+					pTmpData[c*4+3] = Sample(Width*2, Height*2, pTexData, x*2,y*2, 3);
+				}
+			pTexData = pTmpData;
+		}
+	}
+	
+	Oglformat = GL_RGBA;
+	if(Format == CImageInfo::FORMAT_RGB)
+		Oglformat = GL_RGB;
+	else if(Format == CImageInfo::FORMAT_ALPHA)
+		Oglformat = GL_ALPHA;
+	
+	// upload texture
+	if(g_Config.m_GfxTextureCompression)
+	{
+		StoreOglformat = GL_COMPRESSED_RGBA_ARB;
+		if(StoreFormat == CImageInfo::FORMAT_RGB)
+			StoreOglformat = GL_COMPRESSED_RGB_ARB;
+		else if(StoreFormat == CImageInfo::FORMAT_ALPHA)
+			StoreOglformat = GL_COMPRESSED_ALPHA_ARB;
+	}
+	else
+	{
+		StoreOglformat = GL_RGBA;
+		if(StoreFormat == CImageInfo::FORMAT_RGB)
+			StoreOglformat = GL_RGB;
+		else if(StoreFormat == CImageInfo::FORMAT_ALPHA)
+			StoreOglformat = GL_ALPHA;
+	}
+		
+	glGenTextures(1, &m_aTextures[Tex].m_Tex);
+	glBindTexture(GL_TEXTURE_2D, m_aTextures[Tex].m_Tex);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+	gluBuild2DMipmaps(GL_TEXTURE_2D, StoreOglformat, Width, Height, Oglformat, GL_UNSIGNED_BYTE, pTexData);
+	
+	// calculate memory usage
+	{
+		int PixelSize = 4;
+		if(StoreFormat == CImageInfo::FORMAT_RGB)
+			PixelSize = 3;
+		else if(StoreFormat == CImageInfo::FORMAT_ALPHA)
+			PixelSize = 1;
+
+		m_aTextures[Tex].m_MemSize = Width*Height*PixelSize;
+		if(Mipmap)
+		{
+			while(Width > 2 && Height > 2)
+			{
+				Width>>=1;
+				Height>>=1;
+				m_aTextures[Tex].m_MemSize += Width*Height*PixelSize;
+			}
+		}
+	}
+	
+	m_TextureMemoryUsage += m_aTextures[Tex].m_MemSize;
+	mem_free(pTmpData);
+	return Tex;
+}
+
+// simple uncompressed RGBA loaders
+int CGraphics_OpenGL::LoadTexture(const char *pFilename, int StoreFormat, int Flags)
+{
+	int l = str_length(pFilename);
+	int Id;
+	CImageInfo Img;
+	
+	if(l < 3)
+		return -1;
+	if(LoadPNG(&Img, pFilename))
+	{
+		if (StoreFormat == CImageInfo::FORMAT_AUTO)
+			StoreFormat = Img.m_Format;
+
+		Id = LoadTextureRaw(Img.m_Width, Img.m_Height, Img.m_Format, Img.m_pData, StoreFormat, Flags);
+		mem_free(Img.m_pData);
+		return Id;
+	}
+	
+	return m_InvalidTexture;
+}
+
+int CGraphics_OpenGL::LoadPNG(CImageInfo *pImg, const char *pFilename)
+{
+	char aCompleteFilename[512];
+	unsigned char *pBuffer;
+	png_t Png; // ignore_convention
+	
+	// open file for reading
+	png_init(0,0); // ignore_convention
+
+	IOHANDLE File = m_pStorage->OpenFile(pFilename, IOFLAG_READ, aCompleteFilename, sizeof(aCompleteFilename));
+	if(File)
+		io_close(File);
+	
+	if(png_open_file(&Png, aCompleteFilename) != PNG_NO_ERROR) // ignore_convention
+	{
+		dbg_msg("game/png", "failed to open file. filename='%s'", aCompleteFilename);
+		return 0;
+	}
+	
+	if(Png.depth != 8 || (Png.color_type != PNG_TRUECOLOR && Png.color_type != PNG_TRUECOLOR_ALPHA)) // ignore_convention
+	{
+		dbg_msg("game/png", "invalid format. filename='%s'", aCompleteFilename);
+		png_close_file(&Png); // ignore_convention
+		return 0;
+	}
+		
+	pBuffer = (unsigned char *)mem_alloc(Png.width * Png.height * Png.bpp, 1); // ignore_convention
+	png_get_data(&Png, pBuffer); // ignore_convention
+	png_close_file(&Png); // ignore_convention
+	
+	pImg->m_Width = Png.width; // ignore_convention
+	pImg->m_Height = Png.height; // ignore_convention
+	if(Png.color_type == PNG_TRUECOLOR) // ignore_convention
+		pImg->m_Format = CImageInfo::FORMAT_RGB;
+	else if(Png.color_type == PNG_TRUECOLOR_ALPHA) // ignore_convention
+		pImg->m_Format = CImageInfo::FORMAT_RGBA;
+	pImg->m_pData = pBuffer;
+	return 1;
+}
+
+void CGraphics_OpenGL::ScreenshotDirect(const char *pFilename)
+{
+	// fetch image data
+	int y;
+	int w = m_ScreenWidth;
+	int h = m_ScreenHeight;
+	unsigned char *pPixelData = (unsigned char *)mem_alloc(w*(h+1)*4, 1);
+	unsigned char *pTempRow = pPixelData+w*h*4;
+	glReadPixels(0,0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pPixelData);
+	
+	// flip the pixel because opengl works from bottom left corner
+	for(y = 0; y < h/2; y++)
+	{
+		mem_copy(pTempRow, pPixelData+y*w*4, w*4);
+		mem_copy(pPixelData+y*w*4, pPixelData+(h-y-1)*w*4, w*4);
+		mem_copy(pPixelData+(h-y-1)*w*4, pTempRow,w*4);
+	}
+	
+	// find filename
+	{
+		char aWholePath[1024];
+		png_t Png; // ignore_convention
+
+		IOHANDLE File  = m_pStorage->OpenFile(pFilename, IOFLAG_WRITE, aWholePath, sizeof(aWholePath));
+		if(File)
+			io_close(File);
+	
+		// save png
+		dbg_msg("client", "saved screenshot to '%s'", aWholePath);
+		png_open_file_write(&Png, aWholePath); // ignore_convention
+		png_set_data(&Png, w, h, 8, PNG_TRUECOLOR_ALPHA, (unsigned char *)pPixelData); // ignore_convention
+		png_close_file(&Png); // ignore_convention
+	}
+
+	// clean up
+	mem_free(pPixelData);
+}
+
+void CGraphics_OpenGL::TextureSet(int TextureID)
+{
+	dbg_assert(m_Drawing == 0, "called Graphics()->TextureSet within begin");
+	if(TextureID == -1)
+	{
+		glDisable(GL_TEXTURE_2D);
+	}
+	else
+	{
+		glEnable(GL_TEXTURE_2D);
+		glBindTexture(GL_TEXTURE_2D, m_aTextures[TextureID].m_Tex);
+	}
+}
+
+void CGraphics_OpenGL::Clear(float r, float g, float b)
+{
+	glClearColor(r,g,b,0.0f);
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+
+void CGraphics_OpenGL::QuadsBegin()
+{
+	dbg_assert(m_Drawing == 0, "called quads_begin twice");
+	m_Drawing = DRAWING_QUADS;
+	
+	QuadsSetSubset(0,0,1,1);
+	QuadsSetRotation(0);
+	SetColor(1,1,1,1);
+}
+
+void CGraphics_OpenGL::QuadsEnd()
+{
+	dbg_assert(m_Drawing == DRAWING_QUADS, "called quads_end without begin");
+	Flush();
+	m_Drawing = 0;
+}
+
+void CGraphics_OpenGL::QuadsSetRotation(float Angle)
+{
+	dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsSetRotation without begin");
+	m_Rotation = Angle;
+}
+
+void CGraphics_OpenGL::SetColorVertex(const CColorVertex *pArray, int Num)
+{
+	dbg_assert(m_Drawing != 0, "called gfx_quads_setcolorvertex without begin");
+
+	for(int i = 0; i < Num; ++i)
+	{
+		m_aColor[pArray[i].m_Index].r = pArray[i].m_R;
+		m_aColor[pArray[i].m_Index].g = pArray[i].m_G;
+		m_aColor[pArray[i].m_Index].b = pArray[i].m_B;
+		m_aColor[pArray[i].m_Index].a = pArray[i].m_A;
+	}
+}
+
+void CGraphics_OpenGL::SetColor(float r, float g, float b, float a)
+{
+	dbg_assert(m_Drawing != 0, "called gfx_quads_setcolor without begin");
+	CColorVertex Array[4] = {
+		CColorVertex(0, r, g, b, a),
+		CColorVertex(1, r, g, b, a),
+		CColorVertex(2, r, g, b, a),
+		CColorVertex(3, r, g, b, a)};
+	SetColorVertex(Array, 4);
+}
+
+void CGraphics_OpenGL::QuadsSetSubset(float TlU, float TlV, float BrU, float BrV)
+{
+	dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsSetSubset without begin");
+
+	m_aTexture[0].u = TlU;	m_aTexture[1].u = BrU;
+	m_aTexture[0].v = TlV;	m_aTexture[1].v = TlV;
+
+	m_aTexture[3].u = TlU;	m_aTexture[2].u = BrU;
+	m_aTexture[3].v = BrV;	m_aTexture[2].v = BrV;
+}
+
+void CGraphics_OpenGL::QuadsSetSubsetFree(
+	float x0, float y0, float x1, float y1,
+	float x2, float y2, float x3, float y3)
+{
+	m_aTexture[0].u = x0; m_aTexture[0].v = y0;
+	m_aTexture[1].u = x1; m_aTexture[1].v = y1;
+	m_aTexture[2].u = x2; m_aTexture[2].v = y2;
+	m_aTexture[3].u = x3; m_aTexture[3].v = y3;
+}
+
+void CGraphics_OpenGL::QuadsDraw(CQuadItem *pArray, int Num)
+{
+	for(int i = 0; i < Num; ++i)
+	{
+		pArray[i].m_X -= pArray[i].m_Width/2;
+		pArray[i].m_Y -= pArray[i].m_Height/2;
+	}
+
+	QuadsDrawTL(pArray, Num);
+}
+
+void CGraphics_OpenGL::QuadsDrawTL(const CQuadItem *pArray, int Num)
+{
+	CPoint Center;
+
+	dbg_assert(m_Drawing == DRAWING_QUADS, "called quads_draw without begin");
+
+	for(int i = 0; i < Num; ++i)
+	{
+		Center.x = pArray[i].m_X + pArray[i].m_Width/2;
+		Center.y = pArray[i].m_Y + pArray[i].m_Height/2;
+		Center.z = 0;
+		
+		m_aVertices[m_NumVertices + 4*i].m_Pos.x = pArray[i].m_X;
+		m_aVertices[m_NumVertices + 4*i].m_Pos.y = pArray[i].m_Y;
+		m_aVertices[m_NumVertices + 4*i].m_Tex = m_aTexture[0];
+		m_aVertices[m_NumVertices + 4*i].m_Color = m_aColor[0];
+
+		m_aVertices[m_NumVertices + 4*i + 1].m_Pos.x = pArray[i].m_X + pArray[i].m_Width;
+		m_aVertices[m_NumVertices + 4*i + 1].m_Pos.y = pArray[i].m_Y;
+		m_aVertices[m_NumVertices + 4*i + 1].m_Tex = m_aTexture[1];
+		m_aVertices[m_NumVertices + 4*i + 1].m_Color = m_aColor[1];
+
+		m_aVertices[m_NumVertices + 4*i + 2].m_Pos.x = pArray[i].m_X + pArray[i].m_Width;
+		m_aVertices[m_NumVertices + 4*i + 2].m_Pos.y = pArray[i].m_Y + pArray[i].m_Height;
+		m_aVertices[m_NumVertices + 4*i + 2].m_Tex = m_aTexture[2];
+		m_aVertices[m_NumVertices + 4*i + 2].m_Color = m_aColor[2];
+
+		m_aVertices[m_NumVertices + 4*i + 3].m_Pos.x = pArray[i].m_X;
+		m_aVertices[m_NumVertices + 4*i + 3].m_Pos.y = pArray[i].m_Y + pArray[i].m_Height;
+		m_aVertices[m_NumVertices + 4*i + 3].m_Tex = m_aTexture[3];
+		m_aVertices[m_NumVertices + 4*i + 3].m_Color = m_aColor[3];
+
+		if(m_Rotation != 0)
+			Rotate4(&Center, &m_aVertices[m_NumVertices + 4*i]);
+	}
+
+	AddVertices(4*Num);
+}
+
+void CGraphics_OpenGL::QuadsDrawFreeform(const CFreeformItem *pArray, int Num)
+{
+	dbg_assert(m_Drawing == DRAWING_QUADS, "called quads_draw_freeform without begin");
+	
+	for(int i = 0; i < Num; ++i)
+	{
+		m_aVertices[m_NumVertices + 4*i].m_Pos.x = pArray[i].m_X0;
+		m_aVertices[m_NumVertices + 4*i].m_Pos.y = pArray[i].m_Y0;
+		m_aVertices[m_NumVertices + 4*i].m_Tex = m_aTexture[0];
+		m_aVertices[m_NumVertices + 4*i].m_Color = m_aColor[0];
+
+		m_aVertices[m_NumVertices + 4*i + 1].m_Pos.x = pArray[i].m_X1;
+		m_aVertices[m_NumVertices + 4*i + 1].m_Pos.y = pArray[i].m_Y1;
+		m_aVertices[m_NumVertices + 4*i + 1].m_Tex = m_aTexture[1];
+		m_aVertices[m_NumVertices + 4*i + 1].m_Color = m_aColor[1];
+
+		m_aVertices[m_NumVertices + 4*i + 2].m_Pos.x = pArray[i].m_X3;
+		m_aVertices[m_NumVertices + 4*i + 2].m_Pos.y = pArray[i].m_Y3;
+		m_aVertices[m_NumVertices + 4*i + 2].m_Tex = m_aTexture[3];
+		m_aVertices[m_NumVertices + 4*i + 2].m_Color = m_aColor[3];
+
+		m_aVertices[m_NumVertices + 4*i + 3].m_Pos.x = pArray[i].m_X2;
+		m_aVertices[m_NumVertices + 4*i + 3].m_Pos.y = pArray[i].m_Y2;
+		m_aVertices[m_NumVertices + 4*i + 3].m_Tex = m_aTexture[2];
+		m_aVertices[m_NumVertices + 4*i + 3].m_Color = m_aColor[2];
+	}
+	
+	AddVertices(4*Num);
+}
+
+void CGraphics_OpenGL::QuadsText(float x, float y, float Size, float r, float g, float b, float a, const char *pText)
+{
+	float StartX = x;
+
+	QuadsBegin();
+	SetColor(r,g,b,a);
+
+	while(*pText)
+	{
+		char c = *pText;
+		pText++;
+		
+		if(c == '\n')
+		{
+			x = StartX;
+			y += Size;
+		}
+		else
+		{
+			QuadsSetSubset(
+				(c%16)/16.0f,
+				(c/16)/16.0f,
+				(c%16)/16.0f+1.0f/16.0f,
+				(c/16)/16.0f+1.0f/16.0f);
+			
+			CQuadItem QuadItem(x, y, Size, Size);
+			QuadsDrawTL(&QuadItem, 1);
+			x += Size/2;
+		}
+	}
+	
+	QuadsEnd();
+}
+
+bool CGraphics_OpenGL::Init()
+{
+	m_pStorage = Kernel()->RequestInterface<IStorage>();
+	
+	// Set all z to -5.0f
+	for(int i = 0; i < MAX_VERTICES; i++)
+		m_aVertices[i].m_Pos.z = -5.0f;
+
+	// init textures
+	m_FirstFreeTexture = 0;
+	for(int i = 0; i < MAX_TEXTURES; i++)
+		m_aTextures[i].m_Next = i+1;
+	m_aTextures[MAX_TEXTURES-1].m_Next = -1;
+
+	// set some default settings
+	glEnable(GL_BLEND);
+	glDisable(GL_CULL_FACE);
+	glDisable(GL_DEPTH_TEST);
+	glMatrixMode(GL_MODELVIEW);
+	glLoadIdentity();
+	
+	glAlphaFunc(GL_GREATER, 0);
+	glEnable(GL_ALPHA_TEST);
+	glDepthMask(0);
+
+	// create null texture, will get id=0
+	static const unsigned char aNullTextureData[] = {
+		0xff,0x00,0x00,0xff, 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0xff,0x00,0xff, 
+		0xff,0x00,0x00,0xff, 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0xff,0x00,0xff, 
+		0x00,0x00,0xff,0xff, 0x00,0x00,0xff,0xff, 0xff,0xff,0x00,0xff, 0xff,0xff,0x00,0xff, 
+		0x00,0x00,0xff,0xff, 0x00,0x00,0xff,0xff, 0xff,0xff,0x00,0xff, 0xff,0xff,0x00,0xff, 
+	};
+	
+	m_InvalidTexture = LoadTextureRaw(4,4,CImageInfo::FORMAT_RGBA,aNullTextureData,CImageInfo::FORMAT_RGBA,TEXLOAD_NORESAMPLE);
+	dbg_msg("", "invalid texture id: %d %d", m_InvalidTexture, m_aTextures[m_InvalidTexture].m_Tex);
+	
+	return true;
+}
+
+int CGraphics_SDL::TryInit()
+{
+	const SDL_VideoInfo *pInfo;
+	int Flags = SDL_OPENGL;
+	
+	m_ScreenWidth = g_Config.m_GfxScreenWidth;
+	m_ScreenHeight = g_Config.m_GfxScreenHeight;
+
+	pInfo = SDL_GetVideoInfo();
+	SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
+
+	// set flags
+	Flags  = SDL_OPENGL;
+	Flags |= SDL_GL_DOUBLEBUFFER;
+	Flags |= SDL_HWPALETTE;
+	if(g_Config.m_DbgResizable)
+		Flags |= SDL_RESIZABLE;
+
+	if(pInfo->hw_available) // ignore_convention
+		Flags |= SDL_HWSURFACE;
+	else
+		Flags |= SDL_SWSURFACE;
+
+	if(pInfo->blit_hw) // ignore_convention
+		Flags |= SDL_HWACCEL;
+
+	if(g_Config.m_GfxFullscreen)
+		Flags |= SDL_FULLSCREEN;
+
+	// set gl attributes
+	if(g_Config.m_GfxFsaaSamples)
+	{
+		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
+		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, g_Config.m_GfxFsaaSamples);
+	}
+	else
+	{
+		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
+		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
+	}
+
+	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+	SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, g_Config.m_GfxVsync);
+
+	// set caption
+	SDL_WM_SetCaption("Teeworlds", "Teeworlds");
+	
+	// create window
+	m_pScreenSurface = SDL_SetVideoMode(m_ScreenWidth, m_ScreenHeight, 0, Flags);
+	if(m_pScreenSurface == NULL)
+	{
+		dbg_msg("gfx", "unable to set video mode: %s", SDL_GetError());
+		return -1;
+	}
+	
+	return 0;
+}
+
+
+int CGraphics_SDL::InitWindow()
+{
+	if(TryInit() == 0)
+		return 0;
+	
+	// try disabling fsaa
+	while(g_Config.m_GfxFsaaSamples)
+	{
+		g_Config.m_GfxFsaaSamples--;
+		
+		if(g_Config.m_GfxFsaaSamples)
+			dbg_msg("gfx", "lowering FSAA to %d and trying again", g_Config.m_GfxFsaaSamples);
+		else
+			dbg_msg("gfx", "disabling FSAA and trying again");
+
+		if(TryInit() == 0)
+			return 0;
+	}
+
+	// try lowering the resolution
+	if(g_Config.m_GfxScreenWidth != 640 || g_Config.m_GfxScreenHeight != 480)
+	{
+		dbg_msg("gfx", "setting resolution to 640x480 and trying again");
+		g_Config.m_GfxScreenWidth = 640;
+		g_Config.m_GfxScreenHeight = 480;
+
+		if(TryInit() == 0)
+			return 0;
+	}
+
+	dbg_msg("gfx", "out of ideas. failed to init graphics");
+					
+	return -1;		
+}
+
+
+CGraphics_SDL::CGraphics_SDL()
+{
+	m_pScreenSurface = 0;
+}
+
+bool CGraphics_SDL::Init()
+{
+	{
+		int Systems = SDL_INIT_VIDEO;
+		
+		if(g_Config.m_SndEnable)
+			Systems |= SDL_INIT_AUDIO;
+
+		if(g_Config.m_ClEventthread)
+			Systems |= SDL_INIT_EVENTTHREAD;
+		
+		if(SDL_Init(Systems) < 0)
+		{
+			dbg_msg("gfx", "unable to init SDL: %s", SDL_GetError());
+			return true;
+		}
+	}
+	
+	atexit(SDL_Quit); // ignore_convention
+
+	#ifdef CONF_FAMILY_WINDOWS
+		if(!getenv("SDL_VIDEO_WINDOW_POS") && !getenv("SDL_VIDEO_CENTERED")) // ignore_convention
+			putenv("SDL_VIDEO_WINDOW_POS=8,27"); // ignore_convention
+	#endif
+	
+	if(InitWindow() != 0)
+		return true;
+
+	SDL_ShowCursor(0);
+		
+	CGraphics_OpenGL::Init();
+	
+	MapScreen(0,0,g_Config.m_GfxScreenWidth, g_Config.m_GfxScreenHeight);
+	return false;
+}
+
+void CGraphics_SDL::Shutdown()
+{
+	// TODO: SDL, is this correct?
+	SDL_Quit();
+}
+
+void CGraphics_SDL::Minimize()
+{
+	SDL_WM_IconifyWindow();
+}
+
+void CGraphics_SDL::Maximize()
+{
+	// TODO: SDL
+}
+
+int CGraphics_SDL::WindowActive()
+{
+	return SDL_GetAppState()&SDL_APPINPUTFOCUS;
+}
+
+int CGraphics_SDL::WindowOpen()
+{
+	return SDL_GetAppState()&SDL_APPACTIVE;
+
+}
+
+void CGraphics_SDL::TakeScreenshot()
+{
+	m_DoScreenshot = true;
+}
+
+void CGraphics_SDL::Swap()
+{
+	if(m_DoScreenshot)
+	{
+		// find filename
+		char aFilename[128];
+		static int Index = 1;
+
+		for(; Index < 10000; Index++)
+		{
+			IOHANDLE io;
+			str_format(aFilename, sizeof(aFilename), "screenshots/screenshot%05d.png", Index);
+			io = m_pStorage->OpenFile(aFilename, IOFLAG_READ);
+			if(io)
+				io_close(io);
+			else
+				break;
+		}
+
+		ScreenshotDirect(aFilename);
+		m_DoScreenshot = false;
+	}
+	
+	SDL_GL_SwapBuffers();
+	
+	if(g_Config.m_GfxFinish)
+		glFinish();		
+}
+
+
+int CGraphics_SDL::GetVideoModes(CVideoMode *pModes, int MaxModes)
+{
+	int NumModes = sizeof(g_aFakeModes)/sizeof(CVideoMode);
+	SDL_Rect **ppModes;
+
+	if(g_Config.m_GfxDisplayAllModes)
+	{
+		int Count = sizeof(g_aFakeModes)/sizeof(CVideoMode);
+		mem_copy(pModes, g_aFakeModes, sizeof(g_aFakeModes));
+		if(MaxModes < Count)
+			Count = MaxModes;
+		return Count;
+	}
+	
+	// TODO: fix this code on osx or windows
+		
+	ppModes = SDL_ListModes(NULL, SDL_OPENGL|SDL_GL_DOUBLEBUFFER|SDL_FULLSCREEN);
+	if(ppModes == NULL)
+	{
+		// no modes
+		NumModes = 0;
+	}
+	else if(ppModes == (SDL_Rect**)-1)
+	{
+		// all modes
+	}
+	else
+	{
+		NumModes = 0;
+		for(int i = 0; ppModes[i]; ++i)
+		{
+			if(NumModes == MaxModes)
+				break;
+			pModes[NumModes].m_Width = ppModes[i]->w;
+			pModes[NumModes].m_Height = ppModes[i]->h;
+			pModes[NumModes].m_Red = 8;
+			pModes[NumModes].m_Green = 8;
+			pModes[NumModes].m_Blue = 8;
+			NumModes++;
+		}
+	}
+	
+	return NumModes;
+}
+
+extern IEngineGraphics *CreateEngineGraphics() { return new CGraphics_SDL(); }
diff --git a/src/engine/client/graphics.h b/src/engine/client/graphics.h
index 80dbf1b9..ff4c3562 100644
--- a/src/engine/client/graphics.h
+++ b/src/engine/client/graphics.h
@@ -1,69 +1,143 @@
-#include "../e_if_gfx.h"
+#ifndef ENGINE_CLIENT_GRAPHICS_H
+#define ENGINE_CLIENT_GRAPHICS_H
 
-class IGraphics
+class CGraphics_OpenGL : public IEngineGraphics
 {
 protected:
-	int m_ScreenWidth;
-	int m_ScreenHeight;
-public:
-	virtual ~IGraphics() {}
-	
-	int ScreenWidth() const { return m_ScreenWidth; }
-	int ScreenHeight() const { return m_ScreenHeight; }
-	float ScreenAspect() const { return (float)ScreenWidth()/(float)ScreenHeight(); }
-	
-	virtual void Clear(float r, float g, float b) = 0;
-	
-	virtual void ClipEnable(int x, int y, int w, int h) = 0;
-	virtual void ClipDisable() = 0;
-	
-	virtual void MapScreen(float tl_x, float tl_y, float br_x, float br_y) = 0;
-	virtual void GetScreen(float *tl_x, float *tl_y, float *br_x, float *br_y) = 0;
+	class IStorage *m_pStorage;
 	
-	virtual void BlendNone() = 0;
-	virtual void BlendNormal() = 0;
-	virtual void BlendAdditive() = 0;
-	
-	virtual int LoadPNG(IMAGE_INFO *pImg, const char *pFilename) =0;
-	virtual int UnloadTexture(int Index) = 0;
-	virtual int LoadTextureRaw(int Width, int Height, int Format, const void *pData, int StoreFormat, int Flags) = 0;
-	virtual int LoadTexture(const char *pFilename, int StoreFormat, int Flags) = 0;
-	virtual void TextureSet(int TextureID) = 0;
+	//
+	typedef struct { float x, y, z; } CPoint;
+	typedef struct { float u, v; } CTexCoord;
+	typedef struct { float r, g, b, a; } CColor;
+
+	typedef struct
+	{
+		CPoint m_Pos;
+		CTexCoord m_Tex;
+		CColor m_Color;
+	} CVertex;
 	
-	virtual void LinesBegin() = 0;
-	virtual void LinesEnd() = 0;
-	virtual void LinesDraw(float x0, float y0, float x1, float y1) = 0;
+	enum
+	{
+		MAX_VERTICES = 32*1024,
+		MAX_TEXTURES = 1024*4,
+		
+		DRAWING_QUADS=1,
+		DRAWING_LINES=2		
+	};
+
+	CVertex m_aVertices[MAX_VERTICES];
+	int m_NumVertices;
+
+	CColor m_aColor[4];
+	CTexCoord m_aTexture[4];
+
+	bool m_RenderEnable;
+
+	float m_Rotation;
+	int m_Drawing;
+	bool m_DoScreenshot;
+
+	float m_ScreenX0;
+	float m_ScreenY0;
+	float m_ScreenX1;
+	float m_ScreenY1;
+
+	int m_InvalidTexture;
+
+	struct CTexture
+	{
+		GLuint m_Tex;
+		int m_MemSize;
+		int m_Flags;
+		int m_Next;
+	};
+
+	CTexture m_aTextures[MAX_TEXTURES];
+	int m_FirstFreeTexture;
+	int m_TextureMemoryUsage;
+
+	void Flush();
+	void AddVertices(int Count);
+	void Rotate4(CPoint *pCenter, CVertex *pPoints);
 	
-	virtual void QuadsBegin() = 0;
-	virtual void QuadsEnd() = 0;
-	virtual void QuadsSetRotation(float Angle) = 0;
-	virtual void QuadsSetSubset(float tl_u, float tl_v, float br_u, float br_v) = 0;
-	virtual void QuadsSetSubsetFree(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) = 0;
+	static unsigned char Sample(int w, int h, const unsigned char *pData, int u, int v, int Offset);
+public:
+	CGraphics_OpenGL();
 	
-	virtual void QuadsDraw(float x, float y, float w, float h) = 0;
-	virtual void QuadsDrawTL(float x, float y, float w, float h) = 0;
-	virtual void QuadsDrawFreeform(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) = 0;
-	virtual void QuadsText(float x, float y, float Size, float r, float g, float b, float a, const char *pText) = 0;
+	virtual void ClipEnable(int x, int y, int w, int h);
+	virtual void ClipDisable();
+		
+	virtual void BlendNone();
+	virtual void BlendNormal();
+	virtual void BlendAdditive();
+
+	virtual int MemoryUsage() const;
+		
+	virtual void MapScreen(float TopLeftX, float TopLeftY, float BottomRightX, float BottomRightY);
+	virtual void GetScreen(float *pTopLeftX, float *pTopLeftY, float *pBottomRightX, float *pBottomRightY);
+
+	virtual void LinesBegin();
+	virtual void LinesEnd();
+	virtual void LinesDraw(const CLineItem *pArray, int Num);
 	
-	virtual void SetColorVertex(int i, float r, float g, float b, float a) = 0;
-	virtual void SetColor(float r, float g, float b, float a) = 0;
+	virtual int UnloadTexture(int Index);
+	virtual int LoadTextureRaw(int Width, int Height, int Format, const void *pData, int StoreFormat, int Flags);
+
+	// simple uncompressed RGBA loaders
+	virtual int LoadTexture(const char *pFilename, int StoreFormat, int Flags);
+	virtual int LoadPNG(CImageInfo *pImg, const char *pFilename);
+
+	void ScreenshotDirect(const char *pFilename);
+
+	virtual void TextureSet(int TextureID);
+
+	virtual void Clear(float r, float g, float b);
+
+	virtual void QuadsBegin();
+	virtual void QuadsEnd();
+	virtual void QuadsSetRotation(float Angle);
+
+	virtual void SetColorVertex(const CColorVertex *pArray, int Num);
+	virtual void SetColor(float r, float g, float b, float a);
+
+	virtual void QuadsSetSubset(float TlU, float TlV, float BrU, float BrV);
+	virtual void QuadsSetSubsetFree(
+		float x0, float y0, float x1, float y1,
+		float x2, float y2, float x3, float y3);
+
+	virtual void QuadsDraw(CQuadItem *pArray, int Num);
+	virtual void QuadsDrawTL(const CQuadItem *pArray, int Num);
+	virtual void QuadsDrawFreeform(const CFreeformItem *pArray, int Num);
+	virtual void QuadsText(float x, float y, float Size, float r, float g, float b, float a, const char *pText);
 	
-	virtual void TakeScreenshot() = 0;
+	virtual bool Init();
 };
 
-class IEngineGraphics : public IGraphics
+class CGraphics_SDL : public CGraphics_OpenGL
 {
-public:
-	virtual bool Init() = 0;
-	virtual void Shutdown() = 0;
-	virtual void Swap() = 0;
-	
-	virtual void Minimize() = 0;
-	virtual void Maximize() = 0;
+	SDL_Surface *m_pScreenSurface;	
 	
-	virtual int WindowActive() = 0;
-	virtual int WindowOpen() = 0;
+	int TryInit();
+	int InitWindow();
+public:
+	CGraphics_SDL();
+
+	virtual bool Init();
+	virtual void Shutdown();
+
+	virtual void Minimize();
+	virtual void Maximize();
+
+	virtual int WindowActive();
+	virtual int WindowOpen();
+
+	virtual void TakeScreenshot();
+	virtual void Swap();
+
+	virtual int GetVideoModes(CVideoMode *pModes, int MaxModes);
 	
 };
 
-extern IEngineGraphics *CreateEngineGraphics();
+#endif
diff --git a/src/engine/client/input.cpp b/src/engine/client/input.cpp
new file mode 100644
index 00000000..9f546226
--- /dev/null
+++ b/src/engine/client/input.cpp
@@ -0,0 +1,208 @@
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+#include "SDL.h"
+
+#include <base/system.h>
+#include <engine/shared/config.h>
+#include <engine/graphics.h>
+#include <engine/input.h>
+#include <engine/keys.h>
+
+#include "input.h"
+
+//print >>f, "int inp_key_code(const char *key_name) { int i; if (!strcmp(key_name, \"-?-\")) return -1; else for (i = 0; i < 512; i++) if (!strcmp(key_strings[i], key_name)) return i; return -1; }"
+
+// this header is protected so you don't include it from anywere
+#define KEYS_INCLUDE
+#include "keynames.h"
+#undef KEYS_INCLUDE
+
+void CInput::AddEvent(int Unicode, int Key, int Flags)
+{
+	if(m_NumEvents != INPUT_BUFFER_SIZE)
+	{
+		m_aInputEvents[m_NumEvents].m_Unicode = Unicode;
+		m_aInputEvents[m_NumEvents].m_Key = Key;
+		m_aInputEvents[m_NumEvents].m_Flags = Flags;
+		m_NumEvents++;
+	}
+}
+
+CInput::CInput()
+{
+	mem_zero(m_aInputCount, sizeof(m_aInputCount));
+	mem_zero(m_aInputState, sizeof(m_aInputState));
+	mem_zero(m_Keys, sizeof(m_Keys));
+
+	m_InputCurrent = 0;
+	m_InputGrabbed = 0;
+
+	m_LastRelease = 0;
+	m_ReleaseDelta = -1;
+
+	m_NumEvents = 0;
+}
+
+void CInput::Init()
+{
+	m_pGraphics = Kernel()->RequestInterface<IEngineGraphics>();
+	SDL_EnableUNICODE(1);
+	SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
+}
+
+void CInput::MouseRelative(int *x, int *y)
+{
+	int nx = 0, ny = 0;
+	float Sens = g_Config.m_InpMousesens/100.0f;
+
+	if(g_Config.m_InpGrab)
+		SDL_GetRelativeMouseState(&nx, &ny);
+	else
+	{
+		if(m_InputGrabbed)
+		{
+			SDL_GetMouseState(&nx,&ny);
+			SDL_WarpMouse(Graphics()->ScreenWidth()/2,Graphics()->ScreenHeight()/2);
+			nx -= Graphics()->ScreenWidth()/2; ny -= Graphics()->ScreenHeight()/2;
+		}
+	}
+
+	*x = nx*Sens;
+	*y = ny*Sens;
+}
+
+void CInput::MouseModeAbsolute()
+{
+	SDL_ShowCursor(1);
+	m_InputGrabbed = 0;
+	if(g_Config.m_InpGrab)
+		SDL_WM_GrabInput(SDL_GRAB_OFF);
+}
+
+void CInput::MouseModeRelative()
+{
+	SDL_ShowCursor(0);
+	m_InputGrabbed = 1;
+	if(g_Config.m_InpGrab)
+		SDL_WM_GrabInput(SDL_GRAB_ON);
+}
+
+int CInput::MouseDoubleClick()
+{
+	return m_ReleaseDelta < (time_freq() >> 2);
+}
+
+void CInput::ClearKeyStates()
+{
+	mem_zero(m_aInputState, sizeof(m_aInputState));
+	mem_zero(m_aInputCount, sizeof(m_aInputCount));
+}
+
+int CInput::KeyState(int Key)
+{
+	return m_aInputState[m_InputCurrent][Key];
+}
+
+void CInput::Update()
+{
+	if(m_InputGrabbed && !Graphics()->WindowActive())
+		MouseModeAbsolute();
+
+	/*if(!input_grabbed && Graphics()->WindowActive())
+		Input()->MouseModeRelative();*/
+
+	// clear and begin count on the other one
+	m_InputCurrent^=1;
+	mem_zero(&m_aInputCount[m_InputCurrent], sizeof(m_aInputCount[m_InputCurrent]));
+	mem_zero(&m_aInputState[m_InputCurrent], sizeof(m_aInputState[m_InputCurrent]));
+
+	{
+		int i;
+		Uint8 *pState = SDL_GetKeyState(&i);
+		if(i >= KEY_LAST)
+			i = KEY_LAST-1;
+		mem_copy(m_aInputState[m_InputCurrent], pState, i);
+	}
+
+	// these states must always be updated manually because they are not in the GetKeyState from SDL
+	int i = SDL_GetMouseState(NULL, NULL);
+	if(i&SDL_BUTTON(1)) m_aInputState[m_InputCurrent][KEY_MOUSE_1] = 1; // 1 is left
+	if(i&SDL_BUTTON(3)) m_aInputState[m_InputCurrent][KEY_MOUSE_2] = 1; // 3 is right
+	if(i&SDL_BUTTON(2)) m_aInputState[m_InputCurrent][KEY_MOUSE_3] = 1; // 2 is middle
+	if(i&SDL_BUTTON(4)) m_aInputState[m_InputCurrent][KEY_MOUSE_4] = 1;
+	if(i&SDL_BUTTON(5)) m_aInputState[m_InputCurrent][KEY_MOUSE_5] = 1;
+	if(i&SDL_BUTTON(6)) m_aInputState[m_InputCurrent][KEY_MOUSE_6] = 1;
+	if(i&SDL_BUTTON(7)) m_aInputState[m_InputCurrent][KEY_MOUSE_7] = 1;
+	if(i&SDL_BUTTON(8)) m_aInputState[m_InputCurrent][KEY_MOUSE_8] = 1;
+
+	{
+		SDL_Event Event;
+
+		while(SDL_PollEvent(&Event))
+		{
+			int Key = -1;
+			int Action = IInput::FLAG_PRESS;
+			switch (Event.type)
+			{
+				// handle keys
+				case SDL_KEYDOWN:
+					AddEvent(Event.key.keysym.unicode, 0, 0); // ignore_convention
+                    if(Event.key.keysym.unicode != 0 && Event.key.keysym.unicode < 256) // ignore_convention
+                    {
+                        Key = Event.key.keysym.unicode;  // ignore_convention
+                        m_Keys[Event.key.keysym.sym] = Event.key.keysym.unicode; // ignore_convention
+                    }
+                    else
+                        Key = Event.key.keysym.sym;  // ignore_convention
+					break;
+				case SDL_KEYUP:
+					Action = IInput::FLAG_RELEASE;
+					if(m_Keys[Event.key.keysym.sym] != 0) // ignore_convention
+                        Key = m_Keys[Event.key.keysym.sym]; // ignore_convention
+                    else
+                        Key = Event.key.keysym.sym; // ignore_convention
+					break;
+
+				// handle mouse buttons
+				case SDL_MOUSEBUTTONUP:
+					Action = IInput::FLAG_RELEASE;
+
+					if(Event.button.button == 1) // ignore_convention
+					{
+						m_ReleaseDelta = time_get() - m_LastRelease;
+						m_LastRelease = time_get();
+					}
+
+					// fall through
+				case SDL_MOUSEBUTTONDOWN:
+					if(Event.button.button == SDL_BUTTON_LEFT) Key = KEY_MOUSE_1; // ignore_convention
+					if(Event.button.button == SDL_BUTTON_RIGHT) Key = KEY_MOUSE_2; // ignore_convention
+					if(Event.button.button == SDL_BUTTON_MIDDLE) Key = KEY_MOUSE_3; // ignore_convention
+					if(Event.button.button == SDL_BUTTON_WHEELUP) Key = KEY_MOUSE_WHEEL_UP; // ignore_convention
+					if(Event.button.button == SDL_BUTTON_WHEELDOWN) Key = KEY_MOUSE_WHEEL_DOWN; // ignore_convention
+					if(Event.button.button == 6) Key = KEY_MOUSE_6; // ignore_convention
+					if(Event.button.button == 7) Key = KEY_MOUSE_7; // ignore_convention
+					if(Event.button.button == 8) Key = KEY_MOUSE_8; // ignore_convention
+					break;
+
+				// other messages
+				case SDL_QUIT:
+					// TODO: cleaner exit
+					exit(0); // ignore_convention
+					break;
+			}
+
+			//
+			if(Key != -1)
+			{
+				m_aInputCount[m_InputCurrent][Key].m_Presses++;
+				if(Action == IInput::FLAG_PRESS)
+					m_aInputState[m_InputCurrent][Key] = 1;
+				AddEvent(0, Key, Action);
+			}
+
+		}
+	}
+}
+
+
+IEngineInput *CreateEngineInput() { return new CInput; }
diff --git a/src/engine/client/input.h b/src/engine/client/input.h
new file mode 100644
index 00000000..bf7739ab
--- /dev/null
+++ b/src/engine/client/input.h
@@ -0,0 +1,37 @@
+#ifndef ENGINE_CLIENT_INPUT_H
+#define ENGINE_CLIENT_INPUT_H
+
+class CInput : public IEngineInput
+{
+	IEngineGraphics *m_pGraphics;
+
+	int m_InputGrabbed;
+
+	unsigned int m_LastRelease;
+	unsigned int m_ReleaseDelta;
+
+	int m_Keys[1024];
+
+	void AddEvent(int Unicode, int Key, int Flags);
+
+	IEngineGraphics *Graphics() { return m_pGraphics; }
+
+public:
+	CInput();
+
+	virtual void Init();
+
+	virtual void MouseRelative(int *x, int *y);
+	virtual void MouseModeAbsolute();
+	virtual void MouseModeRelative();
+	virtual int MouseDoubleClick();
+
+	void ClearKeyStates();
+	int KeyState(int Key);
+
+	int ButtonPressed(int Button) { return m_aInputState[m_InputCurrent][Button]; }
+
+	virtual void Update();
+};
+
+#endif
diff --git a/src/engine/e_keynames.cpp b/src/engine/client/keynames.h
index c81744b9..2f159a5a 100644
--- a/src/engine/e_keynames.cpp
+++ b/src/engine/client/keynames.h
@@ -1,10 +1,13 @@
 /* AUTO GENERATED! DO NOT EDIT MANUALLY! */
 
+#ifndef KEYS_INCLUDE
+#error do not include this header!
+#endif
+
 #include <string.h>
 
-static const char key_strings[512][16] =
+const char g_aaKeyStrings[512][16] =
 {
-
 	"first",
 	"&1",
 	"&2",
@@ -519,6 +522,3 @@ static const char key_strings[512][16] =
 	"&511",
 };
 
-const char *inp_key_name(int k) { if (k >= 0 && k < 512) return key_strings[k]; else return key_strings[0]; }
-int inp_key_code(const char *key_name) { int i; if (!strcmp(key_name, "-?-")) return -1; else for (i = 0; i < 512; i++) if (!strcmp(key_strings[i], key_name)) return i; return -1; }
-
diff --git a/src/engine/client/sound.cpp b/src/engine/client/sound.cpp
new file mode 100644
index 00000000..df8fa66b
--- /dev/null
+++ b/src/engine/client/sound.cpp
@@ -0,0 +1,485 @@
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+#include <base/system.h>
+#include <engine/shared/config.h>
+
+#include "SDL.h"
+
+#include "sound.h"
+
+extern "C" { // wavpack
+	#include <engine/external/wavpack/wavpack.h>
+}
+#include <math.h>
+
+enum
+{
+	NUM_SAMPLES = 512,
+	NUM_VOICES = 64,
+	NUM_CHANNELS = 16,
+	
+	MAX_FRAMES = 1024
+};
+
+struct CSample
+{
+	short *m_pData;
+	int m_NumFrames;
+	int m_Rate;
+	int m_Channels;
+	int m_LoopStart;
+	int m_LoopEnd;
+};
+
+struct CChannel
+{
+	int m_Vol;
+	int m_Pan;
+} ;
+
+struct CVoice
+{
+	CSample *m_pSample;
+	CChannel *m_pChannel;
+	int m_Tick;
+	int m_Vol; // 0 - 255
+	int m_Flags;
+	int m_X, m_Y;
+} ;
+
+static CSample m_aSamples[NUM_SAMPLES] = { {0} };
+static CVoice m_aVoices[NUM_VOICES] = { {0} };
+static CChannel m_aChannels[NUM_CHANNELS] = { {255, 0} };
+
+static LOCK m_SoundLock = 0;
+static int m_SoundEnabled = 0;
+
+static int m_CenterX = 0;
+static int m_CenterY = 0;
+
+static int m_MixingRate = 48000;
+static volatile int m_SoundVolume = 100;
+
+static int m_NextVoice = 0;
+
+
+// TODO: there should be a faster way todo this
+static short Int2Short(int i)
+{
+	if(i > 0x7fff)
+		return 0x7fff;
+	else if(i < -0x7fff)
+		return -0x7fff;
+	return i;
+}
+
+static int IntAbs(int i)
+{
+	if(i<0)
+		return -i;
+	return i;
+}
+
+static void Mix(short *pFinalOut, unsigned Frames)
+{
+	int aMixBuffer[MAX_FRAMES*2] = {0};
+	int MasterVol;
+
+	// aquire lock while we are mixing
+	lock_wait(m_SoundLock);
+	
+	MasterVol = m_SoundVolume;
+	
+	for(unsigned i = 0; i < NUM_VOICES; i++)
+	{
+		if(m_aVoices[i].m_pSample)
+		{
+			// mix voice
+			CVoice *v = &m_aVoices[i];
+			int *pOut = aMixBuffer;
+
+			int Step = v->m_pSample->m_Channels; // setup input sources
+			short *pInL = &v->m_pSample->m_pData[v->m_Tick*Step];
+			short *pInR = &v->m_pSample->m_pData[v->m_Tick*Step+1];
+			
+			unsigned End = v->m_pSample->m_NumFrames-v->m_Tick;
+
+			int Rvol = v->m_pChannel->m_Vol;
+			int Lvol = v->m_pChannel->m_Vol;
+
+			// make sure that we don't go outside the sound data
+			if(Frames < End)
+				End = Frames;
+			
+			// check if we have a mono sound
+			if(v->m_pSample->m_Channels == 1)
+				pInR = pInL;
+
+			// volume calculation
+			if(v->m_Flags&ISound::FLAG_POS && v->m_pChannel->m_Pan)
+			{
+				// TODO: we should respect the channel panning value
+				const int Range = 1500; // magic value, remove
+				int dx = v->m_X - m_CenterX;
+				int dy = v->m_Y - m_CenterY;
+				int Dist = sqrtf((float)dx*dx+dy*dy); // float here. nasty
+				int p = IntAbs(dx);
+				if(Dist < Range)
+				{
+					// panning
+					if(dx > 0)
+						Lvol = ((Range-p)*Lvol)/Range;
+					else
+						Rvol = ((Range-p)*Rvol)/Range;
+					
+					// falloff
+					Lvol = (Lvol*(Range-Dist))/Range;
+					Rvol = (Rvol*(Range-Dist))/Range;
+				}
+				else
+				{
+					Lvol = 0;
+					Rvol = 0;
+				}
+			}
+
+			// process all frames
+			for(unsigned s = 0; s < End; s++)
+			{
+				*pOut++ += (*pInL)*Lvol;
+				*pOut++ += (*pInR)*Rvol;
+				pInL += Step;
+				pInR += Step;
+				v->m_Tick++;
+			}
+			
+			// free voice if not used any more
+			if(v->m_Tick == v->m_pSample->m_NumFrames)
+				v->m_pSample = 0;
+			
+		}
+	}
+	
+	
+	// release the lock
+	lock_release(m_SoundLock);
+
+	{
+		// clamp accumulated values
+		// TODO: this seams slow
+		for(unsigned i = 0; i < Frames; i++)
+		{
+			int j = i<<1;
+			int vl = ((aMixBuffer[j]*MasterVol)/101)>>8;
+			int vr = ((aMixBuffer[j+1]*MasterVol)/101)>>8;
+
+			pFinalOut[j] = Int2Short(vl);
+			pFinalOut[j+1] = Int2Short(vr);
+		}
+	}
+
+#if defined(CONF_ARCH_ENDIAN_BIG)
+	swap_endian(pFinalOut, sizeof(short), Frames * 2);
+#endif
+}
+
+static void SdlCallback(void *pUnused, Uint8 *pStream, int Len)
+{
+	(void)pUnused;
+	Mix((short *)pStream, Len/2/2);
+}
+
+
+int CSound::Init()
+{
+	m_pGraphics = Kernel()->RequestInterface<IEngineGraphics>();
+	m_pStorage = Kernel()->RequestInterface<IStorage>();
+	
+	SDL_AudioSpec Format;
+	
+	m_SoundLock = lock_create();
+	
+	if(!g_Config.m_SndEnable)
+		return 0;
+	
+	m_MixingRate = g_Config.m_SndRate;
+
+	// Set 16-bit stereo audio at 22Khz
+	Format.freq = g_Config.m_SndRate; // ignore_convention
+	Format.format = AUDIO_S16; // ignore_convention
+	Format.channels = 2; // ignore_convention
+	Format.samples = g_Config.m_SndBufferSize; // ignore_convention
+	Format.callback = SdlCallback; // ignore_convention
+	Format.userdata = NULL; // ignore_convention
+
+	// Open the audio device and start playing sound!
+	if(SDL_OpenAudio(&Format, NULL) < 0)
+	{
+		dbg_msg("client/sound", "unable to open audio: %s", SDL_GetError());
+		return -1;
+	}
+	else
+		dbg_msg("client/sound", "sound init successful");
+
+	SDL_PauseAudio(0);
+	
+	m_SoundEnabled = 1;
+	Update(); // update the volume
+	return 0;
+}
+
+int CSound::Update()
+{
+	// update volume
+	int WantedVolume = g_Config.m_SndVolume;
+	
+	if(!m_pGraphics->WindowActive() && g_Config.m_SndNonactiveMute)
+		WantedVolume = 0;
+	
+	if(WantedVolume != m_SoundVolume)
+	{
+		lock_wait(m_SoundLock);
+		m_SoundVolume = WantedVolume;
+		lock_release(m_SoundLock);
+	}
+	
+	return 0;
+}
+
+int CSound::Shutdown()
+{
+	SDL_CloseAudio();
+	lock_destroy(m_SoundLock);
+	return 0;
+}
+
+int CSound::AllocId()
+{
+	// TODO: linear search, get rid of it
+	for(unsigned SampleId = 0; SampleId < NUM_SAMPLES; SampleId++)
+	{
+		if(m_aSamples[SampleId].m_pData == 0x0)
+			return SampleId;
+	}
+
+	return -1;
+}
+
+void CSound::RateConvert(int SampleId)
+{
+	CSample *pSample = &m_aSamples[SampleId];
+	int NumFrames = 0;
+	short *pNewData = 0;
+	
+	// make sure that we need to convert this sound
+	if(!pSample->m_pData || pSample->m_Rate == m_MixingRate)
+		return;
+
+	// allocate new data
+	NumFrames = (int)((pSample->m_NumFrames/(float)pSample->m_Rate)*m_MixingRate);
+	pNewData = (short *)mem_alloc(NumFrames*pSample->m_Channels*sizeof(short), 1);
+	
+	for(int i = 0; i < NumFrames; i++)
+	{
+		// resample TODO: this should be done better, like linear atleast
+		float a = i/(float)NumFrames;
+		int f = (int)(a*pSample->m_NumFrames);
+		if(f >= pSample->m_NumFrames)
+			f = pSample->m_NumFrames-1;
+		
+		// set new data
+		if(pSample->m_Channels == 1)
+			pNewData[i] = pSample->m_pData[f];
+		else if(pSample->m_Channels == 2)
+		{
+			pNewData[i*2] = pSample->m_pData[f*2];
+			pNewData[i*2+1] = pSample->m_pData[f*2+1];
+		}
+	}
+	
+	// free old data and apply new
+	mem_free(pSample->m_pData);
+	pSample->m_pData = pNewData;
+	pSample->m_NumFrames = NumFrames;
+}
+
+int CSound::ReadData(void *pBuffer, int Size)
+{
+	return io_read(ms_File, pBuffer, Size);
+}
+
+int CSound::LoadWV(const char *pFilename)
+{
+	CSample *pSample;
+	int SampleId = -1;
+	char aError[100];
+	WavpackContext *pContext;
+	
+	// don't waste memory on sound when we are stress testing
+	if(g_Config.m_DbgStress)
+		return -1;
+		
+	// no need to load sound when we are running with no sound
+	if(!m_SoundEnabled)
+		return 1;
+		
+	if(!m_pStorage)
+		return -1;
+
+	ms_File = m_pStorage->OpenFile(pFilename, IOFLAG_READ); // TODO: use system.h stuff for this
+	if(!ms_File)
+	{
+		dbg_msg("sound/wv", "failed to open %s", pFilename);
+		return -1;
+	}
+
+	SampleId = AllocId();
+	if(SampleId < 0)
+		return -1;
+	pSample = &m_aSamples[SampleId];
+
+	pContext = WavpackOpenFileInput(ReadData, aError);
+	if (pContext)
+	{
+		int m_aSamples = WavpackGetNumSamples(pContext);
+		int BitsPerSample = WavpackGetBitsPerSample(pContext);
+		unsigned int SampleRate = WavpackGetSampleRate(pContext);
+		int m_aChannels = WavpackGetNumChannels(pContext);
+		int *pData;
+		int *pSrc;
+		short *pDst;
+		int i;
+
+		pSample->m_Channels = m_aChannels;
+		pSample->m_Rate = SampleRate;
+
+		if(pSample->m_Channels > 2)
+		{
+			dbg_msg("sound/wv", "file is not mono or stereo. filename='%s'", pFilename);
+			return -1;
+		}
+
+		/*
+		if(snd->rate != 44100)
+		{
+			dbg_msg("sound/wv", "file is %d Hz, not 44100 Hz. filename='%s'", snd->rate, filename);
+			return -1;
+		}*/
+		
+		if(BitsPerSample != 16)
+		{
+			dbg_msg("sound/wv", "bps is %d, not 16, filname='%s'", BitsPerSample, pFilename);
+			return -1;
+		}
+
+		pData = (int *)mem_alloc(4*m_aSamples*m_aChannels, 1);
+		WavpackUnpackSamples(pContext, pData, m_aSamples); // TODO: check return value
+		pSrc = pData;
+		
+		pSample->m_pData = (short *)mem_alloc(2*m_aSamples*m_aChannels, 1);
+		pDst = pSample->m_pData;
+
+		for (i = 0; i < m_aSamples*m_aChannels; i++)
+			*pDst++ = (short)*pSrc++;
+
+		mem_free(pData);
+
+		pSample->m_NumFrames = m_aSamples;
+		pSample->m_LoopStart = -1;
+		pSample->m_LoopEnd = -1;
+	}
+	else
+	{
+		dbg_msg("sound/wv", "failed to open %s: %s", pFilename, aError);
+	}
+
+	io_close(ms_File);
+	ms_File = NULL;
+
+	if(g_Config.m_Debug)
+		dbg_msg("sound/wv", "loaded %s", pFilename);
+
+	RateConvert(SampleId);
+	return SampleId;
+}
+
+void CSound::SetListenerPos(float x, float y)
+{
+	m_CenterX = (int)x;
+	m_CenterY = (int)y;
+}
+	
+
+void CSound::SetChannel(int ChannelId, float Vol, float Pan)
+{
+	m_aChannels[ChannelId].m_Vol = (int)(Vol*255.0f);
+	m_aChannels[ChannelId].m_Pan = (int)(Pan*255.0f); // TODO: this is only on and off right now
+}
+
+int CSound::Play(int ChannelId, int SampleId, int Flags, float x, float y)
+{
+	int VoiceId = -1;
+	int i;
+	
+	lock_wait(m_SoundLock);
+	
+	// search for voice
+	for(i = 0; i < NUM_VOICES; i++)
+	{
+		int id = (m_NextVoice + i) % NUM_VOICES;
+		if(!m_aVoices[id].m_pSample)
+		{
+			VoiceId = id;
+			m_NextVoice = id+1;
+			break;
+		}
+	}
+	
+	// voice found, use it
+	if(VoiceId != -1)
+	{
+		m_aVoices[VoiceId].m_pSample = &m_aSamples[SampleId];
+		m_aVoices[VoiceId].m_pChannel = &m_aChannels[ChannelId];
+		m_aVoices[VoiceId].m_Tick = 0;
+		m_aVoices[VoiceId].m_Vol = 255;
+		m_aVoices[VoiceId].m_Flags = Flags;
+		m_aVoices[VoiceId].m_X = (int)x;
+		m_aVoices[VoiceId].m_Y = (int)y;
+	}
+	
+	lock_release(m_SoundLock);
+	return VoiceId;
+}
+
+int CSound::PlayAt(int ChannelId, int SampleId, int Flags, float x, float y)
+{
+	return Play(ChannelId, SampleId, Flags|ISound::FLAG_POS, x, y);
+}
+
+int CSound::Play(int ChannelId, int SampleId, int Flags)
+{
+	return Play(ChannelId, SampleId, Flags, 0, 0);
+}
+
+void CSound::Stop(int VoiceId)
+{
+	// TODO: a nice fade out
+	lock_wait(m_SoundLock);
+	m_aVoices[VoiceId].m_pSample = 0;
+	lock_release(m_SoundLock);
+}
+
+void CSound::StopAll()
+{
+	// TODO: a nice fade out
+	lock_wait(m_SoundLock);
+	for(int i = 0; i < NUM_VOICES; i++)
+	{
+		m_aVoices[i].m_pSample = 0;
+	}
+	lock_release(m_SoundLock);
+}
+
+IOHANDLE CSound::ms_File = 0;
+
+IEngineSound *CreateEngineSound() { return new CSound; }
+
diff --git a/src/engine/client/sound.h b/src/engine/client/sound.h
new file mode 100644
index 00000000..9c94c6ad
--- /dev/null
+++ b/src/engine/client/sound.h
@@ -0,0 +1,39 @@
+#ifndef ENGINE_CLIENT_SOUND_H
+#define ENGINE_CLIENT_SOUND_H
+
+#include <engine/sound.h>
+#include <engine/storage.h>
+#include <engine/graphics.h>
+#include <engine/shared/engine.h>
+
+class CSound : public IEngineSound
+{
+public:
+	IEngineGraphics *m_pGraphics;
+	IStorage *m_pStorage;
+
+	virtual int Init();
+
+	int Update();
+	int Shutdown();
+	int AllocId();
+
+	static void RateConvert(int SampleId);
+
+	// TODO: Refactor: clean this mess up
+	static IOHANDLE ms_File;
+	static int ReadData(void *pBuffer, int Size);
+
+	virtual int LoadWV(const char *pFilename);
+
+	virtual void SetListenerPos(float x, float y);
+	virtual void SetChannel(int ChannelId, float Vol, float Pan);
+
+	int Play(int ChannelId, int SampleId, int Flags, float x, float y);
+	virtual int PlayAt(int ChannelId, int SampleId, int Flags, float x, float y);
+	virtual int Play(int ChannelId, int SampleId, int Flags);
+	virtual void Stop(int VoiceId);
+	virtual void StopAll();
+};
+
+#endif
diff --git a/src/engine/client/srvbrowse.cpp b/src/engine/client/srvbrowse.cpp
new file mode 100644
index 00000000..e0997467
--- /dev/null
+++ b/src/engine/client/srvbrowse.cpp
@@ -0,0 +1,721 @@
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+#include <algorithm> // sort
+
+#include <base/system.h>
+#include <engine/shared/network.h>
+#include <engine/shared/protocol.h>
+#include <engine/shared/config.h>
+#include <engine/shared/memheap.h>
+#include <engine/shared/engine.h>
+
+#include <engine/masterserver.h>
+#include <engine/config.h>
+
+#include <mastersrv/mastersrv.h>
+
+#include "srvbrowse.h"
+
+class SortWrap
+{
+	typedef bool (CServerBrowser::*SortFunc)(int, int) const;
+	SortFunc m_pfnSort;
+	CServerBrowser *m_pThis;
+public:
+	SortWrap(CServerBrowser *t, SortFunc f) : m_pfnSort(f), m_pThis(t) {}
+	bool operator()(int a, int b) { return (m_pThis->*m_pfnSort)(a, b); }
+};
+
+CServerBrowser::CServerBrowser()
+{
+	m_pMasterServer = 0;
+	m_ppServerlist = 0;
+	m_pSortedServerlist = 0;
+
+	m_NumFavoriteServers = 0;
+
+	mem_zero(m_aServerlistIp, sizeof(m_aServerlistIp));
+
+	m_pFirstReqServer = 0; // request list
+	m_pLastReqServer = 0;
+	m_NumRequests = 0;
+
+	m_NeedRefresh = 0;
+
+	m_NumSortedServers = 0;
+	m_NumSortedServersCapacity = 0;
+	m_NumServers = 0;
+	m_NumServerCapacity = 0;
+
+	m_Sorthash = 0;
+	m_aFilterString[0] = 0;
+	m_aFilterGametypeString[0] = 0;
+
+	// the token is to keep server refresh separated from each other
+	m_CurrentToken = 1;
+
+	m_ServerlistType = 0;
+	m_BroadcastTime = 0;
+}
+
+void CServerBrowser::SetBaseInfo(class CNetClient *pClient, const char *pNetVersion)
+{
+	m_pNetClient = pClient;
+	str_copy(m_aNetVersion, pNetVersion, sizeof(m_aNetVersion));
+	m_pMasterServer = Kernel()->RequestInterface<IMasterServer>();
+	IConfig *pConfig = Kernel()->RequestInterface<IConfig>();
+	if(pConfig)
+		pConfig->RegisterCallback(ConfigSaveCallback, this);
+}
+
+const CServerInfo *CServerBrowser::SortedGet(int Index) const
+{
+	if(Index < 0 || Index >= m_NumSortedServers)
+		return 0;
+	return &m_ppServerlist[m_pSortedServerlist[Index]]->m_Info;
+}
+
+
+bool CServerBrowser::SortCompareName(int Index1, int Index2) const
+{
+	CServerEntry *a = m_ppServerlist[Index1];
+	CServerEntry *b = m_ppServerlist[Index2];
+	return str_comp(a->m_Info.m_aName, b->m_Info.m_aName) < 0;
+}
+
+bool CServerBrowser::SortCompareMap(int Index1, int Index2) const
+{
+	CServerEntry *a = m_ppServerlist[Index1];
+	CServerEntry *b = m_ppServerlist[Index2];
+	return str_comp(a->m_Info.m_aMap, b->m_Info.m_aMap) < 0;
+}
+
+bool CServerBrowser::SortComparePing(int Index1, int Index2) const
+{
+	CServerEntry *a = m_ppServerlist[Index1];
+	CServerEntry *b = m_ppServerlist[Index2];
+	return a->m_Info.m_Latency < b->m_Info.m_Latency;
+}
+
+bool CServerBrowser::SortCompareGametype(int Index1, int Index2) const
+{
+	CServerEntry *a = m_ppServerlist[Index1];
+	CServerEntry *b = m_ppServerlist[Index2];
+	return str_comp(a->m_Info.m_aGameType, b->m_Info.m_aGameType) < 0;
+}
+
+bool CServerBrowser::SortCompareProgression(int Index1, int Index2) const
+{
+	CServerEntry *a = m_ppServerlist[Index1];
+	CServerEntry *b = m_ppServerlist[Index2];
+	return a->m_Info.m_Progression < b->m_Info.m_Progression;
+}
+
+bool CServerBrowser::SortCompareNumPlayers(int Index1, int Index2) const
+{
+	CServerEntry *a = m_ppServerlist[Index1];
+	CServerEntry *b = m_ppServerlist[Index2];
+	return a->m_Info.m_NumPlayers < b->m_Info.m_NumPlayers;
+}
+
+void CServerBrowser::Filter()
+{
+	int i = 0, p = 0;
+	m_NumSortedServers = 0;
+
+	// allocate the sorted list
+	if(m_NumSortedServersCapacity < m_NumServers)
+	{
+		if(m_pSortedServerlist)
+			mem_free(m_pSortedServerlist);
+		m_NumSortedServersCapacity = m_NumServers;
+		m_pSortedServerlist = (int *)mem_alloc(m_NumSortedServersCapacity*sizeof(int), 1);
+	}
+
+	// filter the servers
+	for(i = 0; i < m_NumServers; i++)
+	{
+		int Filtered = 0;
+
+		if(g_Config.m_BrFilterEmpty && m_ppServerlist[i]->m_Info.m_NumPlayers == 0)
+			Filtered = 1;
+		else if(g_Config.m_BrFilterFull && m_ppServerlist[i]->m_Info.m_NumPlayers == m_ppServerlist[i]->m_Info.m_MaxPlayers)
+			Filtered = 1;
+		else if(g_Config.m_BrFilterPw && m_ppServerlist[i]->m_Info.m_Flags&SERVER_FLAG_PASSWORD)
+			Filtered = 1;
+		else if(g_Config.m_BrFilterPure &&
+			(str_comp(m_ppServerlist[i]->m_Info.m_aGameType, "DM") != 0 &&
+			str_comp(m_ppServerlist[i]->m_Info.m_aGameType, "TDM") != 0 &&
+			str_comp(m_ppServerlist[i]->m_Info.m_aGameType, "CTF") != 0))
+		{
+			Filtered = 1;
+		}
+		else if(g_Config.m_BrFilterPureMap &&
+			!(str_comp(m_ppServerlist[i]->m_Info.m_aMap, "dm1") == 0 ||
+			str_comp(m_ppServerlist[i]->m_Info.m_aMap, "dm2") == 0 ||
+			str_comp(m_ppServerlist[i]->m_Info.m_aMap, "dm6") == 0 ||
+			str_comp(m_ppServerlist[i]->m_Info.m_aMap, "dm7") == 0 ||
+			str_comp(m_ppServerlist[i]->m_Info.m_aMap, "dm8") == 0 ||
+			str_comp(m_ppServerlist[i]->m_Info.m_aMap, "dm9") == 0 ||
+			str_comp(m_ppServerlist[i]->m_Info.m_aMap, "ctf1") == 0 ||
+			str_comp(m_ppServerlist[i]->m_Info.m_aMap, "ctf2") == 0 ||
+			str_comp(m_ppServerlist[i]->m_Info.m_aMap, "ctf3") == 0 ||
+			str_comp(m_ppServerlist[i]->m_Info.m_aMap, "ctf4") == 0 ||
+			str_comp(m_ppServerlist[i]->m_Info.m_aMap, "ctf5") == 0)
+		)
+		{
+			Filtered = 1;
+		}
+		else if(g_Config.m_BrFilterPing < m_ppServerlist[i]->m_Info.m_Latency)
+			Filtered = 1;
+		else if(g_Config.m_BrFilterCompatversion && str_comp_num(m_ppServerlist[i]->m_Info.m_aVersion, m_aNetVersion, 3) != 0)
+			Filtered = 1;
+		else
+		{
+			if(g_Config.m_BrFilterString[0] != 0)
+			{
+				int MatchFound = 0;
+
+				m_ppServerlist[i]->m_Info.m_QuickSearchHit = 0;
+
+				// match against server name
+				if(str_find_nocase(m_ppServerlist[i]->m_Info.m_aName, g_Config.m_BrFilterString))
+				{
+					MatchFound = 1;
+					m_ppServerlist[i]->m_Info.m_QuickSearchHit |= IServerBrowser::QUICK_SERVERNAME;
+				}
+
+				// match against players
+				for(p = 0; p < m_ppServerlist[i]->m_Info.m_NumPlayers; p++)
+				{
+					if(str_find_nocase(m_ppServerlist[i]->m_Info.m_aPlayers[p].m_aName, g_Config.m_BrFilterString))
+					{
+						MatchFound = 1;
+						m_ppServerlist[i]->m_Info.m_QuickSearchHit |= IServerBrowser::QUICK_PLAYERNAME;
+						break;
+					}
+				}
+
+				// match against map
+				if(str_find_nocase(m_ppServerlist[i]->m_Info.m_aMap, g_Config.m_BrFilterString))
+				{
+					MatchFound = 1;
+					m_ppServerlist[i]->m_Info.m_QuickSearchHit |= IServerBrowser::QUICK_MAPNAME;
+				}
+
+				if(!MatchFound)
+					Filtered = 1;
+			}
+
+			if(!Filtered && g_Config.m_BrFilterGametype[0] != 0)
+			{
+				// match against game type
+				if(!str_find_nocase(m_ppServerlist[i]->m_Info.m_aGameType, g_Config.m_BrFilterGametype))
+					Filtered = 1;
+			}
+		}
+
+		if(Filtered == 0)
+			m_pSortedServerlist[m_NumSortedServers++] = i;
+	}
+}
+
+int CServerBrowser::SortHash() const
+{
+	int i = g_Config.m_BrSort&0xf;
+	i |= g_Config.m_BrFilterEmpty<<4;
+	i |= g_Config.m_BrFilterFull<<5;
+	i |= g_Config.m_BrFilterPw<<6;
+	i |= g_Config.m_BrSortOrder<<7;
+	i |= g_Config.m_BrFilterCompatversion<<8;
+	i |= g_Config.m_BrFilterPure<<9;
+	i |= g_Config.m_BrFilterPureMap<<10;
+	i |= g_Config.m_BrFilterPing<<16;
+	return i;
+}
+
+void CServerBrowser::Sort()
+{
+	int i;
+
+	// create filtered list
+	Filter();
+
+	// sort
+	if(g_Config.m_BrSort == IServerBrowser::SORT_NAME)
+		std::sort(m_pSortedServerlist, m_pSortedServerlist+m_NumSortedServers, SortWrap(this, &CServerBrowser::SortCompareName));
+	else if(g_Config.m_BrSort == IServerBrowser::SORT_PING)
+		std::sort(m_pSortedServerlist, m_pSortedServerlist+m_NumSortedServers, SortWrap(this, &CServerBrowser::SortComparePing));
+	else if(g_Config.m_BrSort == IServerBrowser::SORT_MAP)
+		std::sort(m_pSortedServerlist, m_pSortedServerlist+m_NumSortedServers, SortWrap(this, &CServerBrowser::SortCompareMap));
+	else if(g_Config.m_BrSort == IServerBrowser::SORT_NUMPLAYERS)
+		std::sort(m_pSortedServerlist, m_pSortedServerlist+m_NumSortedServers, SortWrap(this, &CServerBrowser::SortCompareNumPlayers));
+	else if(g_Config.m_BrSort == IServerBrowser::SORT_GAMETYPE)
+		std::sort(m_pSortedServerlist, m_pSortedServerlist+m_NumSortedServers, SortWrap(this, &CServerBrowser::SortCompareGametype));
+	else if(g_Config.m_BrSort == IServerBrowser::SORT_PROGRESSION)
+		std::sort(m_pSortedServerlist, m_pSortedServerlist+m_NumSortedServers, SortWrap(this, &CServerBrowser::SortCompareProgression));
+
+	// invert the list if requested
+	if(g_Config.m_BrSortOrder)
+	{
+		for(i = 0; i < m_NumSortedServers/2; i++)
+		{
+			int Temp = m_pSortedServerlist[i];
+			m_pSortedServerlist[i] = m_pSortedServerlist[m_NumSortedServers-i-1];
+			m_pSortedServerlist[m_NumSortedServers-i-1] = Temp;
+		}
+	}
+
+	// set indexes
+	for(i = 0; i < m_NumSortedServers; i++)
+		m_ppServerlist[m_pSortedServerlist[i]]->m_Info.m_SortedIndex = i;
+
+	str_copy(m_aFilterGametypeString, g_Config.m_BrFilterGametype, sizeof(m_aFilterGametypeString));
+	str_copy(m_aFilterString, g_Config.m_BrFilterString, sizeof(m_aFilterString));
+	m_Sorthash = SortHash();
+}
+
+void CServerBrowser::RemoveRequest(CServerEntry *pEntry)
+{
+	if(pEntry->m_pPrevReq || pEntry->m_pNextReq || m_pFirstReqServer == pEntry)
+	{
+		if(pEntry->m_pPrevReq)
+			pEntry->m_pPrevReq->m_pNextReq = pEntry->m_pNextReq;
+		else
+			m_pFirstReqServer = pEntry->m_pNextReq;
+
+		if(pEntry->m_pNextReq)
+			pEntry->m_pNextReq->m_pPrevReq = pEntry->m_pPrevReq;
+		else
+			m_pLastReqServer = pEntry->m_pPrevReq;
+
+		pEntry->m_pPrevReq = 0;
+		pEntry->m_pNextReq = 0;
+		m_NumRequests--;
+	}
+}
+
+CServerBrowser::CServerEntry *CServerBrowser::Find(const NETADDR &Addr)
+{
+	CServerEntry *pEntry = m_aServerlistIp[Addr.ip[0]];
+
+	for(; pEntry; pEntry = pEntry->m_pNextIp)
+	{
+		if(net_addr_comp(&pEntry->m_Addr, &Addr) == 0)
+			return pEntry;
+	}
+	return (CServerEntry*)0;
+}
+
+void CServerBrowser::QueueRequest(CServerEntry *pEntry)
+{
+	// add it to the list of servers that we should request info from
+	pEntry->m_pPrevReq = m_pLastReqServer;
+	if(m_pLastReqServer)
+		m_pLastReqServer->m_pNextReq = pEntry;
+	else
+		m_pFirstReqServer = pEntry;
+	m_pLastReqServer = pEntry;
+
+	m_NumRequests++;
+}
+
+void CServerBrowser::SetInfo(CServerEntry *pEntry, const CServerInfo &Info)
+{
+	int Fav = pEntry->m_Info.m_Favorite;
+	pEntry->m_Info = Info;
+	pEntry->m_Info.m_Favorite = Fav;
+	pEntry->m_Info.m_NetAddr = pEntry->m_Addr;
+
+	// all these are just for nice compability
+	if(pEntry->m_Info.m_aGameType[0] == '0' && pEntry->m_Info.m_aGameType[1] == 0)
+		str_copy(pEntry->m_Info.m_aGameType, "DM", sizeof(pEntry->m_Info.m_aGameType));
+	else if(pEntry->m_Info.m_aGameType[0] == '1' && pEntry->m_Info.m_aGameType[1] == 0)
+		str_copy(pEntry->m_Info.m_aGameType, "TDM", sizeof(pEntry->m_Info.m_aGameType));
+	else if(pEntry->m_Info.m_aGameType[0] == '2' && pEntry->m_Info.m_aGameType[1] == 0)
+		str_copy(pEntry->m_Info.m_aGameType, "CTF", sizeof(pEntry->m_Info.m_aGameType));
+
+	/*if(!request)
+	{
+		pEntry->m_Info.latency = (time_get()-pEntry->request_time)*1000/time_freq();
+		RemoveRequest(pEntry);
+	}*/
+
+	pEntry->m_GotInfo = 1;
+	Sort();
+}
+
+CServerBrowser::CServerEntry *CServerBrowser::Add(const NETADDR &Addr)
+{
+	int Hash = Addr.ip[0];
+	CServerEntry *pEntry = 0;
+	int i;
+
+	// create new pEntry
+	pEntry = (CServerEntry *)m_ServerlistHeap.Allocate(sizeof(CServerEntry));
+	mem_zero(pEntry, sizeof(CServerEntry));
+
+	// set the info
+	pEntry->m_Addr = Addr;
+	pEntry->m_Info.m_NetAddr = Addr;
+
+	pEntry->m_Info.m_Latency = 999;
+	str_format(pEntry->m_Info.m_aAddress, sizeof(pEntry->m_Info.m_aAddress), "%d.%d.%d.%d:%d",
+		Addr.ip[0], Addr.ip[1], Addr.ip[2],
+		Addr.ip[3], Addr.port);
+	str_format(pEntry->m_Info.m_aName, sizeof(pEntry->m_Info.m_aName), "\255%d.%d.%d.%d:%d", // the \255 is to make sure that it's sorted last
+		Addr.ip[0], Addr.ip[1], Addr.ip[2],
+		Addr.ip[3], Addr.port);
+
+	/*if(serverlist_type == IServerBrowser::TYPE_LAN)
+		pEntry->m_Info.latency = (time_get()-broadcast_time)*1000/time_freq();*/
+
+	// check if it's a favorite
+	for(i = 0; i < m_NumFavoriteServers; i++)
+	{
+		if(net_addr_comp(&Addr, &m_aFavoriteServers[i]) == 0)
+			pEntry->m_Info.m_Favorite = 1;
+	}
+
+	// add to the hash list
+	pEntry->m_pNextIp = m_aServerlistIp[Hash];
+	m_aServerlistIp[Hash] = pEntry;
+
+	if(m_NumServers == m_NumServerCapacity)
+	{
+		CServerEntry **ppNewlist;
+		m_NumServerCapacity += 100;
+		ppNewlist = (CServerEntry **)mem_alloc(m_NumServerCapacity*sizeof(CServerEntry*), 1);
+		mem_copy(ppNewlist, m_ppServerlist, m_NumServers*sizeof(CServerEntry*));
+		mem_free(m_ppServerlist);
+		m_ppServerlist = ppNewlist;
+	}
+
+	// add to list
+	m_ppServerlist[m_NumServers] = pEntry;
+	pEntry->m_Info.m_ServerIndex = m_NumServers;
+	m_NumServers++;
+
+	return pEntry;
+}
+
+void CServerBrowser::Set(const NETADDR &Addr, int Type, int Token, const CServerInfo *pInfo)
+{
+	CServerEntry *pEntry = 0;
+	if(Type == IServerBrowser::SET_MASTER_ADD)
+	{
+		if(m_ServerlistType != IServerBrowser::TYPE_INTERNET)
+			return;
+
+		if(!Find(Addr))
+		{
+			pEntry = Add(Addr);
+			QueueRequest(pEntry);
+		}
+	}
+	else if(Type == IServerBrowser::SET_FAV_ADD)
+	{
+		if(m_ServerlistType != IServerBrowser::TYPE_FAVORITES)
+			return;
+
+		if(!Find(Addr))
+		{
+			pEntry = Add(Addr);
+			QueueRequest(pEntry);
+		}
+	}
+	else if(Type == IServerBrowser::SET_TOKEN)
+	{
+		if(Token != m_CurrentToken)
+			return;
+
+		pEntry = Find(Addr);
+		if(!pEntry)
+			pEntry = Add(Addr);
+		if(pEntry)
+		{
+			SetInfo(pEntry, *pInfo);
+			if(m_ServerlistType == IServerBrowser::TYPE_LAN)
+				pEntry->m_Info.m_Latency = (time_get()-m_BroadcastTime)*1000/time_freq();
+			else
+				pEntry->m_Info.m_Latency = (time_get()-pEntry->m_RequestTime)*1000/time_freq();
+			RemoveRequest(pEntry);
+		}
+	}
+	else if(Type == IServerBrowser::SET_OLD_INTERNET)
+	{
+		pEntry = Find(Addr);
+		if(pEntry)
+		{
+			SetInfo(pEntry, *pInfo);
+
+			if(m_ServerlistType == IServerBrowser::TYPE_LAN)
+				pEntry->m_Info.m_Latency = (time_get()-m_BroadcastTime)*1000/time_freq();
+			else
+				pEntry->m_Info.m_Latency = (time_get()-pEntry->m_RequestTime)*1000/time_freq();
+			RemoveRequest(pEntry);
+		}
+	}
+	else if(Type == IServerBrowser::SET_OLD_LAN)
+	{
+		pEntry = Find(Addr);
+		if(pEntry)
+		if(!pEntry)
+			pEntry = Add(Addr);
+		if(pEntry)
+			SetInfo(pEntry, *pInfo);
+	}
+
+	Sort();
+}
+
+void CServerBrowser::Refresh(int Type)
+{
+	// clear out everything
+	m_ServerlistHeap.Reset();
+	m_NumServers = 0;
+	m_NumSortedServers = 0;
+	mem_zero(m_aServerlistIp, sizeof(m_aServerlistIp));
+	m_pFirstReqServer = 0;
+	m_pLastReqServer = 0;
+	m_NumRequests = 0;
+
+	// next token
+	m_CurrentToken = (m_CurrentToken+1)&0xff;
+
+	//
+	m_ServerlistType = Type;
+
+	if(Type == IServerBrowser::TYPE_LAN)
+	{
+		unsigned char Buffer[sizeof(SERVERBROWSE_GETINFO)+1];
+		CNetChunk Packet;
+		int i;
+
+		mem_copy(Buffer, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO));
+		Buffer[sizeof(SERVERBROWSE_GETINFO)] = m_CurrentToken;
+
+		Packet.m_ClientID = -1;
+		mem_zero(&Packet, sizeof(Packet));
+		Packet.m_Address.ip[0] = 255;
+		Packet.m_Address.ip[1] = 255;
+		Packet.m_Address.ip[2] = 255;
+		Packet.m_Address.ip[3] = 255;
+		Packet.m_Flags = NETSENDFLAG_CONNLESS;
+		Packet.m_DataSize = sizeof(Buffer);
+		Packet.m_pData = Buffer;
+		m_BroadcastTime = time_get();
+
+		for(i = 8303; i <= 8310; i++)
+		{
+			Packet.m_Address.port = i;
+			m_pNetClient->Send(&Packet);
+		}
+
+		if(g_Config.m_Debug)
+			dbg_msg("client", "broadcasting for servers");
+	}
+	else if(Type == IServerBrowser::TYPE_INTERNET)
+		m_NeedRefresh = 1;
+	else if(Type == IServerBrowser::TYPE_FAVORITES)
+	{
+		for(int i = 0; i < m_NumFavoriteServers; i++)
+			Set(m_aFavoriteServers[i], IServerBrowser::SET_FAV_ADD, -1, 0);
+	}
+}
+
+void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry) const
+{
+	//unsigned char buffer[sizeof(SERVERBROWSE_GETINFO)+1];
+	CNetChunk Packet;
+
+	if(g_Config.m_Debug)
+	{
+		dbg_msg("client", "requesting server info from %d.%d.%d.%d:%d",
+			Addr.ip[0], Addr.ip[1], Addr.ip[2],
+			Addr.ip[3], Addr.port);
+	}
+
+	/*mem_copy(buffer, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO));
+	buffer[sizeof(SERVERBROWSE_GETINFO)] = current_token;*/
+
+	Packet.m_ClientID = -1;
+	Packet.m_Address = Addr;
+	Packet.m_Flags = NETSENDFLAG_CONNLESS;
+	/*p.data_size = sizeof(buffer);
+	p.data = buffer;
+	netclient_send(net, &p);*/
+
+	// send old request style aswell
+	Packet.m_DataSize = sizeof(SERVERBROWSE_OLD_GETINFO);
+	Packet.m_pData = SERVERBROWSE_OLD_GETINFO;
+	m_pNetClient->Send(&Packet);
+
+	if(pEntry)
+		pEntry->m_RequestTime = time_get();
+}
+
+void CServerBrowser::Request(const NETADDR &Addr) const
+{
+	RequestImpl(Addr, 0);
+}
+
+
+void CServerBrowser::Update()
+{
+	int64 Timeout = time_freq();
+	int64 Now = time_get();
+	int Count;
+	CServerEntry *pEntry, *pNext;
+
+	// do server list requests
+	if(m_NeedRefresh && !m_pMasterServer->IsRefreshing())
+	{
+		NETADDR Addr;
+		CNetChunk Packet;
+		int i;
+
+		m_NeedRefresh = 0;
+
+		mem_zero(&Packet, sizeof(Packet));
+		Packet.m_ClientID = -1;
+		Packet.m_Flags = NETSENDFLAG_CONNLESS;
+		Packet.m_DataSize = sizeof(SERVERBROWSE_GETLIST);
+		Packet.m_pData = SERVERBROWSE_GETLIST;
+
+		for(i = 0; i < IMasterServer::MAX_MASTERSERVERS; i++)
+		{
+			Addr = m_pMasterServer->GetAddr(i);
+			if(!Addr.ip[0] && !Addr.ip[1] && !Addr.ip[2] && !Addr.ip[3])
+				continue;
+
+			Packet.m_Address = Addr;
+			m_pNetClient->Send(&Packet);
+		}
+
+		if(g_Config.m_Debug)
+			dbg_msg("client", "requesting server list");
+	}
+
+	// do timeouts
+	pEntry = m_pFirstReqServer;
+	while(1)
+	{
+		if(!pEntry) // no more entries
+			break;
+
+		pNext = pEntry->m_pNextReq;
+
+		if(pEntry->m_RequestTime && pEntry->m_RequestTime+Timeout < Now)
+		{
+			// timeout
+			RemoveRequest(pEntry);
+			m_NumRequests--;
+		}
+
+		pEntry = pNext;
+	}
+
+	// do timeouts
+	pEntry = m_pFirstReqServer;
+	Count = 0;
+	while(1)
+	{
+		if(!pEntry) // no more entries
+			break;
+
+		// no more then 10 concurrent requests
+		if(Count == g_Config.m_BrMaxRequests)
+			break;
+
+		if(pEntry->m_RequestTime == 0)
+			RequestImpl(pEntry->m_Addr, pEntry);
+
+		Count++;
+		pEntry = pEntry->m_pNextReq;
+	}
+
+	// check if we need to resort
+	// TODO: remove the str_comp
+	if(m_Sorthash != SortHash() || str_comp(m_aFilterString, g_Config.m_BrFilterString) != 0 || str_comp(m_aFilterGametypeString, g_Config.m_BrFilterGametype) != 0)
+		Sort();
+}
+
+
+bool CServerBrowser::IsFavorite(const NETADDR &Addr) const
+{
+	// search for the address
+	int i;
+	for(i = 0; i < m_NumFavoriteServers; i++)
+	{
+		if(net_addr_comp(&Addr, &m_aFavoriteServers[i]) == 0)
+			return true;
+	}
+	return false;
+}
+
+void CServerBrowser::AddFavorite(const NETADDR &Addr)
+{
+	CServerEntry *pEntry;
+
+	if(m_NumFavoriteServers == MAX_FAVORITES)
+		return;
+
+	// make sure that we don't already have the server in our list
+	for(int i = 0; i < m_NumFavoriteServers; i++)
+	{
+		if(net_addr_comp(&Addr, &m_aFavoriteServers[i]) == 0)
+			return;
+	}
+
+	// add the server to the list
+	m_aFavoriteServers[m_NumFavoriteServers++] = Addr;
+	pEntry = Find(Addr);
+	if(pEntry)
+		pEntry->m_Info.m_Favorite = 1;
+
+    if(g_Config.m_Debug)
+        dbg_msg("", "added fav, %d.%d.%d.%d:%d", Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3], Addr.port);
+}
+
+void CServerBrowser::RemoveFavorite(const NETADDR &Addr)
+{
+	int i;
+	CServerEntry *pEntry;
+
+	for(i = 0; i < m_NumFavoriteServers; i++)
+	{
+		if(net_addr_comp(&Addr, &m_aFavoriteServers[i]) == 0)
+		{
+			mem_move(&m_aFavoriteServers[i], &m_aFavoriteServers[i+1], sizeof(NETADDR)*(m_NumFavoriteServers-(i+1)));
+			m_NumFavoriteServers--;
+
+			pEntry = Find(Addr);
+			if(pEntry)
+				pEntry->m_Info.m_Favorite = 0;
+
+			return;
+		}
+	}
+}
+
+
+bool CServerBrowser::IsRefreshingMasters() const
+{
+	return m_pMasterServer->IsRefreshing();
+}
+
+
+void CServerBrowser::ConfigSaveCallback(IConfig *pConfig, void *pUserData)
+{
+	CServerBrowser *pSelf = (CServerBrowser *)pUserData;
+
+	int i;
+	char aAddrStr[128];
+	char aBuffer[256];
+	for(i = 0; i < pSelf->m_NumFavoriteServers; i++)
+	{
+		net_addr_str(&pSelf->m_aFavoriteServers[i], aAddrStr, sizeof(aAddrStr));
+		str_format(aBuffer, sizeof(aBuffer), "add_favorite %s", aAddrStr);
+		pConfig->WriteLine(aBuffer);
+	}
+}
diff --git a/src/engine/client/srvbrowse.h b/src/engine/client/srvbrowse.h
new file mode 100644
index 00000000..1c255792
--- /dev/null
+++ b/src/engine/client/srvbrowse.h
@@ -0,0 +1,111 @@
+#ifndef ENGINE_CLIENT_SRVBROWSE_H
+#define ENGINE_CLIENT_SRVBROWSE_H
+
+#include <engine/serverbrowser.h>
+
+class CServerBrowser : public IServerBrowser
+{
+public:
+	class CServerEntry
+	{
+	public:
+		NETADDR m_Addr;
+		int64 m_RequestTime;
+		int m_GotInfo;
+		CServerInfo m_Info;
+
+		CServerEntry *m_pNextIp; // ip hashed list
+
+		CServerEntry *m_pPrevReq; // request list
+		CServerEntry *m_pNextReq;
+	};
+
+	enum
+	{
+		MAX_FAVORITES=256
+	};
+
+	CServerBrowser();
+
+	// interface functions
+	void Refresh(int Type);
+	bool IsRefreshingMasters() const;
+
+	int NumServers() const { return m_NumServers; }
+
+	int NumSortedServers() const { return m_NumSortedServers; }
+	const CServerInfo *SortedGet(int Index) const;
+
+	bool IsFavorite(const NETADDR &Addr) const;
+	void AddFavorite(const NETADDR &Addr);
+	void RemoveFavorite(const NETADDR &Addr);
+
+	//
+	void Update();
+	void Set(const NETADDR &Addr, int Type, int Token, const CServerInfo *pInfo);
+	void Request(const NETADDR &Addr) const;
+
+	void SetBaseInfo(class CNetClient *pClient, const char *pNetVersion);
+
+private:
+	CNetClient *m_pNetClient;
+	IMasterServer *m_pMasterServer;
+	char m_aNetVersion[128];
+
+	CHeap m_ServerlistHeap;
+	CServerEntry **m_ppServerlist;
+	int *m_pSortedServerlist;
+
+	NETADDR m_aFavoriteServers[MAX_FAVORITES];
+	int m_NumFavoriteServers;
+
+	CServerEntry *m_aServerlistIp[256]; // ip hash list
+
+	CServerEntry *m_pFirstReqServer; // request list
+	CServerEntry *m_pLastReqServer;
+	int m_NumRequests;
+
+	int m_NeedRefresh;
+
+	int m_NumSortedServers;
+	int m_NumSortedServersCapacity;
+	int m_NumServers;
+	int m_NumServerCapacity;
+
+	int m_Sorthash;
+	char m_aFilterString[64];
+	char m_aFilterGametypeString[128];
+
+	// the token is to keep server refresh separated from each other
+	int m_CurrentToken;
+
+	int m_ServerlistType;
+	int64 m_BroadcastTime;
+
+	// sorting criterions
+	bool SortCompareName(int Index1, int Index2) const;
+	bool SortCompareMap(int Index1, int Index2) const;
+	bool SortComparePing(int Index1, int Index2) const;
+	bool SortCompareGametype(int Index1, int Index2) const;
+	bool SortCompareProgression(int Index1, int Index2) const;
+	bool SortCompareNumPlayers(int Index1, int Index2) const;
+
+	//
+	void Filter();
+	void Sort();
+	int SortHash() const;
+
+	CServerEntry *Find(const NETADDR &Addr);
+	CServerEntry *Add(const NETADDR &Addr);
+ 
+	void RemoveRequest(CServerEntry *pEntry);
+	void QueueRequest(CServerEntry *pEntry);
+
+	void RequestImpl(const NETADDR &Addr, CServerEntry *pEntry) const;
+
+	void SetInfo(CServerEntry *pEntry, const CServerInfo &Info);
+
+	static void ConfigSaveCallback(IConfig *pConfig, void *pUserData);
+};
+
+#endif
diff --git a/src/engine/client/text.cpp b/src/engine/client/text.cpp
new file mode 100644
index 00000000..b05d49f8
--- /dev/null
+++ b/src/engine/client/text.cpp
@@ -0,0 +1,718 @@
+#include <base/system.h>
+#include <base/math.h>
+#include <engine/graphics.h>
+#include <engine/textrender.h>
+
+#ifdef CONF_FAMILY_WINDOWS
+	#include <windows.h>
+#endif
+
+#ifdef CONF_PLATFORM_MACOSX
+	#include <OpenGL/gl.h>
+	#include <OpenGL/glu.h>
+#else
+	#include <GL/gl.h>
+	#include <GL/glu.h>
+#endif
+
+// ft2 texture
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+// TODO: Refactor: clean this up
+
+
+enum
+{
+	MAX_CHARACTERS = 64,
+};
+
+
+static int aFontSizes[] = {8,9,10,11,12,13,14,15,16,17,18,19,20,36};
+#define NUM_FONT_SIZES (sizeof(aFontSizes)/sizeof(int))
+
+struct CFontChar
+{
+	int m_Id;
+	
+	// these values are scaled to the pFont size
+	// width * font_size == real_size
+	float m_Width;
+	float m_Height;
+	float m_OffsetX;
+	float m_OffsetY;
+	float m_AdvanceX;
+	
+	float m_aUvs[4];
+	int64 m_TouchTime;
+};
+
+struct CFontSizeData
+{
+	int m_FontSize;
+	FT_Face *m_pFace;
+
+	unsigned m_aTextures[2];
+	int m_TextureWidth;
+	int m_TextureHeight;
+	
+	int m_NumXChars;
+	int m_NumYChars;
+	
+	int m_CharMaxWidth;
+	int m_CharMaxHeight;
+	
+	CFontChar m_aCharacters[MAX_CHARACTERS*MAX_CHARACTERS];
+	
+	int m_CurrentCharacter;	
+};
+
+struct CFont
+{
+	char m_aFilename[128];
+	FT_Face m_FtFace;
+	CFontSizeData m_aSizes[NUM_FONT_SIZES];
+};
+
+
+class CTextRender : public IEngineTextRender
+{
+	IGraphics *m_pGraphics;
+	IGraphics *Graphics() { return m_pGraphics; }
+	
+	int WordLength(const char *pText)
+	{
+		int s = 1;
+		while(1)
+		{
+			if(*pText == 0)
+				return s-1;
+			if(*pText == '\n' || *pText == '\t' || *pText == ' ')
+				return s;
+			pText++;
+			s++;
+		}
+	}
+
+	float m_TextR;
+	float m_TextG;
+	float m_TextB;
+	float m_TextA;
+	
+	int m_FontTextureFormat;
+
+	struct CFont *m_pDefaultFont;
+
+	FT_Library m_FTLibrary;
+	
+	int GetFontSizeIndex(int Pixelsize)
+	{
+		for(unsigned i = 0; i < NUM_FONT_SIZES; i++)
+		{
+			if(aFontSizes[i] >= Pixelsize)
+				return i;
+		}
+		
+		return NUM_FONT_SIZES-1;
+	}
+	
+
+
+	void Grow(unsigned char *pIn, unsigned char *pOut, int w, int h)
+	{
+		for(int y = 0; y < h; y++) 
+			for(int x = 0; x < w; x++) 
+			{ 
+				int c = pIn[y*w+x]; 
+
+				for(int sy = -1; sy <= 1; sy++)
+					for(int sx = -1; sx <= 1; sx++)
+					{
+						int GetX = x+sx;
+						int GetY = y+sy;
+						if (GetX >= 0 && GetY >= 0 && GetX < w && GetY < h)
+						{
+							int Index = GetY*w+GetX;
+							if(pIn[Index] > c)
+								c = pIn[Index]; 
+						}
+					}
+
+				pOut[y*w+x] = c;
+			}
+	}
+
+	void InitTexture(CFontSizeData *pSizeData, int CharWidth, int CharHeight, int Xchars, int Ychars)
+	{
+		static int FontMemoryUsage = 0;
+		int Width = CharWidth*Xchars;
+		int Height = CharHeight*Ychars;
+		void *pMem = mem_alloc(Width*Height, 1);
+		mem_zero(pMem, Width*Height);
+		
+		if(pSizeData->m_aTextures[0] == 0)
+			glGenTextures(2, pSizeData->m_aTextures);
+		else
+			FontMemoryUsage -= pSizeData->m_TextureWidth*pSizeData->m_TextureHeight*2;
+		
+		pSizeData->m_NumXChars = Xchars;
+		pSizeData->m_NumYChars = Ychars;
+		pSizeData->m_TextureWidth = Width;
+		pSizeData->m_TextureHeight = Height;
+		pSizeData->m_CurrentCharacter = 0;
+		
+		for(int i = 0; i < 2; i++)
+		{
+			glBindTexture(GL_TEXTURE_2D, pSizeData->m_aTextures[i]);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+			glTexImage2D(GL_TEXTURE_2D, 0, m_FontTextureFormat, Width, Height, 0, m_FontTextureFormat, GL_UNSIGNED_BYTE, pMem);
+			FontMemoryUsage += Width*Height;
+		}
+		
+		dbg_msg("", "pFont memory usage: %d", FontMemoryUsage);
+		
+		mem_free(pMem);
+	}
+
+	void IncreaseTextureSize(CFontSizeData *pSizeData)
+	{
+		if(pSizeData->m_TextureWidth < pSizeData->m_TextureHeight)
+			pSizeData->m_NumXChars <<= 1;
+		else
+			pSizeData->m_NumYChars <<= 1;
+		InitTexture(pSizeData, pSizeData->m_CharMaxWidth, pSizeData->m_CharMaxHeight, pSizeData->m_NumXChars, pSizeData->m_NumYChars);		
+	}
+	
+	
+	// TODO: Refactor: move this into a pFont class
+	void InitIndex(CFont *pFont, int Index)
+	{
+		int OutlineThickness = 1;
+		CFontSizeData *pSizeData = &pFont->m_aSizes[Index];
+		
+		pSizeData->m_FontSize = aFontSizes[Index];
+		FT_Set_Pixel_Sizes(pFont->m_FtFace, 0, pSizeData->m_FontSize);
+		
+		if(pSizeData->m_FontSize >= 18)
+			OutlineThickness = 2;
+			
+		{
+			unsigned GlyphIndex;
+			int MaxH = 0;
+			int MaxW = 0;
+			
+			int Charcode = FT_Get_First_Char(pFont->m_FtFace, &GlyphIndex);
+			while(GlyphIndex != 0)
+			{   
+				// do stuff
+				FT_Load_Glyph(pFont->m_FtFace, GlyphIndex, FT_LOAD_DEFAULT);
+				
+				if(pFont->m_FtFace->glyph->metrics.width > MaxW) MaxW = pFont->m_FtFace->glyph->metrics.width; // ignore_convention
+				if(pFont->m_FtFace->glyph->metrics.height > MaxH) MaxH = pFont->m_FtFace->glyph->metrics.height; // ignore_convention
+				Charcode = FT_Get_Next_Char(pFont->m_FtFace, Charcode, &GlyphIndex);
+			}
+			
+			MaxW = (MaxW>>6)+2+OutlineThickness*2;
+			MaxH = (MaxH>>6)+2+OutlineThickness*2;
+			
+			for(pSizeData->m_CharMaxWidth = 1; pSizeData->m_CharMaxWidth < MaxW; pSizeData->m_CharMaxWidth <<= 1);
+			for(pSizeData->m_CharMaxHeight = 1; pSizeData->m_CharMaxHeight < MaxH; pSizeData->m_CharMaxHeight <<= 1);
+		}
+		
+		//dbg_msg("pFont", "init size %d, texture size %d %d", pFont->sizes[index].font_size, w, h);
+		//FT_New_Face(m_FTLibrary, "data/fonts/vera.ttf", 0, &pFont->ft_face);
+		InitTexture(pSizeData, pSizeData->m_CharMaxWidth, pSizeData->m_CharMaxHeight, 8, 8);
+	}
+
+	CFontSizeData *GetSize(CFont *pFont, int Pixelsize)
+	{
+		int Index = GetFontSizeIndex(Pixelsize);
+		if(pFont->m_aSizes[Index].m_FontSize != aFontSizes[Index])
+			InitIndex(pFont, Index);
+		return &pFont->m_aSizes[Index];
+	}
+
+
+	void UploadGlyph(CFontSizeData *pSizeData, int Texnum, int SlotId, int Chr, const void *pData)
+	{
+		int x = (SlotId%pSizeData->m_NumXChars) * (pSizeData->m_TextureWidth/pSizeData->m_NumXChars);
+		int y = (SlotId/pSizeData->m_NumXChars) * (pSizeData->m_TextureHeight/pSizeData->m_NumYChars);
+		
+		glBindTexture(GL_TEXTURE_2D, pSizeData->m_aTextures[Texnum]);
+		glTexSubImage2D(GL_TEXTURE_2D, 0, x, y,
+			pSizeData->m_TextureWidth/pSizeData->m_NumXChars,
+			pSizeData->m_TextureHeight/pSizeData->m_NumYChars,
+			m_FontTextureFormat, GL_UNSIGNED_BYTE, pData);
+	}
+
+	// 8k of data used for rendering glyphs
+	unsigned char ms_aGlyphData[(4096/64) * (4096/64)];
+	unsigned char ms_aGlyphDataOutlined[(4096/64) * (4096/64)];
+
+	int GetSlot(CFontSizeData *pSizeData)
+	{
+		int CharCount = pSizeData->m_NumXChars*pSizeData->m_NumYChars;
+		if(pSizeData->m_CurrentCharacter < CharCount)
+		{
+			int i = pSizeData->m_CurrentCharacter;
+			pSizeData->m_CurrentCharacter++;
+			return i;
+		}
+
+		// kick out the oldest
+		// TODO: remove this linear search
+		{
+			int Oldest = 0;
+			for(int i = 1; i < CharCount; i++)
+			{
+				if(pSizeData->m_aCharacters[i].m_TouchTime < pSizeData->m_aCharacters[Oldest].m_TouchTime)
+					Oldest = i;
+			}
+			
+			if(time_get()-pSizeData->m_aCharacters[Oldest].m_TouchTime < time_freq())
+			{
+				IncreaseTextureSize(pSizeData);
+				return GetSlot(pSizeData);
+			}
+			
+			return Oldest;
+		}
+	}
+
+	int RenderGlyph(CFont *pFont, CFontSizeData *pSizeData, int Chr)
+	{
+		FT_Bitmap *pBitmap;
+		int SlotId = 0;
+		int SlotW = pSizeData->m_TextureWidth / pSizeData->m_NumXChars;
+		int SlotH = pSizeData->m_TextureHeight / pSizeData->m_NumYChars;
+		int SlotSize = SlotW*SlotH;
+		int OutlineThickness = 1;
+		int x = 1;
+		int y = 1;
+		int px, py;
+
+		FT_Set_Pixel_Sizes(pFont->m_FtFace, 0, pSizeData->m_FontSize);
+
+		if(FT_Load_Char(pFont->m_FtFace, Chr, FT_LOAD_RENDER|FT_LOAD_NO_BITMAP))
+		{
+			dbg_msg("pFont", "error loading glyph %d", Chr);
+			return -1;
+		}
+
+		pBitmap = &pFont->m_FtFace->glyph->bitmap; // ignore_convention
+		
+		// fetch slot
+		SlotId = GetSlot(pSizeData);
+		if(SlotId < 0)
+			return -1;
+		
+		// adjust spacing
+		if(pSizeData->m_FontSize >= 18)
+			OutlineThickness = 2;
+		x += OutlineThickness;
+		y += OutlineThickness;
+
+		// prepare glyph data
+		mem_zero(ms_aGlyphData, SlotSize);
+
+		if(pBitmap->pixel_mode == FT_PIXEL_MODE_GRAY) // ignore_convention
+		{
+			for(py = 0; py < pBitmap->rows; py++) // ignore_convention
+				for(px = 0; px < pBitmap->width; px++) // ignore_convention
+					ms_aGlyphData[(py+y)*SlotW+px+x] = pBitmap->buffer[py*pBitmap->pitch+px]; // ignore_convention
+		}
+		else if(pBitmap->pixel_mode == FT_PIXEL_MODE_MONO) // ignore_convention
+		{
+			for(py = 0; py < pBitmap->rows; py++)  // ignore_convention
+				for(px = 0; px < pBitmap->width; px++) // ignore_convention
+				{
+					if(pBitmap->buffer[py*pBitmap->pitch+px/8]&(1<<(7-(px%8)))) // ignore_convention
+						ms_aGlyphData[(py+y)*SlotW+px+x] = 255;
+				}
+		}
+
+		if(0) for(py = 0; py < SlotW; py++) 
+			for(px = 0; px < SlotH; px++) 
+				ms_aGlyphData[py*SlotW+px] = 255;
+		
+		// upload the glyph
+		UploadGlyph(pSizeData, 0, SlotId, Chr, ms_aGlyphData);
+		
+		if(OutlineThickness == 1)
+		{
+			Grow(ms_aGlyphData, ms_aGlyphDataOutlined, SlotW, SlotH);
+			UploadGlyph(pSizeData, 1, SlotId, Chr, ms_aGlyphDataOutlined);
+		}
+		else
+		{
+			Grow(ms_aGlyphData, ms_aGlyphDataOutlined, SlotW, SlotH);
+			Grow(ms_aGlyphDataOutlined, ms_aGlyphData, SlotW, SlotH);
+			UploadGlyph(pSizeData, 1, SlotId, Chr, ms_aGlyphData);
+		}
+		
+		// set char info
+		{
+			CFontChar *pFontchr = &pSizeData->m_aCharacters[SlotId];
+			float Scale = 1.0f/pSizeData->m_FontSize;
+			float Uscale = 1.0f/pSizeData->m_TextureWidth;
+			float Vscale = 1.0f/pSizeData->m_TextureHeight;
+			int Height = pBitmap->rows + OutlineThickness*2 + 2; // ignore_convention
+			int Width = pBitmap->width + OutlineThickness*2 + 2; // ignore_convention
+			
+			pFontchr->m_Id = Chr;
+			pFontchr->m_Height = Height * Scale;
+			pFontchr->m_Width = Width * Scale;
+			pFontchr->m_OffsetX = (pFont->m_FtFace->glyph->bitmap_left-1) * Scale; // ignore_convention
+			pFontchr->m_OffsetY = (pSizeData->m_FontSize - pFont->m_FtFace->glyph->bitmap_top) * Scale; // ignore_convention
+			pFontchr->m_AdvanceX = (pFont->m_FtFace->glyph->advance.x>>6) * Scale; // ignore_convention
+			
+			pFontchr->m_aUvs[0] = (SlotId%pSizeData->m_NumXChars) / (float)(pSizeData->m_NumXChars);
+			pFontchr->m_aUvs[1] = (SlotId/pSizeData->m_NumXChars) / (float)(pSizeData->m_NumYChars);
+			pFontchr->m_aUvs[2] = pFontchr->m_aUvs[0] + Width*Uscale;
+			pFontchr->m_aUvs[3] = pFontchr->m_aUvs[1] + Height*Vscale;
+		}
+		
+		return SlotId;
+	}
+
+	CFontChar *GetChar(CFont *pFont, CFontSizeData *pSizeData, int Chr)
+	{
+		CFontChar *pFontchr = NULL;
+		
+		// search for the character
+		// TODO: remove this linear search
+		int i;
+		for(i = 0; i < pSizeData->m_CurrentCharacter; i++)
+		{
+			if(pSizeData->m_aCharacters[i].m_Id == Chr)
+			{
+				pFontchr = &pSizeData->m_aCharacters[i];
+				break;
+			}
+		}
+		
+		// check if we need to render the character
+		if(!pFontchr)
+		{
+			int Index = RenderGlyph(pFont, pSizeData, Chr);
+			if(Index >= 0)
+				pFontchr = &pSizeData->m_aCharacters[Index];
+		}
+		
+		// touch the character
+		// TODO: don't call time_get here
+		if(pFontchr)
+			pFontchr->m_TouchTime = time_get();
+			
+		return pFontchr;
+	}
+
+	// must only be called from the rendering function as the pFont must be set to the correct size
+	void RenderSetup(CFont *pFont, int size)
+	{
+		FT_Set_Pixel_Sizes(pFont->m_FtFace, 0, size);
+	}
+
+	float Kerning(CFont *pFont, int Left, int Right)
+	{
+		FT_Vector Kerning = {0,0};
+		FT_Get_Kerning(pFont->m_FtFace, Left, Right, FT_KERNING_DEFAULT, &Kerning);
+		return (Kerning.x>>6);
+	}
+	
+	
+public:
+	CTextRender()
+	{
+		m_pGraphics = 0;
+
+		m_TextR = 1;
+		m_TextG = 1;
+		m_TextB = 1;
+		m_TextA = 1;
+
+		m_pDefaultFont = 0;
+
+		// GL_LUMINANCE can be good for debugging
+		m_FontTextureFormat = GL_ALPHA;
+	}
+		
+	virtual void Init()
+	{
+		m_pGraphics = Kernel()->RequestInterface<IGraphics>();
+		FT_Init_FreeType(&m_FTLibrary);
+	}
+			
+
+	virtual CFont *LoadFont(const char *pFilename)
+	{
+		CFont *pFont = (CFont *)mem_alloc(sizeof(CFont), 1);
+		
+		mem_zero(pFont, sizeof(*pFont));
+		str_copy(pFont->m_aFilename, pFilename, sizeof(pFont->m_aFilename));
+		
+		if(FT_New_Face(m_FTLibrary, pFont->m_aFilename, 0, &pFont->m_FtFace))
+		{
+			mem_free(pFont);
+			return NULL;
+		}
+
+		for(unsigned i = 0; i < NUM_FONT_SIZES; i++)
+			pFont->m_aSizes[i].m_FontSize = -1;
+		
+		dbg_msg("textrender", "loaded pFont from '%s'", pFilename);
+		return pFont;
+	};
+
+	virtual void DestroyFont(CFont *pFont)
+	{
+		mem_free(pFont);
+	}
+
+	virtual void SetDefaultFont(struct CFont *pFont)
+	{
+		dbg_msg("textrender", "default pFont set %p", pFont);
+		m_pDefaultFont = pFont;
+	}
+		
+		
+	virtual void SetCursor(CTextCursor *pCursor, float x, float y, float FontSize, int Flags)
+	{
+		mem_zero(pCursor, sizeof(*pCursor));
+		pCursor->m_FontSize = FontSize;
+		pCursor->m_StartX = x;
+		pCursor->m_StartY = y;
+		pCursor->m_X = x;
+		pCursor->m_Y = y;
+		pCursor->m_LineCount = 1;
+		pCursor->m_LineWidth = -1;
+		pCursor->m_Flags = Flags;
+		pCursor->m_CharCount = 0;
+	}
+	
+		
+	virtual void Text(void *pFontSetV, float x, float y, float Size, const char *pText, int MaxWidth)
+	{
+		CTextCursor Cursor;
+		SetCursor(&Cursor, x, y, Size, TEXTFLAG_RENDER);
+		Cursor.m_LineWidth = MaxWidth;
+		TextEx(&Cursor, pText, -1);
+	}
+
+	virtual float TextWidth(void *pFontSetV, float Size, const char *pText, int Length)
+	{
+		CTextCursor Cursor;
+		SetCursor(&Cursor, 0, 0, Size, 0);
+		TextEx(&Cursor, pText, Length);
+		return Cursor.m_X;
+	}
+	
+	virtual float TextLineCount(void *pFontSetV, float Size, const char *pText, int LineWidth)
+	{
+		CTextCursor Cursor;
+		SetCursor(&Cursor, 0, 0, Size, 0);
+		Cursor.m_LineWidth = LineWidth;
+		TextEx(&Cursor, pText, -1);
+		return Cursor.m_LineCount;
+	}
+
+	virtual void TextColor(float r, float g, float b, float a)
+	{
+		m_TextR = r;
+		m_TextG = g;
+		m_TextB = b;
+		m_TextA = a;
+	}
+	
+	virtual void TextEx(CTextCursor *pCursor, const char *pText, int Length)
+	{
+		CFont *pFont = pCursor->m_pFont;
+		CFontSizeData *pSizeData = NULL;
+		
+		//dbg_msg("textrender", "rendering text '%s'", text);
+
+		float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
+		float FakeToScreenX, FakeToScreenY;
+		int ActualX, ActualY;
+
+		int ActualSize;
+		int i;
+		int GotNewLine = 0;
+		float DrawX, DrawY;
+		float CursorX, CursorY;
+		const char *pEnd;
+
+		float Size = pCursor->m_FontSize;
+
+		// to correct coords, convert to screen coords, round, and convert back
+		Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1);
+		
+		FakeToScreenX = (Graphics()->ScreenWidth()/(ScreenX1-ScreenX0));
+		FakeToScreenY = (Graphics()->ScreenHeight()/(ScreenY1-ScreenY0));
+		ActualX = pCursor->m_X * FakeToScreenX;
+		ActualY = pCursor->m_Y * FakeToScreenY;
+
+		CursorX = ActualX / FakeToScreenX;
+		CursorY = ActualY / FakeToScreenY;
+
+		// same with size
+		ActualSize = Size * FakeToScreenY;
+		Size = ActualSize / FakeToScreenY;
+
+		// fetch pFont data
+		if(!pFont)
+			pFont = m_pDefaultFont;
+		
+		if(!pFont)
+			return;
+
+		pSizeData = GetSize(pFont, ActualSize);
+		RenderSetup(pFont, ActualSize);
+		
+		// set length
+		if(Length < 0)
+			Length = str_length(pText);
+			
+		pEnd = pText + Length;
+
+		// if we don't want to render, we can just skip the first outline pass
+		i = 1;
+		if(pCursor->m_Flags&TEXTFLAG_RENDER)
+			i = 0;
+
+		for(;i < 2; i++)
+		{
+			const char *pCurrent = (char *)pText;
+			const char *pEnd = pCurrent+Length;
+			DrawX = CursorX;
+			DrawY = CursorY;
+
+			if(pCursor->m_Flags&TEXTFLAG_RENDER)
+			{
+				// TODO: Make this better
+				glEnable(GL_TEXTURE_2D);
+				if (i == 0)
+					glBindTexture(GL_TEXTURE_2D, pSizeData->m_aTextures[1]);
+				else
+					glBindTexture(GL_TEXTURE_2D, pSizeData->m_aTextures[0]);
+
+				Graphics()->QuadsBegin();
+				if (i == 0)
+					Graphics()->SetColor(0.0f, 0.0f, 0.0f, 0.3f*m_TextA);
+				else
+					Graphics()->SetColor(m_TextR, m_TextG, m_TextB, m_TextA);
+			}
+
+			while(pCurrent < pEnd)
+			{
+				int NewLine = 0;
+				const char *pBatchEnd = pEnd;
+				if(pCursor->m_LineWidth > 0 && !(pCursor->m_Flags&TEXTFLAG_STOP_AT_END))
+				{
+					int Wlen = min(WordLength((char *)pCurrent), (int)(pEnd-pCurrent));
+					CTextCursor Compare = *pCursor;
+					Compare.m_X = DrawX;
+					Compare.m_Y = DrawY;
+					Compare.m_Flags &= ~TEXTFLAG_RENDER;
+					Compare.m_LineWidth = -1;
+					TextEx(&Compare, pText, Wlen);
+					
+					if(Compare.m_X-DrawX > pCursor->m_LineWidth)
+					{
+						// word can't be fitted in one line, cut it
+						CTextCursor Cutter = *pCursor;
+						Cutter.m_CharCount = 0;
+						Cutter.m_X = DrawX;
+						Cutter.m_Y = DrawY;
+						Cutter.m_Flags &= ~TEXTFLAG_RENDER;
+						Cutter.m_Flags |= TEXTFLAG_STOP_AT_END;
+						
+						TextEx(&Cutter, (const char *)pCurrent, Wlen);
+						Wlen = Cutter.m_CharCount;
+						NewLine = 1;
+						
+						if(Wlen <= 3) // if we can't place 3 chars of the word on this line, take the next
+							Wlen = 0;
+					}
+					else if(Compare.m_X-pCursor->m_StartX > pCursor->m_LineWidth)
+					{
+						NewLine = 1;
+						Wlen = 0;
+					}
+					
+					pBatchEnd = pCurrent + Wlen;
+				}
+				
+				while(pCurrent < pBatchEnd)
+				{
+					const char *pTmp;
+					float Advance = 0;
+					int Character = 0;
+					int Nextcharacter = 0;
+					CFontChar *pChr;
+
+					// TODO: UTF-8 decode
+					Character = str_utf8_decode(&pCurrent);
+					pTmp = pCurrent;
+					Nextcharacter = str_utf8_decode(&pTmp);
+					
+					if(Character == '\n')
+					{
+						DrawX = pCursor->m_StartX;
+						DrawY += Size;
+						DrawX = (int)(DrawX * FakeToScreenX) / FakeToScreenX; // realign
+						DrawY = (int)(DrawY * FakeToScreenY) / FakeToScreenY;
+						++pCursor->m_LineCount;
+						continue;
+					}
+
+					pChr = GetChar(pFont, pSizeData, Character);
+
+					if(pChr)
+					{
+						if(pCursor->m_Flags&TEXTFLAG_RENDER)
+						{
+							Graphics()->QuadsSetSubset(pChr->m_aUvs[0], pChr->m_aUvs[1], pChr->m_aUvs[2], pChr->m_aUvs[3]);
+							IGraphics::CQuadItem QuadItem(DrawX+pChr->m_OffsetX*Size, DrawY+pChr->m_OffsetY*Size, pChr->m_Width*Size, pChr->m_Height*Size);
+							Graphics()->QuadsDrawTL(&QuadItem, 1);
+						}
+
+						Advance = pChr->m_AdvanceX + Kerning(pFont, Character, Nextcharacter)/Size;
+					}
+									
+					if(pCursor->m_Flags&TEXTFLAG_STOP_AT_END && DrawX+Advance*Size-pCursor->m_StartX > pCursor->m_LineWidth)
+					{
+						// we hit the end of the line, no more to render or count
+						pCurrent = pEnd;
+						break;
+					}
+
+					DrawX += Advance*Size;
+					pCursor->m_CharCount++;
+				}
+				
+				if(NewLine)
+				{
+					DrawX = pCursor->m_StartX;
+					DrawY += Size;
+					GotNewLine = 1;
+					DrawX = (int)(DrawX * FakeToScreenX) / FakeToScreenX; // realign
+					DrawY = (int)(DrawY * FakeToScreenY) / FakeToScreenY;				
+					++pCursor->m_LineCount;
+				}
+			}
+
+			if(pCursor->m_Flags&TEXTFLAG_RENDER)
+				Graphics()->QuadsEnd();
+		}
+
+		pCursor->m_X = DrawX;
+		
+		if(GotNewLine)
+			pCursor->m_Y = DrawY;
+	}
+	
+};
+
+IEngineTextRender *CreateEngineTextRender() { return new CTextRender; }
diff --git a/src/engine/config.h b/src/engine/config.h
new file mode 100644
index 00000000..967d3593
--- /dev/null
+++ b/src/engine/config.h
@@ -0,0 +1,23 @@
+#ifndef ENGINE_CONFIG_H
+#define ENGINE_CONFIG_H
+
+#include "kernel.h"
+
+class IConfig : public IInterface
+{
+	MACRO_INTERFACE("config", 0)
+public:
+	typedef void (*SAVECALLBACKFUNC)(IConfig *pConfig, void *pUserData);
+
+	virtual void Init() = 0;
+	virtual void Reset() = 0;
+	virtual void Save() = 0;
+	
+	virtual void RegisterCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData) = 0;
+	
+	virtual void WriteLine(const char *pLine) = 0;
+};
+
+extern IConfig *CreateConfig();
+
+#endif
diff --git a/src/engine/console.h b/src/engine/console.h
new file mode 100644
index 00000000..74d789e9
--- /dev/null
+++ b/src/engine/console.h
@@ -0,0 +1,58 @@
+#ifndef ENGINE_CONSOLE_H
+#define ENGINE_CONSOLE_H
+
+#include "kernel.h"
+
+class IConsole : public IInterface
+{
+	MACRO_INTERFACE("console", 0)
+public:
+
+	// TODO: rework this interface to reduce the amount of virtual calls
+	class IResult
+	{
+	protected:
+		unsigned m_NumArgs;
+	public:
+		IResult() { m_NumArgs = 0; }
+		virtual ~IResult() {}
+		
+		virtual int GetInteger(unsigned Index) = 0;
+		virtual float GetFloat(unsigned Index) = 0;
+		virtual const char *GetString(unsigned Index) = 0;
+		
+		int NumArguments() const { return m_NumArgs; }
+	};
+	
+	class CCommandInfo
+	{
+	public:
+		const char *m_pName;
+		const char *m_pHelp;
+		const char *m_pParams;
+	};
+
+	typedef void (*FPrintCallback)(const char *pStr, void *pUser);
+	typedef void (*FPossibleCallback)(const char *pCmd, void *pUser);
+	typedef void (*FCommandCallback)(IResult *pResult, void *pUserData);
+	typedef void (*FChainCommandCallback)(IResult *pResult, void *pUserData, FCommandCallback pfnCallback, void *pCallbackUserData);
+
+	virtual CCommandInfo *GetCommandInfo(const char *pName) = 0;
+	virtual void PossibleCommands(const char *pStr, int FlagMask, FPossibleCallback pfnCallback, void *pUser) = 0;
+	virtual void ParseArguments(int NumArgs, const char **ppArguments) = 0;
+
+	virtual void Register(const char *pName, const char *pParams, 
+		int Flags, FCommandCallback pfnFunc, void *pUser, const char *pHelp) = 0;
+	virtual void Chain(const char *pName, FChainCommandCallback pfnChainFunc, void *pUser) = 0;
+	
+	virtual void ExecuteLine(const char *Sptr) = 0;
+	virtual void ExecuteLineStroked(int Stroke, const char *pStr) = 0;
+	virtual void ExecuteFile(const char *pFilename) = 0;
+	
+	virtual void RegisterPrintCallback(FPrintCallback pfnPrintCallback, void *pUserData) = 0;
+	virtual void Print(const char *pStr) = 0;
+};
+
+extern IConsole *CreateConsole();
+
+#endif // FILE_ENGINE_CONSOLE_H
diff --git a/src/engine/demo.h b/src/engine/demo.h
new file mode 100644
index 00000000..7b353e7c
--- /dev/null
+++ b/src/engine/demo.h
@@ -0,0 +1,29 @@
+#ifndef ENGINE_DEMO_H
+#define ENGINE_DEMO_H
+
+#include "kernel.h"
+
+class IDemoPlayer : public IInterface
+{
+	MACRO_INTERFACE("demoplayer", 0)
+public:
+	class CInfo
+	{
+	public:
+		bool m_Paused;
+		float m_Speed;
+
+		int m_FirstTick;
+		int m_CurrentTick;
+		int m_LastTick;
+	};
+
+	~IDemoPlayer() {}
+	virtual void SetSpeed(float Speed) = 0;
+	virtual int SetPos(float Precent) = 0;
+	virtual void Pause() = 0;
+	virtual void Unpause() = 0;
+	virtual const CInfo *BaseInfo() const = 0;
+};
+
+#endif
diff --git a/src/engine/e_client_interface.h b/src/engine/e_client_interface.h
deleted file mode 100644
index 079eabca..00000000
--- a/src/engine/e_client_interface.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef ENGINE_CLIENT_INTERFACE_H
-#define ENGINE_CLIENT_INTERFACE_H
-
-#include "e_if_other.h"
-#include "e_if_client.h"
-#include "e_if_snd.h"
-#include "e_if_gfx.h"
-#include "e_if_inp.h"
-#include "e_if_msg.h"
-#include "e_if_modc.h"
-
-#include "e_console.h"
-#include "e_config.h"
-
-#endif
diff --git a/src/engine/e_common_interface.h b/src/engine/e_common_interface.h
deleted file mode 100644
index 9c95b48b..00000000
--- a/src/engine/e_common_interface.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef ENGINE_COMMON_INTERFACE_H
-#define ENGINE_COMMON_INTERFACE_H
-
-#include "e_if_other.h"
-#include "e_if_msg.h"
-
-#endif
diff --git a/src/engine/e_compression.cpp b/src/engine/e_compression.cpp
deleted file mode 100644
index f4d6e0c0..00000000
--- a/src/engine/e_compression.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <base/system.h>
-
-/* Format: ESDDDDDD EDDDDDDD EDD...  Extended, Data, Sign */
-unsigned char *vint_pack(unsigned char *dst, int i) 
-{ 
-	*dst = (i>>25)&0x40; /* set sign bit if i<0 */
-	i = i^(i>>31); /* if(i<0) i = ~i */
-
-	*dst |= i&0x3F; /* pack 6bit into dst */
-	i >>= 6; /* discard 6 bits */
-	if(i)
-	{
-		*dst |= 0x80; /* set extend bit */
-		while(1)
-		{
-			dst++;
-			*dst = i&(0x7F); /* pack 7bit */
-			i >>= 7; /* discard 7 bits */
-			*dst |= (i!=0)<<7; /* set extend bit (may branch) */
-			if(!i)
-				break;
-		}
-	}
-
-	dst++;
-	return dst; 
-} 
- 
-const unsigned char *vint_unpack(const unsigned char *src, int *i)
-{ 
-	int sign = (*src>>6)&1; 
-	*i = *src&0x3F; 
-
-	do
-	{ 
-		if(!(*src&0x80)) break;
-		src++;
-		*i |= (*src&(0x7F))<<(6);
-
-		if(!(*src&0x80)) break;
-		src++;
-		*i |= (*src&(0x7F))<<(6+7);
-
-		if(!(*src&0x80)) break;
-		src++;
-		*i |= (*src&(0x7F))<<(6+7+7);
-
-		if(!(*src&0x80)) break;
-		src++;
-		*i |= (*src&(0x7F))<<(6+7+7+7);
-	} while(0);
-
-	src++;
-	*i ^= -sign; /* if(sign) *i = ~(*i) */
-	return src; 
-} 
-
-
-long intpack_decompress(const void *src_, int size, void *dst_)
-{
-	const unsigned char *src = (unsigned char *)src_;
-	const unsigned char *end = src + size;
-	int *dst = (int *)dst_;
-	while(src < end)
-	{
-		src = vint_unpack(src, dst);
-		dst++;
-	}
-	return (long)((unsigned char *)dst-(unsigned char *)dst_);
-}
-
-long intpack_compress(const void *src_, int size, void *dst_)
-{
-	int *src = (int *)src_;
-	unsigned char *dst = (unsigned char *)dst_;
-	size /= 4;
-	while(size)
-	{
-		dst = vint_pack(dst, *src);
-		size--;
-		src++;
-	}
-	return (long)(dst-(unsigned char *)dst_);
-}
-
diff --git a/src/engine/e_compression.h b/src/engine/e_compression.h
deleted file mode 100644
index be5bf78f..00000000
--- a/src/engine/e_compression.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-
-/* variable int packing */
-unsigned char *vint_pack(unsigned char *dst, int i);
-const unsigned char *vint_unpack(const unsigned char *src, int *inout);
-long intpack_compress(const void *src, int size, void *dst);
-long intpack_decompress(const void *src, int size, void *dst);
diff --git a/src/engine/e_config.cpp b/src/engine/e_config.cpp
deleted file mode 100644
index 67a4c81a..00000000
--- a/src/engine/e_config.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <base/system.h>
-#include "e_if_other.h"
-#include "e_config.h"
-#include "e_linereader.h"
-#include "e_engine.h"
-
-CONFIGURATION config;
-
-void config_reset()
-{
-    #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" 
- 
-    #undef MACRO_CONFIG_INT 
-    #undef MACRO_CONFIG_STR 
-}
-
-void config_save()
-{
-	char linebuf[1024*2];
-	
-	#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" 
-
-	#undef MACRO_CONFIG_INT 
-	#undef MACRO_CONFIG_STR 
-}
-
-#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,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
deleted file mode 100644
index 6ca7a8ee..00000000
--- a/src/engine/e_config.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef _CONFIG_H
-#define _CONFIG_H
-
-typedef struct
-{ 
-    #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 
-} CONFIGURATION;
-
-extern CONFIGURATION config;
-
-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,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,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
-
-#endif
diff --git a/src/engine/e_config_variables.h b/src/engine/e_config_variables.h
deleted file mode 100644
index aa3da3f6..00000000
--- a/src/engine/e_config_variables.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-
-/* TODO: remove this */
-#include "../game/variables.hpp"
-
-
-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, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
-MACRO_CONFIG_INT(cl_editor, 0, 0, 1, CFGFLAG_CLIENT, "")
-
-MACRO_CONFIG_INT(cl_eventthread, 0, 0, 1, CFGFLAG_CLIENT, "Enables the usage of a thread to pump the events")
-
-MACRO_CONFIG_INT(inp_grab, 0, 0, 1, CFGFLAG_CLIENT, "Use forceful input grabbing method")
-
-MACRO_CONFIG_STR(b_filter_string, 64, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Server browser filtering string")
-
-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_pure, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out non-standard servers in browser")
-MACRO_CONFIG_INT(b_filter_pure_map, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out non-standard maps 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, 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_buffer_size, 512, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sound buffer size")
-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, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
-
-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_finish, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
-
-MACRO_CONFIG_INT(inp_mousesens, 100, 5, 100000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Mouse sensitivity")
-
-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_INT(sv_map_reload, 0, 0, 1, CFGFLAG_SERVER, "Reload the current map")
-
-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(dbg_resizable, 0, 0, 0, CFGFLAG_CLIENT, "Enables window resizing")
diff --git a/src/engine/e_console.cpp b/src/engine/e_console.cpp
deleted file mode 100644
index c641289d..00000000
--- a/src/engine/e_console.cpp
+++ /dev/null
@@ -1,464 +0,0 @@
-#include <base/system.h>
-#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>
-#include <stdlib.h>
-
-
-#define CONSOLE_MAX_STR_LENGTH 1024
-/* the maximum number of tokens occurs in a string of length CONSOLE_MAX_STR_LENGTH with tokens size 1 separated by single spaces */
-#define MAX_PARTS (CONSOLE_MAX_STR_LENGTH+1)/2
-
-typedef struct
-{ 
-	char string_storage[CONSOLE_MAX_STR_LENGTH+1];
-	char *args_start;
-	
-	const char *command;
-	const char *args[MAX_PARTS]; 
-	unsigned int num_args; 
-} PARSE_RESULT;
-
-static char *str_skipblanks(char *str)
-{
-	while(*str && (*str == ' ' || *str == '\t' || *str == '\n'))
-		str++;
-	return str;
-}
-
-static char *str_skiptoblank(char *str)
-{
-	while(*str && (*str != ' ' && *str != '\t' && *str != '\n'))
-		str++;
-	return str;
-}
-
-/* static int digit(char c) { return '0' <= c && c <= '9'; } */
-
-static int console_parse_start(PARSE_RESULT *result, const char *string, int length)
-{
-	char *str;
-	int len = sizeof(result->string_storage);
-	if(length < len)
-		len = length;
-		
-	str_copy(result->string_storage, string, length);
-	str = result->string_storage;
-	
-	/* get command */
-	str = str_skipblanks(str);
-	result->command = str;
-	str = str_skiptoblank(str);
-	
-	if(*str)
-	{
-		str[0] = 0;
-		str++;
-	}
-	
-	result->args_start = str;
-	result->num_args = 0;
-	return 0;
-}
-
-static int console_parse_args(PARSE_RESULT *result, const char *format)
-{
-	char command;
-	char *str;
-	int optional = 0;
-	int error = 0;
-	
-	str = result->args_start;
-
-	while(1)	
-	{
-		/* fetch command */
-		command = *format;
-		format++;
-		
-		if(!command)
-			break;
-		
-		if(command == '?')
-			optional = 1;
-		else
-		{
-			str = str_skipblanks(str);
-		
-			if(!(*str)) /* error, non optional command needs value */
-			{
-				if(!optional)
-					error = 1;
-				break;
-			}
-			
-			/* add token */
-			if(*str == '"')
-			{
-				char *dst;
-				str++;
-				result->args[result->num_args++] = str;
-				
-				dst = str; /* we might have to process escape data */
-				while(1)
-				{
-					if(str[0] == '"')
-						break;
-					else if(str[0] == '\\')
-					{
-						if(str[1] == '\\')
-							str++; /* skip due to escape */
-						else if(str[1] == '"')
-							str++; /* skip due to escape */
-					}
-					else if(str[0] == 0)
-						return 1; /* return error */
-						
-					*dst = *str;
-					dst++;
-					str++;
-				}
-				
-				/* write null termination */
-				*dst = 0;
-			}
-			else
-			{
-				result->args[result->num_args++] = str;
-				
-				if(command == 'r') /* rest of the string */
-					break;
-				else if(command == 'i') /* validate int */
-					str = str_skiptoblank(str);
-				else if(command == 'f') /* validate float */
-					str = str_skiptoblank(str);
-				else if(command == 's') /* validate string */
-					str = str_skiptoblank(str);
-
-				if(str[0] != 0) /* check for end of string */
-				{
-					str[0] = 0;
-					str++;
-				}
-			}
-		}
-	}
-
-	return error;
-}
-
-const char *console_arg_string(void *res, unsigned index)
-{
-	PARSE_RESULT *result = (PARSE_RESULT *)res;
-	if (index < 0 || index >= result->num_args)
-		return "";
-	return result->args[index];
-}
-
-int console_arg_int(void *res, unsigned index)
-{
-	PARSE_RESULT *result = (PARSE_RESULT *)res;
-	if (index < 0 || index >= result->num_args)
-		return 0;
-	return atoi(result->args[index]);
-}
-
-float console_arg_float(void *res, unsigned index)
-{
-	PARSE_RESULT *result = (PARSE_RESULT *)res;
-	if (index < 0 || index >= result->num_args)
-		return 0.0f;
-	return atof(result->args[index]);
-}
-
-int console_arg_num(void *result)
-{
-	return ((PARSE_RESULT *)result)->num_args;
-}
-
-static COMMAND *first_command = 0x0;
-
-COMMAND *console_find_command(const char *name)
-{
-	COMMAND *cmd;
-	for (cmd = first_command; cmd; cmd = cmd->next)
-	{
-		if (strcmp(cmd->name, name) == 0)
-			return cmd;
-	}
-
-	return 0x0;
-}
-
-void console_register(COMMAND *cmd)
-{
-	cmd->next = first_command;
-	first_command = cmd;
-}
-
-static void (*print_callback)(const char *, void *) = 0x0;
-static void *print_callback_userdata;
-
-void console_register_print_callback(void (*callback)(const char *, void *), void *user_data)
-{
-	print_callback = callback;
-	print_callback_userdata = user_data;
-}
-
-void console_print(const char *str)
-{
-	if (print_callback)
-		print_callback(str, print_callback_userdata);
-}
-
-void console_execute_line_stroked(int stroke, const char *str)
-{
-	PARSE_RESULT result;
-	COMMAND *command;
-	
-	char strokestr[2] = {'0', 0};
-	if(stroke)
-		strokestr[0] = '1';
-
-	while(str)
-	{
-		const char *end = str;
-		const char *next_part = 0;
-		int in_string = 0;
-		
-		while(*end)
-		{
-			if(*end == '"')
-				in_string ^= 1;
-			else if(*end == '\\') /* escape sequences */
-			{
-				if(end[1] == '"')
-					end++;
-			}
-			else if(!in_string)
-			{
-				if(*end == ';')  /* command separator */
-				{
-					next_part = end+1;
-					break;
-				}
-				else if(*end == '#')  /* comment, no need to do anything more */
-					break;
-			}
-			
-			end++;
-		}
-		
-		if(console_parse_start(&result, str, (end-str) + 1) != 0)
-			return;
-
-		command = console_find_command(result.command);
-
-		if(command)
-		{
-			int is_stroke_command = 0;
-			if(result.command[0] == '+')
-			{
-				/* insert the stroke direction token */
-				result.args[result.num_args] = strokestr;
-				result.num_args++;
-				is_stroke_command = 1;
-			}
-			
-			if(stroke || is_stroke_command)
-			{
-				if(console_parse_args(&result, command->params))
-				{
-					char buf[256];
-					str_format(buf, sizeof(buf), "Invalid arguments... Usage: %s %s", command->name, command->params);
-					console_print(buf);
-				}
-				else
-					command->callback(&result, command->user_data);
-			}
-		}
-		else
-		{
-			char buf[256];
-			str_format(buf, sizeof(buf), "No such command: %s.", result.command);
-			console_print(buf);
-		}
-		
-		str = next_part;
-	}
-}
-
-void console_possible_commands(const char *str, int flagmask, void (*callback)(const char *cmd, void *user), void *user)
-{
-	COMMAND *cmd;
-	for (cmd = first_command; cmd; cmd = cmd->next)
-	{
-		if(cmd->flags&flagmask)
-		{
-			if(str_find_nocase(cmd->name, str))
-				callback(cmd->name, user);
-		}
-	}	
-}
-
-
-COMMAND *console_get_command(const char *str)
-{
-	COMMAND *cmd;
-	for (cmd = first_command; cmd; cmd = cmd->next)
-	{
-		if(str_comp_nocase(cmd->name, str) == 0)
-			return cmd;
-	}	
-	
-	return 0x0;
-}
-
-void console_execute_line(const char *str)
-{
-	console_execute_line_stroked(1, str);
-}
-
-static void console_execute_file_real(const char *filename)
-{
-	IOHANDLE file;
-	file = engine_openfile(filename, IOFLAG_READ);
-	
-	if(file)
-	{
-		char *line;
-		LINEREADER lr;
-		
-		dbg_msg("console", "executing '%s'", filename);
-		linereader_init(&lr, file);
-
-		while((line = linereader_get(&lr)))
-			console_execute_line(line);
-
-		io_close(file);
-	}
-	else
-		dbg_msg("console", "failed to open '%s'", filename);
-}
-
-struct EXECFILE
-{
-	const char *filename;
-	struct EXECFILE *next;
-};
-
-void console_execute_file(const char *filename)
-{
-	static struct EXECFILE *first = 0;
-	struct EXECFILE this_file;
-	struct EXECFILE *cur;
-	struct EXECFILE *prev;
-
-	/* make sure that this isn't being executed already */	
-	for(cur = first; cur; cur = cur->next)
-		if(strcmp(filename, cur->filename) == 0)
-			return;
-	
-	/* push this one to the stack */
-	prev = first;
-	this_file.filename = filename;
-	this_file.next = first;
-	first = &this_file;
-	
-	/* execute file */
-	console_execute_file_real(filename);
-	
-	/* pop this one from the stack */
-	first = prev;
-}
-
-static void con_echo(void *result, void *user_data)
-{
-	console_print(console_arg_string(result, 0));
-}
-
-static void con_exec(void *result, void *user_data)
-{
-	console_execute_file(console_arg_string(result, 0));
-
-}
-
-
-typedef struct 
-{
-	CONFIG_INT_GETTER getter;
-	CONFIG_INT_SETTER setter;
-} INT_VARIABLE_DATA;
-
-typedef struct
-{
-	CONFIG_STR_GETTER getter;
-	CONFIG_STR_SETTER setter;
-} STR_VARIABLE_DATA;
-
-static void int_variable_command(void *result, void *user_data)
-{
-	INT_VARIABLE_DATA *data = (INT_VARIABLE_DATA *)user_data;
-
-	if(console_arg_num(result))
-		data->setter(&config, console_arg_int(result, 0));
-	else
-	{
-		char buf[1024];
-		str_format(buf, sizeof(buf), "Value: %d", data->getter(&config));
-		console_print(buf);
-	}
-}
-
-static void str_variable_command(void *result, void *user_data)
-{
-	STR_VARIABLE_DATA *data = (STR_VARIABLE_DATA *)user_data;
-
-	if(console_arg_num(result))
-		data->setter(&config, console_arg_string(result, 0));
-	else
-	{
-		char buf[1024];
-		str_format(buf, sizeof(buf), "Value: %s", data->getter(&config));
-		console_print(buf);
-	}
-}
-
-static void console_chain(void *result, void *user_data)
-{
-	COMMANDCHAIN *info = (COMMANDCHAIN *)user_data;
-	info->chain_callback(result, info->user_data, info->callback, info->callback_user_data);
-}
-
-void console_chain_command(const char *cmd, COMMANDCHAIN *chaininfo, CONSOLE_CHAIN_CALLBACK cb, void *user)
-{
-	COMMAND *command = console_get_command(cmd);
-
-	/* store info */
-	chaininfo->chain_callback = cb;
-	chaininfo->callback = command->callback;
-	chaininfo->callback_user_data = command->user_data;
-	chaininfo->user_data = user;
-	
-	/* chain */
-	command->callback = console_chain;
-	command->user_data = chaininfo;
-}
-
-void console_init()
-{
-	MACRO_REGISTER_COMMAND("echo", "r", CFGFLAG_SERVER|CFGFLAG_CLIENT, con_echo, 0x0, "Echo the text");
-	MACRO_REGISTER_COMMAND("exec", "r", CFGFLAG_SERVER|CFGFLAG_CLIENT, con_exec, 0x0, "Execute the specified file");
-
-	#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", flags, int_variable_command, &data, desc) }
-	#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", flags, str_variable_command, &data, desc) }
-
-	#include "e_config_variables.h" 
-
-	#undef MACRO_CONFIG_INT 
-	#undef MACRO_CONFIG_STR 
-}
diff --git a/src/engine/e_console.h b/src/engine/e_console.h
deleted file mode 100644
index a45bac10..00000000
--- a/src/engine/e_console.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef _CONSOLE_H
-#define _CONSOLE_H
-
-typedef void (*CONSOLE_CALLBACK)(void *result, void *user_data);
-typedef void (*CONSOLE_CHAIN_CALLBACK)(void *result, void *user_data, CONSOLE_CALLBACK cb, void *cbuser);
-
-typedef struct COMMAND_t
-{
-	const char *name;
-	const char *params;
-	int flags;
-	CONSOLE_CALLBACK callback;
-	void *user_data;
-	const char *help;
-	struct COMMAND_t *next;
-} COMMAND;
-
-typedef struct COMMANDCHAIN_t
-{
-	CONSOLE_CHAIN_CALLBACK chain_callback;
-	CONSOLE_CALLBACK callback;
-	void *callback_user_data;
-	void *user_data;
-} COMMANDCHAIN;
-
-void console_init();
-void console_register(COMMAND *cmd);
-void console_execute_line(const char *str);
-void console_execute_line_stroked(int stroke, const char *str);
-void console_execute_file(const char *filename);
-void console_possible_commands(const char *str, int flagmask, void (*callback)(const char *cmd, void *user), void *user);
-COMMAND *console_get_command(const char *cmd);
-void console_chain_command(const char *cmd, COMMANDCHAIN *chaininfo, CONSOLE_CHAIN_CALLBACK cb, void *user);
-void console_print(const char *str);
-void console_register_print_callback(void (*callback)(const char *, void *user_data), void *user_data);
-
-/*int console_result_string(void *result, int index, const char **str);
-int console_result_int(void *result, int index, int *i);
-int console_result_float(void *result, int index, float *f);*/
-
-const char *console_arg_string(void *result, unsigned index);
-int console_arg_int(void *result, unsigned index);
-float console_arg_float(void *result, unsigned index);
-int console_arg_num(void *result);
-
-#define MACRO_REGISTER_COMMAND(name, params, flags, func, ptr, help) { static COMMAND cmd = { name, params, flags, func, ptr, help, 0x0}; console_register(&cmd); }
-
-#endif
diff --git a/src/engine/e_datafile.cpp b/src/engine/e_datafile.cpp
deleted file mode 100644
index 0317f9d0..00000000
--- a/src/engine/e_datafile.cpp
+++ /dev/null
@@ -1,677 +0,0 @@
-/* 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;
-
-typedef struct 
-{
-	int type;
-	int start;
-	int num;
-} DATAFILE_ITEM_TYPE;
-
-typedef struct 
-{
-	int type_and_id;
-	int size;
-} DATAFILE_ITEM;
-
-typedef struct
-{
-	char id[4];
-	int version;
-	int size;
-	int swaplen;
-	int num_item_types;
-	int num_items;
-	int num_raw_data;
-	int item_size;
-	int data_size;
-} DATAFILE_HEADER;
-
-typedef struct
-{
-	int num_item_types;
-	int num_items;
-	int num_raw_data;
-	int item_size;
-	int data_size;
-	char start[4];
-} DATAFILE_DATA;
-
-typedef struct
-{
-	DATAFILE_ITEM_TYPE *item_types;
-	int *item_offsets;
-	int *data_offsets;
-	int *data_sizes;
-
-	char *item_start;
-	char *data_start;
-} DATAFILE_INFO;
-
-struct DATAFILE_t
-{
-	IOHANDLE file;
-	DATAFILE_INFO info;
-	DATAFILE_HEADER header;
-	int data_start_offset;
-	char **data_ptrs;
-	char *data;
-};
-
-DATAFILE *datafile_load(const char *filename)
-{
-	DATAFILE *df;
-	IOHANDLE file;
-	DATAFILE_HEADER header;
-	unsigned readsize;
-	
-	unsigned *dst;
-	unsigned char *src;
-	unsigned j;
-	int size = 0;
-	int allocsize = 0;
-	
-	(void)dst;
-	(void)src;
-	(void)j;
-	
-	
-	dbg_msg("datafile", "datafile loading. filename='%s'", filename);
-
-	file = engine_openfile(filename, IOFLAG_READ);
-	if(!file)
-		return 0;
-	
-	/* TODO: change this header */
-	io_read(file, &header, sizeof(header));
-	if(header.id[0] != 'A' || header.id[1] != 'T' || header.id[2] != 'A' || header.id[3] != 'D')
-	{
-		if(header.id[0] != 'D' || header.id[1] != 'A' || header.id[2] != 'T' || header.id[3] != 'A')
-		{
-			dbg_msg("datafile", "wrong signature. %x %x %x %x", header.id[0], header.id[1], header.id[2], header.id[3]);
-			return 0;
-		}
-	}
-
-#if defined(CONF_ARCH_ENDIAN_BIG)
-	swap_endian(&header, sizeof(int), sizeof(header)/sizeof(int));	
-#endif
-	if(header.version != 3 && header.version != 4)
-	{
-		dbg_msg("datafile", "wrong version. version=%x", header.version);
-		return 0;
-	}
-	
-	/* read in the rest except the data */
-	size = 0;
-	size += header.num_item_types*sizeof(DATAFILE_ITEM_TYPE);
-	size += (header.num_items+header.num_raw_data)*sizeof(int);
-	if(header.version == 4)
-		size += header.num_raw_data*sizeof(int); /* v4 has uncompressed data sizes aswell */
-	size += header.item_size;
-	
-	allocsize = size;
-	allocsize += sizeof(DATAFILE); /* add space for info structure */
-	allocsize += header.num_raw_data*sizeof(void*); /* add space for data pointers */
-
-	df = (DATAFILE*)mem_alloc(allocsize, 1);
-	df->header = header;
-	df->data_start_offset = sizeof(DATAFILE_HEADER) + size;
-	df->data_ptrs = (char**)(df+1);
-	df->data = (char *)(df+1)+header.num_raw_data*sizeof(char *);
-	df->file = file;
-	
-	/* clear the data pointers */
-	mem_zero(df->data_ptrs, header.num_raw_data*sizeof(void*));
-	
-	/* read types, offsets, sizes and item data */
-	readsize = io_read(file, df->data, size);
-	if(readsize != size)
-	{
-		dbg_msg("datafile", "couldn't load the whole thing, wanted=%d got=%d", size, readsize);
-		return 0;
-	}
-
-#if defined(CONF_ARCH_ENDIAN_BIG)
-	swap_endian(df->data, sizeof(int), header.swaplen / sizeof(int));
-#endif
-
-	if(DEBUG)
-	{
-		dbg_msg("datafile", "allocsize=%d", allocsize);
-		dbg_msg("datafile", "readsize=%d", readsize);
-		dbg_msg("datafile", "swaplen=%d", header.swaplen);
-		dbg_msg("datafile", "item_size=%d", df->header.item_size);
-	}
-	
-	df->info.item_types = (DATAFILE_ITEM_TYPE *)df->data;
-	df->info.item_offsets = (int *)&df->info.item_types[df->header.num_item_types];
-	df->info.data_offsets = (int *)&df->info.item_offsets[df->header.num_items];
-	df->info.data_sizes = (int *)&df->info.data_offsets[df->header.num_raw_data];
-	
-	if(header.version == 4)
-		df->info.item_start = (char *)&df->info.data_sizes[df->header.num_raw_data];
-	else
-		df->info.item_start = (char *)&df->info.data_offsets[df->header.num_raw_data];
-	df->info.data_start = df->info.item_start + df->header.item_size;
-
-	if(DEBUG)
-		dbg_msg("datafile", "datafile loading done. datafile='%s'", filename);
-
-	if(DEBUG)
-	{
-		/*
-		for(int i = 0; i < df->data.num_raw_data; i++)
-		{
-			void *p = datafile_get_data(df, i);
-			dbg_msg("datafile", "%d %d", (int)((char*)p - (char*)(&df->data)), size);
-		}
-			
-		for(int i = 0; i < datafile_num_items(df); i++)
-		{
-			int type, id;
-			void *data = datafile_get_item(df, i, &type, &id);
-			dbg_msg("map", "\t%d: type=%x id=%x p=%p offset=%d", i, type, id, data, df->info.item_offsets[i]);
-			int *idata = (int*)data;
-			for(int k = 0; k < 3; k++)
-				dbg_msg("datafile", "\t\t%d=%d (%x)", k, idata[k], idata[k]);
-		}
-
-		for(int i = 0; i < df->data.num_item_types; i++)
-		{
-			dbg_msg("map", "\t%d: type=%x start=%d num=%d", i,
-				df->info.item_types[i].type,
-				df->info.item_types[i].start,
-				df->info.item_types[i].num);
-			for(int k = 0; k < df->info.item_types[i].num; k++)
-			{
-				int type, id;
-				datafile_get_item(df, df->info.item_types[i].start+k, &type, &id);
-				if(type != df->info.item_types[i].type)
-					dbg_msg("map", "\tERROR");
-			}
-		}
-		*/
-	}
-		
-	return df;
-}
-
-int datafile_num_data(DATAFILE *df)
-{
-	return df->header.num_raw_data;
-}
-
-/* always returns the size in the file */
-int datafile_get_datasize(DATAFILE *df, int index)
-{
-	if(index == df->header.num_raw_data-1)
-		return df->header.data_size-df->info.data_offsets[index];
-	return  df->info.data_offsets[index+1]-df->info.data_offsets[index];
-}
-
-static void *datafile_get_data_impl(DATAFILE *df, int index, int swap)
-{
-	/* load it if needed */
-	if(!df->data_ptrs[index])
-	{
-		/* fetch the data size */
-		int datasize = datafile_get_datasize(df, index);
-		int swapsize = datasize;
-		
-		if(df->header.version == 4)
-		{
-			/* v4 has compressed data */
-			void *temp = (char *)mem_alloc(datasize, 1);
-			unsigned long uncompressed_size = df->info.data_sizes[index];
-			unsigned long s;
-
-			dbg_msg("datafile", "loading data index=%d size=%d uncompressed=%d", index, datasize, uncompressed_size);
-			df->data_ptrs[index] = (char *)mem_alloc(uncompressed_size, 1);
-			
-			/* read the compressed data */
-			io_seek(df->file, df->data_start_offset+df->info.data_offsets[index], IOSEEK_START);
-			io_read(df->file, temp, datasize);
-
-			/* decompress the data, TODO: check for errors */
-			s = uncompressed_size;
-			uncompress((Bytef*)df->data_ptrs[index], &s, (Bytef*)temp, datasize);
-			swapsize = s;
-
-			/* clean up the temporary buffers */
-			mem_free(temp);
-		}
-		else
-		{
-			/* load the data */
-			dbg_msg("datafile", "loading data index=%d size=%d", index, datasize);
-			df->data_ptrs[index] = (char *)mem_alloc(datasize, 1);
-			io_seek(df->file, df->data_start_offset+df->info.data_offsets[index], IOSEEK_START);
-			io_read(df->file, df->data_ptrs[index], datasize);
-		}
-
-#if defined(CONF_ARCH_ENDIAN_BIG)
-		if(swap && swapsize)
-			swap_endian(df->data_ptrs[index], sizeof(int), swapsize/sizeof(int));
-#endif
-	}
-	
-	return df->data_ptrs[index];
-}
-
-void *datafile_get_data(DATAFILE *df, int index)
-{
-	return datafile_get_data_impl(df, index, 0);
-}
-
-void *datafile_get_data_swapped(DATAFILE *df, int index)
-{
-	return datafile_get_data_impl(df, index, 1);
-}
-
-void datafile_unload_data(DATAFILE *df, int index)
-{
-	if(index < 0)
-		return;
-		
-	/* */
-	mem_free(df->data_ptrs[index]);
-	df->data_ptrs[index] = 0x0;
-}
-
-int datafile_get_itemsize(DATAFILE *df, int index)
-{
-	if(index == df->header.num_items-1)
-		return df->header.item_size-df->info.item_offsets[index];
-	return  df->info.item_offsets[index+1]-df->info.item_offsets[index];
-}
-
-void *datafile_get_item(DATAFILE *df, int index, int *type, int *id)
-{
-	DATAFILE_ITEM *i = (DATAFILE_ITEM *)(df->info.item_start+df->info.item_offsets[index]);
-	if(type)
-		*type = (i->type_and_id>>16)&0xffff; /* remove sign extention */
-	if(id)
-		*id = i->type_and_id&0xffff;
-	return (void *)(i+1);
-}
-
-void datafile_get_type(DATAFILE *df, int type, int *start, int *num)
-{
-	int i;
-	for(i = 0; i < df->header.num_item_types; i++)
-	{
-		if(df->info.item_types[i].type == type)
-		{
-			*start = df->info.item_types[i].start;
-			*num = df->info.item_types[i].num;
-			return;
-		}
-	}
-	
-	*start = 0;
-	*num = 0;
-}
-
-void *datafile_find_item(DATAFILE *df, int type, int id)
-{
-	int start, num,i ;
-	int item_id;
-	void *item;
-	
-	datafile_get_type(df, type, &start, &num);
-	for(i = 0; i < num; i++)
-	{
-		item = datafile_get_item(df, start+i,0, &item_id);
-		if(id == item_id)
-			return item;
-	}
-	return 0;
-}
-
-int datafile_num_items(DATAFILE *df)
-{
-	return df->header.num_items;
-}
-
-void datafile_unload(DATAFILE *df)
-{
-	if(df)
-	{
-		/* free the data that is loaded */
-		int i;
-		for(i = 0; i < df->header.num_raw_data; i++)
-			mem_free(df->data_ptrs[i]);
-		
-		io_close(df->file);
-		mem_free(df);
-	}
-}
-
-/* DATAFILE output */
-typedef struct
-{
-	int uncompressed_size;
-	int compressed_size;
-	void *compressed_data;
-} DATA_INFO;
-
-typedef struct
-{
-	int type;
-	int id;
-	int size;
-	int next;
-	int prev;
-	void *data;
-} ITEM_INFO;
-
-typedef struct
-{
-	int num;
-	int first;
-	int last;
-} ITEMTYPE_INFO;
-
-/* */
-struct DATAFILE_OUT_t
-{
-	IOHANDLE file;
-	int num_items;
-	int num_datas;
-	int num_item_types;
-	ITEMTYPE_INFO item_types[0xffff];
-	ITEM_INFO items[1024];
-	DATA_INFO datas[1024];
-};
-
-DATAFILE_OUT *datafile_create(const char *filename)
-{
-	int i;
-	DATAFILE_OUT *df = (DATAFILE_OUT*)mem_alloc(sizeof(DATAFILE_OUT), 1);
-	df->file = engine_openfile(filename, IOFLAG_WRITE);
-	if(!df->file)
-	{
-		mem_free(df);
-		return 0;
-	}
-	
-	df->num_items = 0;
-	df->num_datas = 0;
-	df->num_item_types = 0;
-	mem_zero(&df->item_types, sizeof(df->item_types));
-
-	for(i = 0; i < 0xffff; i++)
-	{
-		df->item_types[i].first = -1;
-		df->item_types[i].last = -1;
-	}
-	
-	return df;
-}
-
-int datafile_add_item(DATAFILE_OUT *df, int type, int id, int size, void *data)
-{
-	df->items[df->num_items].type = type;
-	df->items[df->num_items].id = id;
-	df->items[df->num_items].size = size;
-	
-	/*
-	dbg_msg("datafile", "added item type=%d id=%d size=%d", type, id, size);
-	int i;
-	for(i = 0; i < size/4; i++)
-		dbg_msg("datafile", "\t%d: %08x %d", i, ((int*)data)[i], ((int*)data)[i]);
-	*/
-	
-	/* copy data */
-	df->items[df->num_items].data = mem_alloc(size, 1);
-	mem_copy(df->items[df->num_items].data, data, size);
-
-	if(!df->item_types[type].num) /* count item types */
-		df->num_item_types++;
-
-	/* link */
-	df->items[df->num_items].prev = df->item_types[type].last;
-	df->items[df->num_items].next = -1;
-	
-	if(df->item_types[type].last != -1)
-		df->items[df->item_types[type].last].next = df->num_items;
-	df->item_types[type].last = df->num_items;
-	
-	if(df->item_types[type].first == -1)
-		df->item_types[type].first = df->num_items;
-	
-	df->item_types[type].num++;
-		
-	df->num_items++;
-	return df->num_items-1;
-}
-
-int datafile_add_data(DATAFILE_OUT *df, int size, void *data)
-{
-	DATA_INFO *info = &df->datas[df->num_datas];
-	unsigned long s = compressBound(size);
-	void *compdata = mem_alloc(s, 1); /* temporary buffer that we use duing compression */
-
-	int result = compress((Bytef*)compdata, &s, (Bytef*)data, size);
-	if(result != Z_OK)
-	{
-		dbg_msg("datafile", "compression error %d", result);
-		dbg_assert(0, "zlib error");
-	}
-		
-	info->uncompressed_size = size;
-	info->compressed_size = (int)s;
-	info->compressed_data = mem_alloc(info->compressed_size, 1);
-	mem_copy(info->compressed_data, compdata, info->compressed_size);
-	mem_free(compdata);
-
-	df->num_datas++;
-	return df->num_datas-1;
-}
-
-int datafile_add_data_swapped(DATAFILE_OUT *df, int size, void *data)
-{
-#if defined(CONF_ARCH_ENDIAN_BIG)
-	void *swapped = mem_alloc(size, 1); /* temporary buffer that we use duing compression */
-	int index;
-	mem_copy(swapped, data, size);
-	swap_endian(&swapped, sizeof(int), size/sizeof(int));
-	index = datafile_add_data(df, size, swapped);
-	mem_free(swapped);
-	return index;
-#else
-	return datafile_add_data(df, size, data);
-#endif
-}
-
-
-int datafile_finish(DATAFILE_OUT *df)
-{
-	int itemsize = 0;
-	int i, count, offset;
-	int typessize, headersize, offsetsize, filesize, swapsize;
-	int datasize = 0;
-	DATAFILE_ITEM_TYPE info;
-	DATAFILE_ITEM itm;
-	DATAFILE_HEADER header;
-
-	/* we should now write this file! */
-	if(DEBUG)
-		dbg_msg("datafile", "writing");
-
-	/* calculate sizes */
-	for(i = 0; i < df->num_items; i++)
-	{
-		if(DEBUG)
-			dbg_msg("datafile", "item=%d size=%d (%d)", i, df->items[i].size, df->items[i].size+sizeof(DATAFILE_ITEM));
-		itemsize += df->items[i].size + sizeof(DATAFILE_ITEM);
-	}
-	
-	
-	for(i = 0; i < df->num_datas; i++)
-		datasize += df->datas[i].compressed_size;
-	
-	/* calculate the complete size */
-	typessize = df->num_item_types*sizeof(DATAFILE_ITEM_TYPE);
-	headersize = sizeof(DATAFILE_HEADER);
-	offsetsize = df->num_items*sizeof(int) + df->num_datas*sizeof(int);
-	filesize = headersize + typessize + offsetsize + itemsize + datasize;
-	swapsize = filesize - datasize;
-	
-	(void)swapsize;
-	
-	if(DEBUG)
-		dbg_msg("datafile", "num_item_types=%d typessize=%d itemsize=%d datasize=%d", df->num_item_types, typessize, itemsize, datasize);
-	
-	/* construct header */
-	{
-		header.id[0] = 'D';
-		header.id[1] = 'A';
-		header.id[2] = 'T';
-		header.id[3] = 'A';
-		header.version = 4;
-		header.size = filesize - 16;
-		header.swaplen = swapsize - 16;
-		header.num_item_types = df->num_item_types;
-		header.num_items = df->num_items;
-		header.num_raw_data = df->num_datas;
-		header.item_size = itemsize;
-		header.data_size = datasize;
-		
-		/* TODO: apply swapping */
-		/* write header */
-		if(DEBUG)
-			dbg_msg("datafile", "headersize=%d", sizeof(header));
-		io_write(df->file, &header, sizeof(header));
-	}
-	
-	/* write types */
-	for(i = 0, count = 0; i < 0xffff; i++)
-	{
-		if(df->item_types[i].num)
-		{
-			/* write info */
-			info.type = i;
-			info.start = count;
-			info.num = df->item_types[i].num;
-			if(DEBUG)
-				dbg_msg("datafile", "writing type=%x start=%d num=%d", info.type, info.start, info.num);
-			io_write(df->file, &info, sizeof(info));
-			count += df->item_types[i].num;
-		}
-	}
-	
-	/* write item offsets */
-	for(i = 0, offset = 0; i < 0xffff; i++)
-	{
-		if(df->item_types[i].num)
-		{
-			/* write all items in of this type */
-			int k = df->item_types[i].first;
-			while(k != -1)
-			{
-				if(DEBUG)
-					dbg_msg("datafile", "writing item offset num=%d offset=%d", k, offset);
-				io_write(df->file, &offset, sizeof(offset));
-				offset += df->items[k].size + sizeof(DATAFILE_ITEM);
-				
-				/* next */
-				k = df->items[k].next;
-			}
-		}
-	}
-	
-	/* write data offsets */
-	for(i = 0, offset = 0; i < df->num_datas; i++)
-	{
-		if(DEBUG)
-			dbg_msg("datafile", "writing data offset num=%d offset=%d", i, offset);
-		io_write(df->file, &offset, sizeof(offset));
-		offset += df->datas[i].compressed_size;
-	}
-
-	/* write data uncompressed sizes */
-	for(i = 0, offset = 0; i < df->num_datas; i++)
-	{
-		/*
-		if(DEBUG)
-			dbg_msg("datafile", "writing data offset num=%d offset=%d", i, offset);
-		*/
-		io_write(df->file, &df->datas[i].uncompressed_size, sizeof(int));
-	}
-	
-	/* write items */
-	for(i = 0; i < 0xffff; i++)
-	{
-		if(df->item_types[i].num)
-		{
-			/* write all items in of this type */
-			int k = df->item_types[i].first;
-			while(k != -1)
-			{
-				itm.type_and_id = (i<<16)|df->items[k].id;
-				itm.size = df->items[k].size;
-				if(DEBUG)
-					dbg_msg("datafile", "writing item type=%x idx=%d id=%d size=%d", i, k, df->items[k].id, df->items[k].size);
-				
-				io_write(df->file, &itm, sizeof(itm));
-				io_write(df->file, df->items[k].data, df->items[k].size);
-				
-				/* next */
-				k = df->items[k].next;
-			}
-		}
-	}
-	
-	/* write data */
-	for(i = 0; i < df->num_datas; i++)
-	{
-		if(DEBUG)
-			dbg_msg("datafile", "writing data id=%d size=%d", i, df->datas[i].compressed_size);
-		io_write(df->file, df->datas[i].compressed_data, df->datas[i].compressed_size);
-	}
-
-	/* free data */
-	for(i = 0; i < df->num_items; i++)
-		mem_free(df->items[i].data);
-
-	
-	io_close(df->file);
-	mem_free(df);
-
-	if(DEBUG)
-		dbg_msg("datafile", "done");
-	return 0;
-}
-
-#define BUFFER_SIZE 64*1024
-
-int datafile_crc(const char *filename)
-{
-	unsigned char buffer[BUFFER_SIZE];
-	IOHANDLE file;
-	int crc = 0;
-	unsigned bytes = 0;
-	
-	file = engine_openfile(filename, IOFLAG_READ);
-	if(!file)
-		return 0;
-		
-	while(1)
-	{
-		bytes = io_read(file, buffer, BUFFER_SIZE);
-		if(bytes <= 0)
-			break;
-		crc = crc32(crc, buffer, bytes);
-	}
-	
-	io_close(file);
-
-	return crc;	
-}
diff --git a/src/engine/e_datafile.h b/src/engine/e_datafile.h
deleted file mode 100644
index 203f415c..00000000
--- a/src/engine/e_datafile.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-
-/* raw datafile access */
-typedef struct DATAFILE_t DATAFILE;
-
-/* read access */
-DATAFILE *datafile_load(const char *filename);
-DATAFILE *datafile_load_old(const char *filename);
-void *datafile_get_data(DATAFILE *df, int index);
-void *datafile_get_data_swapped(DATAFILE *df, int index); /* makes sure that the data is 32bit LE ints when saved */
-int datafile_get_datasize(DATAFILE *df, int index);
-void datafile_unload_data(DATAFILE *df, int index);
-void *datafile_get_item(DATAFILE *df, int index, int *type, int *id);
-int datafile_get_itemsize(DATAFILE *df, int index);
-void datafile_get_type(DATAFILE *df, int type, int *start, int *num);
-void *datafile_find_item(DATAFILE *df, int type, int id);
-int datafile_num_items(DATAFILE *df);
-int datafile_num_data(DATAFILE *df);
-void datafile_unload(DATAFILE *df);
-
-int datafile_crc(const char *filename);
-
-/* write access */
-typedef struct DATAFILE_OUT_t DATAFILE_OUT;
-DATAFILE_OUT *datafile_create(const char *filename);
-int datafile_add_data(DATAFILE_OUT *df, int size, void *data);
-int datafile_add_data_swapped(DATAFILE_OUT *df, int size, void *data);
-int datafile_add_item(DATAFILE_OUT *df, int type, int id, int size, void *data);
-int datafile_finish(DATAFILE_OUT *df);
diff --git a/src/engine/e_demorec.cpp b/src/engine/e_demorec.cpp
deleted file mode 100644
index 1bab1b8d..00000000
--- a/src/engine/e_demorec.cpp
+++ /dev/null
@@ -1,640 +0,0 @@
-#include <base/system.h>
-#include "e_demorec.h"
-#include "e_memheap.h"
-#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;
-static const unsigned char header_marker[8] = {'T', 'W', 'D', 'E', 'M', 'O', 0, 1};
-
-/* Record */
-static int record_lasttickmarker = -1;
-static int record_lastkeyframe;
-static unsigned char record_lastsnapshotdata[CSnapshot::MAX_SIZE];
-
-int demorec_isrecording() { return record_file != 0; }
-
-int demorec_record_start(const char *filename, const char *netversion, const char *map, int crc, const char *type)
-{
-	DEMOREC_HEADER header;
-	if(record_file)
-		return -1;
-
-	record_file = engine_openfile(filename, IOFLAG_WRITE);
-	
-	if(!record_file)
-	{
-		dbg_msg("demorec/record", "Unable to open '%s' for recording", filename);
-		return -1;
-	}
-	
-	/* write header */
-	mem_zero(&header, sizeof(header));
-	mem_copy(header.marker, header_marker, sizeof(header.marker));
-	str_copy(header.netversion, netversion, sizeof(header.netversion));
-	str_copy(header.map, map, sizeof(header.map));
-	str_copy(header.type, type, sizeof(header.type));
-	header.crc[0] = (crc>>24)&0xff;
-	header.crc[1] = (crc>>16)&0xff;
-	header.crc[2] = (crc>>8)&0xff;
-	header.crc[3] = (crc)&0xff;
-	io_write(record_file, &header, sizeof(header));
-	
-	record_lastkeyframe = -1;
-	record_lasttickmarker = -1;
-	
-	dbg_msg("demorec/record", "Recording to '%s'", filename);
-	return 0;
-}
-
-/*
-	Tickmarker
-		7   = Always set
-		6   = Keyframe flag
-		0-5 = Delta tick
-	
-	Normal
-		7   = Not set
-		5-6 = Type
-		0-4 = Size
-*/
-
-enum
-{
-	CHUNKTYPEFLAG_TICKMARKER = 0x80,
-	CHUNKTICKFLAG_KEYFRAME = 0x40, /* only when tickmarker is set*/
-	
-	CHUNKMASK_TICK = 0x3f,
-	CHUNKMASK_TYPE = 0x60,
-	CHUNKMASK_SIZE = 0x1f,
-	
-	CHUNKTYPE_SNAPSHOT = 1,
-	CHUNKTYPE_MESSAGE = 2,
-	CHUNKTYPE_DELTA = 3,
-
-	CHUNKFLAG_BIGSIZE = 0x10
-};
-
-static void demorec_record_write_tickmarker(int tick, int keyframe)
-{
-	if(record_lasttickmarker == -1 || tick-record_lasttickmarker > 63 || keyframe)
-	{
-		unsigned char chunk[5];
-		chunk[0] = CHUNKTYPEFLAG_TICKMARKER;
-		chunk[1] = (tick>>24)&0xff;
-		chunk[2] = (tick>>16)&0xff;
-		chunk[3] = (tick>>8)&0xff;
-		chunk[4] = (tick)&0xff;
-
-		if(keyframe)
-			chunk[0] |= CHUNKTICKFLAG_KEYFRAME;
-		
-		io_write(record_file, chunk, sizeof(chunk));
-	}
-	else
-	{
-		unsigned char chunk[1];
-		chunk[0] = CHUNKTYPEFLAG_TICKMARKER | (tick-record_lasttickmarker);
-		io_write(record_file, chunk, sizeof(chunk));
-	}	
-
-	record_lasttickmarker = tick;
-}
-
-static void demorec_record_write(int type, const void *data, int size)
-{
-	char buffer[64*1024];
-	char buffer2[64*1024];
-	unsigned char chunk[3];
-	
-	if(!record_file)
-		return;
-
-	
-	/* pad the data with 0 so we get an alignment of 4,
-	else the compression won't work and miss some bytes */
-	mem_copy(buffer2, data, size);
-	while(size&3)
-		buffer2[size++] = 0;
-	size = intpack_compress(buffer2, size, buffer); /* buffer2 -> buffer */
-	size = CNetBase::Compress(buffer, size, buffer2, sizeof(buffer2)); /* buffer -> buffer2 */
-	
-	
-	chunk[0] = ((type&0x3)<<5);
-	if(size < 30)
-	{
-		chunk[0] |= size;
-		io_write(record_file, chunk, 1);
-	}
-	else
-	{
-		if(size < 256)
-		{
-			chunk[0] |= 30;
-			chunk[1] = size&0xff;
-			io_write(record_file, chunk, 2);
-		}
-		else
-		{
-			chunk[0] |= 31;
-			chunk[1] = size&0xff;
-			chunk[2] = size>>8;
-			io_write(record_file, chunk, 3);
-		}
-	}
-	
-	io_write(record_file, buffer2, size);
-}
-
-void demorec_record_snapshot(int tick, const void *data, int size)
-{
-	if(record_lastkeyframe == -1 || (tick-record_lastkeyframe) > SERVER_TICK_SPEED*5)
-	{
-		/* write full tickmarker */
-		demorec_record_write_tickmarker(tick, 1);
-		
-		/* write snapshot */
-		demorec_record_write(CHUNKTYPE_SNAPSHOT, data, size);
-			
-		record_lastkeyframe = tick;
-		mem_copy(record_lastsnapshotdata, data, size);
-	}
-	else
-	{
-		/* create delta, prepend tick */
-		char delta_data[CSnapshot::MAX_SIZE+sizeof(int)];
-		int delta_size;
-
-		/* write tickmarker */
-		demorec_record_write_tickmarker(tick, 0);
-		
-		delta_size = CSnapshot::CreateDelta((CSnapshot*)record_lastsnapshotdata, (CSnapshot*)data, &delta_data);
-		if(delta_size)
-		{
-			/* record delta */
-			demorec_record_write(CHUNKTYPE_DELTA, delta_data, delta_size);
-			mem_copy(record_lastsnapshotdata, data, size);
-		}
-	}
-}
-
-void demorec_record_message(const void *data, int size)
-{
-	demorec_record_write(CHUNKTYPE_MESSAGE, data, size);
-}
-
-int demorec_record_stop()
-{
-	if(!record_file)
-		return -1;
-		
-	dbg_msg("demorec/record", "Stopped recording");
-	io_close(record_file);
-	record_file = 0;
-	return 0;
-}
-
-/* Playback */
-typedef struct KEYFRAME
-{
-	long filepos;
-	int tick;
-} KEYFRAME;
-
-typedef struct KEYFRAME_SEARCH
-{
-	KEYFRAME frame;
-	struct KEYFRAME_SEARCH *next;
-} KEYFRAME_SEARCH;
-
-static IOHANDLE play_file = 0;
-static DEMOREC_PLAYCALLBACK play_callback_snapshot = 0;
-static DEMOREC_PLAYCALLBACK play_callback_message = 0;
-static KEYFRAME *keyframes = 0;
-
-static DEMOREC_PLAYBACKINFO playbackinfo;
-static unsigned char playback_lastsnapshotdata[CSnapshot::MAX_SIZE];
-static int playback_lastsnapshotdata_size = -1;
-
-
-const DEMOREC_PLAYBACKINFO *demorec_playback_info() { return &playbackinfo; }
-int demorec_isplaying() { return play_file != 0; }
-
-int demorec_playback_registercallbacks(DEMOREC_PLAYCALLBACK snapshot_cb, DEMOREC_PLAYCALLBACK message_cb)
-{
-	play_callback_snapshot = snapshot_cb;
-	play_callback_message = message_cb;
-	return 0;
-}
-
-static int read_chunk_header(int *type, int *size, int *tick)
-{
-	unsigned char chunk = 0;
-	
-	*size = 0;
-	*type = 0;
-	
-	if(io_read(play_file, &chunk, sizeof(chunk)) != sizeof(chunk))
-		return -1;
-		
-	if(chunk&CHUNKTYPEFLAG_TICKMARKER)
-	{
-		/* decode tick marker */
-		int tickdelta = chunk&(CHUNKMASK_TICK);
-		*type = chunk&(CHUNKTYPEFLAG_TICKMARKER|CHUNKTICKFLAG_KEYFRAME);
-		
-		if(tickdelta == 0)
-		{
-			unsigned char tickdata[4];
-			if(io_read(play_file, tickdata, sizeof(tickdata)) != sizeof(tickdata))
-				return -1;
-			*tick = (tickdata[0]<<24) | (tickdata[1]<<16) | (tickdata[2]<<8) | tickdata[3];
-		}
-		else
-		{
-			*tick += tickdelta;
-		}
-		
-	}
-	else
-	{
-		/* decode normal chunk */
-		*type = (chunk&CHUNKMASK_TYPE)>>5;
-		*size = chunk&CHUNKMASK_SIZE;
-		
-		if(*size == 30)
-		{
-			unsigned char sizedata[1];
-			if(io_read(play_file, sizedata, sizeof(sizedata)) != sizeof(sizedata))
-				return -1;
-			*size = sizedata[0];
-			
-		}
-		else if(*size == 31)
-		{
-			unsigned char sizedata[2];
-			if(io_read(play_file, sizedata, sizeof(sizedata)) != sizeof(sizedata))
-				return -1;
-			*size = (sizedata[1]<<8) | sizedata[0];
-		}
-	}
-	
-	return 0;
-}
-
-static void scan_file()
-{
-	long start_pos;
-	HEAP *heap = 0;
-	KEYFRAME_SEARCH *first_key = 0;
-	KEYFRAME_SEARCH *current_key = 0;
-	/*DEMOREC_CHUNK chunk;*/
-	int chunk_size, chunk_type, chunk_tick = 0;
-	int i;
-	
-	heap = memheap_create();
-
-	start_pos = io_tell(play_file);
-	playbackinfo.seekable_points = 0;
-
-	while(1)
-	{
-		long current_pos = io_tell(play_file);
-		
-		if(read_chunk_header(&chunk_type, &chunk_size, &chunk_tick))
-			break;
-			
-		/* read the chunk */
-		if(chunk_type&CHUNKTYPEFLAG_TICKMARKER)
-		{
-			if(chunk_type&CHUNKTICKFLAG_KEYFRAME)
-			{
-				KEYFRAME_SEARCH *key;
-				
-				/* save the position */
-				key = (KEYFRAME_SEARCH *)memheap_allocate(heap, sizeof(KEYFRAME_SEARCH));
-				key->frame.filepos = current_pos;
-				key->frame.tick = chunk_tick;
-				key->next = 0;
-				if(current_key)
-					current_key->next = key;
-				if(!first_key)
-					first_key = key;
-				current_key = key;
-				playbackinfo.seekable_points++;
-			}
-			
-			if(playbackinfo.first_tick == -1)
-				playbackinfo.first_tick = chunk_tick;
-			playbackinfo.last_tick = chunk_tick;
-		}
-		else if(chunk_size)
-			io_skip(play_file, chunk_size);
-			
-	}
-
-	/* copy all the frames to an array instead for fast access */
-	keyframes = (KEYFRAME*)mem_alloc(playbackinfo.seekable_points*sizeof(KEYFRAME), 1);
-	for(current_key = first_key, i = 0; current_key; current_key = current_key->next, i++)
-		keyframes[i] = current_key->frame;
-		
-	/* destroy the temporary heap and seek back to the start */
-	memheap_destroy(heap);
-	io_seek(play_file, start_pos, IOSEEK_START);
-}
-
-static void do_tick()
-{
-	static char compresseddata[CSnapshot::MAX_SIZE];
-	static char decompressed[CSnapshot::MAX_SIZE];
-	static char data[CSnapshot::MAX_SIZE];
-	int chunk_type, chunk_tick, chunk_size;
-	int data_size;
-	int got_snapshot = 0;
-
-	/* update ticks */
-	playbackinfo.previous_tick = playbackinfo.current_tick;
-	playbackinfo.current_tick = playbackinfo.next_tick;
-	chunk_tick = playbackinfo.current_tick;
-
-	while(1)
-	{
-		if(read_chunk_header(&chunk_type, &chunk_size, &chunk_tick))
-		{
-			/* stop on error or eof */
-			dbg_msg("demorec", "end of file");
-			demorec_playback_pause();
-			break;
-		}
-		
-		/* read the chunk */
-		if(chunk_size)
-		{
-			if(io_read(play_file, compresseddata, chunk_size) != (unsigned)chunk_size)
-			{
-				/* stop on error or eof */
-				dbg_msg("demorec", "error reading chunk");
-				demorec_playback_stop();
-				break;
-			}
-			
-			data_size = CNetBase::Decompress(compresseddata, chunk_size, decompressed, sizeof(decompressed));
-			if(data_size < 0)
-			{
-				/* stop on error or eof */
-				dbg_msg("demorec", "error during network decompression");
-				demorec_playback_stop();
-				break;
-			}
-			
-			data_size = intpack_decompress(decompressed, data_size, data);
-
-			if(data_size < 0)
-			{
-				dbg_msg("demorec", "error during intpack decompression");
-				demorec_playback_stop();
-				break;
-			}
-		}
-			
-		if(chunk_type == CHUNKTYPE_DELTA)
-		{
-			/* process delta snapshot */
-			static char newsnap[CSnapshot::MAX_SIZE];
-			
-			got_snapshot = 1;
-			
-			data_size = CSnapshot::UnpackDelta((CSnapshot*)playback_lastsnapshotdata, (CSnapshot*)newsnap, data, data_size);
-			
-			if(data_size >= 0)
-			{
-				if(play_callback_snapshot)
-					play_callback_snapshot(newsnap, data_size);
-
-				playback_lastsnapshotdata_size = data_size;
-				mem_copy(playback_lastsnapshotdata, newsnap, data_size);
-			}
-			else
-				dbg_msg("demorec", "error duing unpacking of delta, err=%d", data_size);
-		}
-		else if(chunk_type == CHUNKTYPE_SNAPSHOT)
-		{
-			/* process full snapshot */
-			got_snapshot = 1;
-			
-			playback_lastsnapshotdata_size = data_size;
-			mem_copy(playback_lastsnapshotdata, data, data_size);
-			if(play_callback_snapshot)
-				play_callback_snapshot(data, data_size);
-		}
-		else
-		{
-			/* if there were no snapshots in this tick, replay the last one */
-			if(!got_snapshot && play_callback_snapshot && playback_lastsnapshotdata_size != -1)
-			{
-				got_snapshot = 1;
-				play_callback_snapshot(playback_lastsnapshotdata, playback_lastsnapshotdata_size);
-			}
-			
-			/* check the remaining types */
-			if(chunk_type&CHUNKTYPEFLAG_TICKMARKER)
-			{
-				playbackinfo.next_tick = chunk_tick;
-				break;
-			}
-			else if(chunk_type == CHUNKTYPE_MESSAGE)
-			{
-				if(play_callback_message)
-					play_callback_message(data, data_size);
-			}
-		}
-	}
-}
-
-void demorec_playback_pause()
-{
-	playbackinfo.paused = 1;
-}
-
-void demorec_playback_unpause()
-{
-	if(playbackinfo.paused)
-	{
-		/*playbackinfo.start_tick = playbackinfo.current_tick;
-		playbackinfo.start_time = time_get();*/
-		playbackinfo.paused = 0;
-	}
-}
-
-int demorec_playback_load(const char *filename)
-{
-	play_file = engine_openfile(filename, IOFLAG_READ);
-	if(!play_file)
-	{
-		dbg_msg("demorec/playback", "could not open '%s'", filename);
-		return -1;
-	}
-	
-	/* clear the playback info */
-	mem_zero(&playbackinfo, sizeof(playbackinfo));
-	playbackinfo.first_tick = -1;
-	playbackinfo.last_tick = -1;
-	/*playbackinfo.start_tick = -1;*/
-	playbackinfo.next_tick = -1;
-	playbackinfo.current_tick = -1;
-	playbackinfo.previous_tick = -1;
-	playbackinfo.speed = 1;
-	
-	playback_lastsnapshotdata_size = -1;
-
-	/* read the header */	
-	io_read(play_file, &playbackinfo.header, sizeof(playbackinfo.header));
-	if(mem_comp(playbackinfo.header.marker, header_marker, sizeof(header_marker)) != 0)
-	{
-		dbg_msg("demorec/playback", "'%s' is not a demo file", filename);
-		io_close(play_file);
-		play_file = 0;
-		return -1;
-	}
-	
-	/* scan the file for interessting points */
-	scan_file();
-	
-	/* ready for playback */	
-	return 0;
-}
-
-int demorec_playback_nextframe()
-{
-	do_tick();
-	return demorec_isplaying();
-}
-
-int demorec_playback_play()
-{
-	/* fill in previous and next tick */
-	while(playbackinfo.previous_tick == -1 && demorec_isplaying())
-		do_tick();
-		
-	/* set start info */
-	/*playbackinfo.start_tick = playbackinfo.previous_tick;
-	playbackinfo.start_time = time_get();*/
-	playbackinfo.current_time = playbackinfo.previous_tick*time_freq()/SERVER_TICK_SPEED;
-	playbackinfo.last_update = time_get();
-	return 0;
-}
-
-int demorec_playback_set(float percent)
-{
-	int keyframe;
-	int wanted_tick;
-	if(!play_file)
-		return -1;
-	
-	/* -5 because we have to have a current tick and previous tick when we do the playback */
-	wanted_tick = playbackinfo.first_tick + (int)((playbackinfo.last_tick-playbackinfo.first_tick)*percent) - 5;
-	
-	keyframe = (int)(playbackinfo.seekable_points*percent);
-
-	if(keyframe < 0 || keyframe >= playbackinfo.seekable_points)
-		return -1;
-	
-	/* get correct key frame */
-	if(keyframes[keyframe].tick < wanted_tick)
-		while(keyframe < playbackinfo.seekable_points-1 && keyframes[keyframe].tick < wanted_tick)
-			keyframe++;
-
-	while(keyframe && keyframes[keyframe].tick > wanted_tick)
-		keyframe--;
-	
-	/* seek to the correct keyframe */
-	io_seek(play_file, keyframes[keyframe].filepos, IOSEEK_START);
-
-	/*playbackinfo.start_tick = -1;*/
-	playbackinfo.next_tick = -1;
-	playbackinfo.current_tick = -1;
-	playbackinfo.previous_tick = -1;
-
-	/* playback everything until we hit our tick */
-	while(playbackinfo.previous_tick < wanted_tick)
-		do_tick();
-	
-	demorec_playback_play();
-	
-	return 0;
-}
-
-void demorec_playback_setspeed(float speed)
-{
-	playbackinfo.speed = speed;
-}
-
-int demorec_playback_update()
-{
-	int64 now = time_get();
-	int64 deltatime = now-playbackinfo.last_update;
-	playbackinfo.last_update = now;
-	
-	if(!demorec_isplaying())
-		return 0;
-	
-	if(playbackinfo.paused)
-	{
-		
-	}
-	else
-	{
-		int64 freq = time_freq();
-		playbackinfo.current_time += (int64)(deltatime*(double)playbackinfo.speed);
-		
-		while(1)
-		{
-			int64 curtick_start = (playbackinfo.current_tick)*freq/SERVER_TICK_SPEED;
-
-			/* break if we are ready */		
-			if(curtick_start > playbackinfo.current_time)
-				break;
-			
-			/* do one more tick */
-			do_tick();
-			
-			if(playbackinfo.paused)
-				return 0;
-		}
-
-		/* update intratick */
-		{	
-			int64 curtick_start = (playbackinfo.current_tick)*freq/SERVER_TICK_SPEED;
-			int64 prevtick_start = (playbackinfo.previous_tick)*freq/SERVER_TICK_SPEED;
-			playbackinfo.intratick = (playbackinfo.current_time - prevtick_start) / (float)(curtick_start-prevtick_start);
-			playbackinfo.ticktime = (playbackinfo.current_time - prevtick_start) / (float)freq;
-		}
-		
-		if(playbackinfo.current_tick == playbackinfo.previous_tick ||
-			playbackinfo.current_tick == playbackinfo.next_tick)
-		{
-			dbg_msg("demorec/playback", "tick error prev=%d cur=%d next=%d",
-				playbackinfo.previous_tick, playbackinfo.current_tick, playbackinfo.next_tick);
-		}
-	}
-	
-	return 0;
-}
-
-int demorec_playback_stop()
-{
-	if(!play_file)
-		return -1;
-		
-	dbg_msg("demorec/playback", "Stopped playback");
-	io_close(play_file);
-	play_file = 0;
-	mem_free(keyframes);
-	keyframes = 0;
-	return 0;
-}
-
-
diff --git a/src/engine/e_demorec.h b/src/engine/e_demorec.h
deleted file mode 100644
index 9716b463..00000000
--- a/src/engine/e_demorec.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef _DEMOREC_H
-#define _DEMOREC_H
-
-typedef struct DEMOREC_HEADER
-{
-	char marker[8];
-	char netversion[64];
-	char map[64];
-	unsigned char crc[4];
-	char type[8];
-} DEMOREC_HEADER;
-
-typedef struct DEMOREC_CHUNK
-{
-	char type[2];
-	unsigned short size;
-} DEMOREC_CHUNK;
-
-typedef struct DEMOREC_TICKMARKER
-{
-	int tick;
-} DEMOREC_TICKMARKER;
-
-typedef struct DEMOREC_PLAYBACKINFO
-{
-	DEMOREC_HEADER header;
-	
-	int paused;
-	float speed;
-	
-	int64 last_update;
-	int64 current_time;
-	
-	int first_tick;
-	int last_tick;
-	
-	int seekable_points;
-	
-	int next_tick;
-	int current_tick;
-	int previous_tick;
-	
-	float intratick;
-	float ticktime;
-} DEMOREC_PLAYBACKINFO;
-
-int demorec_record_start(const char *filename, const char *netversion, const char *map, int map_crc, const char *type);
-int demorec_isrecording();
-void demorec_record_snapshot(int tick, const void *data, int size);
-void demorec_record_message(const void *data, int size);
-int demorec_record_stop();
-
-typedef void (*DEMOREC_PLAYCALLBACK)(void *data, int size);
-
-int demorec_playback_registercallbacks(DEMOREC_PLAYCALLBACK snapshot_cb, DEMOREC_PLAYCALLBACK message_cb);
-int demorec_playback_load(const char *filename);
-int demorec_playback_nextframe();
-int demorec_playback_play();
-void demorec_playback_pause();
-void demorec_playback_unpause();
-void demorec_playback_setspeed(float speed);
-int demorec_playback_set(float precent);
-int demorec_playback_update();
-const DEMOREC_PLAYBACKINFO *demorec_playback_info();
-int demorec_isplaying();
-int demorec_playback_stop();
-
-#endif
diff --git a/src/engine/e_engine.cpp b/src/engine/e_engine.cpp
deleted file mode 100644
index 4475478a..00000000
--- a/src/engine/e_engine.cpp
+++ /dev/null
@@ -1,596 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <base/system.h>
-
-#include <engine/e_server_interface.h>
-#include <engine/e_config.h>
-#include <engine/e_console.h>
-#include <engine/e_engine.h>
-#include <engine/e_network.h>
-#include "e_linereader.h"
-
-/* compiled-in data-dir path */
-#define DATA_DIR "data"
-
-static JOBPOOL hostlookuppool;
-static int engine_find_datadir(char *argv0);
-
-static void con_dbg_dumpmem(void *result, void *user_data)
-{
-	mem_debug_dump();
-}
-
-static void con_dbg_lognetwork(void *result, void *user_data)
-{
-	CNetBase::OpenLog("network_sent.dat", "network_recv.dat");
-}
-
-
-static char application_save_path[512] = {0};
-static char datadir[512] = {0};
-
-const char *engine_savepath(const char *filename, char *buffer, int max)
-{
-	str_format(buffer, max, "%s/%s", application_save_path, filename);
-	return buffer;
-}
-
-void engine_init(const char *appname)
-{
-	dbg_logger_stdout();
-	dbg_logger_debugger();
-	
-	/* */
-	dbg_msg("engine", "running on %s-%s-%s", CONF_FAMILY_STRING, CONF_PLATFORM_STRING, CONF_ARCH_STRING);
-#ifdef CONF_ARCH_ENDIAN_LITTLE
-	dbg_msg("engine", "arch is little endian");
-#elif defined(CONF_ARCH_ENDIAN_BIG)
-	dbg_msg("engine", "arch is big endian");
-#else
-	dbg_msg("engine", "unknown endian");
-#endif
-
-	/* init the network */
-	net_init();
-	CNetBase::Init();
-	
-	/* create storage location */
-	{
-		char path[1024] = {0};
-		fs_storage_path(appname, application_save_path, sizeof(application_save_path));
-		if(fs_makedir(application_save_path) == 0)
-		{		
-			str_format(path, sizeof(path), "%s/screenshots", application_save_path);
-			fs_makedir(path);
-
-			str_format(path, sizeof(path), "%s/maps", application_save_path);
-			fs_makedir(path);
-
-			str_format(path, sizeof(path), "%s/downloadedmaps", application_save_path);
-			fs_makedir(path);
-
-			str_format(path, sizeof(path), "%s/demos", application_save_path);
-			fs_makedir(path);
-		}
-	}
-
-	/* init console and add the console logger */
-	console_init();
-	dbg_logger(console_print);
-	
-	jobs_initpool(&hostlookuppool, 1);
-
-	MACRO_REGISTER_COMMAND("dbg_dumpmem", "", CFGFLAG_SERVER|CFGFLAG_CLIENT, con_dbg_dumpmem, 0x0, "Dump the memory");
-	MACRO_REGISTER_COMMAND("dbg_lognetwork", "", CFGFLAG_SERVER|CFGFLAG_CLIENT, con_dbg_lognetwork, 0x0, "Log the network");
-	
-	/* reset the config */
-	config_reset();
-}
-
-
-void engine_listdir(int types, const char *path, FS_LISTDIR_CALLBACK cb, void *user)
-{
-	char buffer[1024];
-	
-	/* list current directory */
-	if(types&LISTDIRTYPE_CURRENT)
-	{
-		fs_listdir(path, cb, user);
-	}
-	
-	/* list users directory */
-	if(types&LISTDIRTYPE_SAVE)
-	{
-		engine_savepath(path, buffer, sizeof(buffer));
-		fs_listdir(buffer, cb, user);
-	}
-	
-	/* list datadir directory */
-	if(types&LISTDIRTYPE_DATA)
-	{
-		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;
-	
-	/* check for datadir override */
-	for(i = 1; i < argc; i++)
-	{
-		if(argv[i][0] == '-' && argv[i][1] == 'd' && argv[i][2] == 0 && argc - i > 1)
-		{
-			str_copy(datadir, argv[i+1], sizeof(datadir));
-			i++;
-		}
-	}
-	
-	/* 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)
-		{
-			console_execute_file(argv[i+1]);
-			i++;
-		}
-	}
-
-	/* search arguments for overrides */
-	{
-		int i;
-		for(i = 1; i < argc; i++)
-			console_execute_line(argv[i]);
-	}
-
-	console_execute_file("autoexec.cfg");
-
-	/* open logfile if needed */
-	if(config.logfile[0])
-		dbg_logger_file(config.logfile);
-
-	/* set default servers and load from disk*/
-	mastersrv_default();
-	mastersrv_load();
-}
-
-
-static IOHANDLE config_file = 0;
-
-int engine_config_write_start()
-{
-	config_save();
-	config_file = engine_openfile("settings.cfg", IOFLAG_WRITE);
-	if(config_file == 0)
-		return -1;
-	return 0;
-}
-
-void engine_config_write_line(const char *line)
-{
-	if(config_file)
-	{
-#if defined(CONF_FAMILY_WINDOWS)
-		static const char newline[] = "\r\n";
-#else
-		static const char newline[] = "\n";
-#endif
-		io_write(config_file, line, strlen(line));
-		io_write(config_file, newline, sizeof(newline)-1);
-	}
-}
-
-void engine_config_write_stop()
-{
-	io_close(config_file);
-	config_file = 0;
-}
-/*
-void engine_writeconfig()
-{
-}*/
-
-static int perf_tick = 1;
-static PERFORMACE_INFO *current = 0;
-
-void perf_init()
-{
-}
-
-void perf_next()
-{
-	perf_tick++;
-	current = 0;
-}
-
-void perf_start(PERFORMACE_INFO *info)
-{
-	if(info->tick != perf_tick)
-	{
-		info->parent = current;
-		info->first_child = 0;
-		info->next_child = 0;
-		
-		if(info->parent)
-		{
-			info->next_child = info->parent->first_child;
-			info->parent->first_child = info;
-		}
-		
-		info->tick = perf_tick;
-		info->biggest = 0;
-		info->total = 0;
-	}
-	
-	current = info;
-	current->start = time_get();
-}
-
-void perf_end()
-{
-	if(!current)
-		return;
-		
-	current->last_delta = time_get()-current->start;
-	current->total += current->last_delta;
-	
-	if(current->last_delta > current->biggest)
-		current->biggest = current->last_delta;
-	
-	current = current->parent;
-}
-
-static void perf_dump_imp(PERFORMACE_INFO *info, int indent)
-{
-	char buf[512] = {0};
-	int64 freq = time_freq();
-	int i;
-	
-	for(i = 0; i < indent; i++)
-		buf[i] = ' ';
-	
-	str_format(&buf[indent], sizeof(buf)-indent, "%-20s %8.2f %8.2f", info->name, info->total*1000/(float)freq, info->biggest*1000/(float)freq);
-	dbg_msg("perf", "%s", buf);
-	
-	info = info->first_child;
-	while(info)
-	{
-		perf_dump_imp(info, indent+2);
-		info = info->next_child;
-	}
-}
-
-void perf_dump(PERFORMACE_INFO *top)
-{
-	perf_dump_imp(top, 0);
-}
-
-/* master server functions */
-typedef struct
-{
-	char hostname[128];
-	NETADDR addr;
-	
-	HOSTLOOKUP lookup;
-} MASTER_INFO;
-
-static MASTER_INFO master_servers[MAX_MASTERSERVERS] = {{{0}}};
-static int needs_update = -1;
-
-int mastersrv_refresh_addresses()
-{
-	int i;
-	
-	if(needs_update != -1)
-		return 0;
-	
-	dbg_msg("engine/mastersrv", "refreshing master server addresses");
-
-	/* add lookup jobs */
-	for(i = 0; i < MAX_MASTERSERVERS; i++)	
-		engine_hostlookup(&master_servers[i].lookup, master_servers[i].hostname);
-	
-	needs_update = 1;
-	return 0;
-}
-
-void mastersrv_update()
-{
-	int i;
-	
-	/* check if we need to update */
-	if(needs_update != 1)
-		return;
-	needs_update = 0;
-	
-	for(i = 0; i < MAX_MASTERSERVERS; i++)
-	{
-		if(jobs_status(&master_servers[i].lookup.job) != JOBSTATUS_DONE)
-			needs_update = 1;
-		else
-		{
-			master_servers[i].addr = master_servers[i].lookup.addr;
-			master_servers[i].addr.port = 8300;
-		}
-	}
-	
-	if(!needs_update)
-	{
-		dbg_msg("engine/mastersrv", "saving addresses");
-		mastersrv_save();
-	}
-}
-
-int mastersrv_refreshing()
-{
-	return needs_update;
-}
-
-NETADDR mastersrv_get(int index) 
-{
-	return master_servers[index].addr;
-}
-
-const char *mastersrv_name(int index) 
-{
-	return master_servers[index].hostname;
-}
-
-void mastersrv_dump_servers()
-{
-	int i;
-	for(i = 0; i < MAX_MASTERSERVERS; i++)
-	{
-		dbg_msg("mastersrv", "#%d = %d.%d.%d.%d", i,
-			master_servers[i].addr.ip[0], master_servers[i].addr.ip[1],
-			master_servers[i].addr.ip[2], master_servers[i].addr.ip[3]);
-	}
-}
-
-void mastersrv_default()
-{
-	int i;
-	mem_zero(master_servers, sizeof(master_servers));
-	for(i = 0; i < MAX_MASTERSERVERS; i++)
-		sprintf(master_servers[i].hostname, "master%d.teeworlds.com", i+1);
-}
-
-int mastersrv_load()
-{
-	LINEREADER lr;
-	IOHANDLE file;
-	int count = 0;
-	
-	/* try to open file */
-	file = engine_openfile("masters.cfg", IOFLAG_READ);
-	if(!file)
-		return -1;
-	
-	linereader_init(&lr, file);
-	while(1)
-	{
-		MASTER_INFO info = {{0}};
-		int ip[4];
-		const char *line = linereader_get(&lr);
-		if(!line)
-			break;
-
-		/* parse line */		
-		if(sscanf(line, "%s %d.%d.%d.%d", info.hostname, &ip[0], &ip[1], &ip[2], &ip[3]) == 5)
-		{
-			info.addr.ip[0] = (unsigned char)ip[0];
-			info.addr.ip[1] = (unsigned char)ip[1];
-			info.addr.ip[2] = (unsigned char)ip[2];
-			info.addr.ip[3] = (unsigned char)ip[3];
-			info.addr.port = 8300;
-			if(count != MAX_MASTERSERVERS)
-			{
-				master_servers[count] = info;
-				count++;
-			}
-			else
-				dbg_msg("engine/mastersrv", "warning: skipped master server '%s' due to limit of %d", line, MAX_MASTERSERVERS);
-		}
-		else
-			dbg_msg("engine/mastersrv", "warning: couldn't parse master server '%s'", line);
-	}
-	
-	io_close(file);
-	return 0;
-}
-
-int mastersrv_save()
-{
-	IOHANDLE file;
-	int i;
-
-	/* try to open file */
-	file = engine_openfile("masters.cfg", IOFLAG_WRITE);
-	if(!file)
-		return -1;
-
-	for(i = 0; i < MAX_MASTERSERVERS; i++)
-	{
-		char buf[1024];
-		str_format(buf, sizeof(buf), "%s %d.%d.%d.%d\n", master_servers[i].hostname,
-			master_servers[i].addr.ip[0], master_servers[i].addr.ip[1],
-			master_servers[i].addr.ip[2], master_servers[i].addr.ip[3]);
-			
-		io_write(file, buf, strlen(buf));
-	}
-	
-	io_close(file);
-	return 0;
-}
-
-
-int hostlookup_thread(void *user)
-{
-	HOSTLOOKUP *lookup = (HOSTLOOKUP *)user;
-	net_host_lookup(lookup->hostname, &lookup->addr, NETTYPE_IPV4);
-	return 0;
-}
-
-void engine_hostlookup(HOSTLOOKUP *lookup, const char *hostname)
-{
-	str_copy(lookup->hostname, hostname, sizeof(lookup->hostname));
-	jobs_add(&hostlookuppool, &lookup->job, hostlookup_thread, lookup);
-}
-
-static int engine_find_datadir(char *argv0)
-{
-	/* 1) use provided data-dir override */
-	if(datadir[0])
-	{
-		if(fs_is_dir(datadir))
-			return 0;
-		else
-		{
-			dbg_msg("engine/datadir", "specified data-dir '%s' does not exist", datadir);
-			return -1;
-		}
-	}
-	
-	/* 2) use data-dir in PWD if present */
-	if(fs_is_dir("data"))
-	{
-		strcpy(datadir, "data");
-		return 0;
-	}
-	
-	/* 3) use compiled-in data-dir if present */
-	if (fs_is_dir(DATA_DIR))
-	{
-		strcpy(datadir, DATA_DIR);
-		return 0;
-	}
-	
-	/* 4) check for usable path in argv[0] */
-	{
-		unsigned int pos = strrchr(argv0, '/') - argv0;
-		
-		if (pos < sizeof(datadir))
-		{
-			char basedir[sizeof(datadir)];
-			strncpy(basedir, argv0, pos);
-			basedir[pos] = '\0';
-			str_format(datadir, sizeof(datadir), "%s/data", basedir);
-			
-			if (fs_is_dir(datadir))
-				return 0;
-		}
-	}
-	
-#if defined(CONF_FAMILY_UNIX)
-	/* 5) check for all default locations */
-	{
-		const char *sdirs[] = {
-			"/usr/share/teeworlds",
-			"/usr/local/share/teeworlds"
-			"/opt/teeworlds"
-		};
-		const int sdirs_count = sizeof(sdirs) / sizeof(sdirs[0]);
-		
-		int i;
-		for (i = 0; i < sdirs_count; i++)
-		{
-			if (fs_is_dir(sdirs[i]))
-			{
-				strcpy(datadir, sdirs[i]);
-				return 0;
-			}
-		}
-	}
-#endif
-	
-	/* 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
deleted file mode 100644
index 94d49171..00000000
--- a/src/engine/e_engine.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-
-#include "e_jobs.h"
-
-const char *engine_savepath(const char *filename, char *buffer, int max);
-void engine_init(const char *appname);
-void engine_parse_arguments(int argc, char **argv);
-
-int engine_config_write_start();
-void engine_config_write_line(const char *line);
-void engine_config_write_stop();
-
-
-enum
-{
-	LISTDIRTYPE_SAVE=1,
-	LISTDIRTYPE_CURRENT=2,
-	LISTDIRTYPE_DATA=4,
-	LISTDIRTYPE_ALL = ~0
-};
-
-void engine_listdir(int types, 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);
-
-typedef struct HOSTLOOKUP
-{
-	JOB job;
-	char hostname[128];
-	NETADDR addr;
-} HOSTLOOKUP;
-
-void engine_hostlookup(HOSTLOOKUP *lookup, const char *hostname);
-
-enum
-{
-	MAX_MASTERSERVERS=4
-};
-
-void mastersrv_default();
-int mastersrv_load();
-int mastersrv_save();
-
-int mastersrv_refresh_addresses();
-void mastersrv_update();
-int mastersrv_refreshing();
-void mastersrv_dump_servers();
-NETADDR mastersrv_get(int index);
-const char *mastersrv_name(int index);
diff --git a/src/engine/e_huffman.cpp b/src/engine/e_huffman.cpp
deleted file mode 100644
index 43914010..00000000
--- a/src/engine/e_huffman.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-#include <memory.h> /* memset */
-#include "e_huffman.h"
-
-typedef struct HUFFMAN_CONSTRUCT_NODE
-{
-	unsigned short node_id;
- 	int frequency;
-} HUFFMAN_CONSTRUCT_NODE;
-
-static void huffman_setbits_r(HUFFMAN_STATE *huff, HUFFMAN_NODE *node, int bits, int depth)
-{
-	if(node->leafs[1] != 0xffff)
-		huffman_setbits_r(huff, &huff->nodes[node->leafs[1]], bits|(1<<depth), depth+1);
-	if(node->leafs[0] != 0xffff)
-		huffman_setbits_r(huff, &huff->nodes[node->leafs[0]], bits, depth+1);
-		
-	if(node->num_bits)
-	{
-		node->bits = bits;
-		node->num_bits = depth;
-	}
-}
-
-/* TODO: this should be something faster, but it's enough for now */
-void bubblesort(HUFFMAN_CONSTRUCT_NODE **list, int size)
-{
-	int i, changed = 1;
-	HUFFMAN_CONSTRUCT_NODE *temp;
-	
-	while(changed)
-	{
-		changed = 0;
-		for(i = 0; i < size-1; i++)
-		{
-			if(list[i]->frequency < list[i+1]->frequency)
-			{
-				temp = list[i];
-				list[i] = list[i+1];
-				list[i+1] = temp;
-				changed = 1;
-			}
-		}
-	}
-}
-
-static void huffman_construct_tree(HUFFMAN_STATE *huff, const unsigned *frequencies)
-{
-	HUFFMAN_CONSTRUCT_NODE nodes_left_storage[HUFFMAN_MAX_SYMBOLS];
-	HUFFMAN_CONSTRUCT_NODE *nodes_left[HUFFMAN_MAX_SYMBOLS];
-	int num_nodes_left = HUFFMAN_MAX_SYMBOLS;
-	int i;
-
-	/* add the symbols */
-	for(i = 0; i < HUFFMAN_MAX_SYMBOLS; i++)
-	{
-		huff->nodes[i].num_bits = -1;
-		huff->nodes[i].symbol = i;
-		huff->nodes[i].leafs[0] = -1;
-		huff->nodes[i].leafs[1] = -1;
-
-		if(i == HUFFMAN_EOF_SYMBOL)
-			nodes_left_storage[i].frequency = 1;
-		else
-			nodes_left_storage[i].frequency = frequencies[i];
-		nodes_left_storage[i].node_id = i;
-		nodes_left[i] = &nodes_left_storage[i];
-
-	}
-	huff->num_nodes = HUFFMAN_MAX_SYMBOLS;
-	
-	/* construct the table */
-	while(num_nodes_left > 1)
-	{
-		/* we can't rely on stdlib's qsort for this, it can generate different results on different implementations */
-		bubblesort(nodes_left, num_nodes_left);
-		
-		huff->nodes[huff->num_nodes].num_bits = 0;
-		huff->nodes[huff->num_nodes].leafs[0] = nodes_left[num_nodes_left-1]->node_id;
-		huff->nodes[huff->num_nodes].leafs[1] = nodes_left[num_nodes_left-2]->node_id;
-		nodes_left[num_nodes_left-2]->node_id = huff->num_nodes;
-		nodes_left[num_nodes_left-2]->frequency = nodes_left[num_nodes_left-1]->frequency + nodes_left[num_nodes_left-2]->frequency;
-
-		huff->num_nodes++;
-		num_nodes_left--;
-	}
-
-	/* set start node */
-	huff->start_node = &huff->nodes[huff->num_nodes-1];
-	
-	/* build symbol bits */
-	huffman_setbits_r(huff, huff->start_node, 0, 0);
-}
-
-void huffman_init(HUFFMAN_STATE *huff, const unsigned *frequencies)
-{
-	int i;
-
-	/* make sure to cleanout every thing */
-	memset(huff, 0, sizeof(HUFFMAN_STATE));
-
-	/* construct the tree */
-	huffman_construct_tree(huff, frequencies);
-
-	/* build decode LUT */
-	for(i = 0; i < HUFFMAN_LUTSIZE; i++)
-	{
-		unsigned bits = i;
-		int k;
-		HUFFMAN_NODE *node = huff->start_node;
-		for(k = 0; k < HUFFMAN_LUTBITS; k++)
-		{
-			node = &huff->nodes[node->leafs[bits&1]];
-			bits >>= 1;
-
-			if(!node)
-				break;
-
-			if(node->num_bits)
-			{
-				huff->decode_lut[i] = node;
-				break;
-			}
-		}
-
-		if(k == HUFFMAN_LUTBITS)
-			huff->decode_lut[i] = node;
-	}
-
-}
-
-/*****************************************************************/
-int huffman_compress(HUFFMAN_STATE *huff, const void *input, int input_size, void *output, int output_size)
-{
-	/* this macro loads a symbol for a byte into bits and bitcount */
-#define HUFFMAN_MACRO_LOADSYMBOL(sym) \
-	bits |= huff->nodes[sym].bits << bitcount; \
-	bitcount += huff->nodes[sym].num_bits;
-
-	/* this macro writes the symbol stored in bits and bitcount to the dst pointer */
-#define HUFFMAN_MACRO_WRITE() \
-	while(bitcount >= 8) \
-	{ \
-		*dst++ = (unsigned char)(bits&0xff); \
-		if(dst == dst_end) \
-			return -1; \
-		bits >>= 8; \
-		bitcount -= 8; \
-	}
-
-	/* setup buffer pointers */
-	const unsigned char *src = (const unsigned char *)input;
-	const unsigned char *src_end = src + input_size;
-	unsigned char *dst = (unsigned char *)output;
-	unsigned char *dst_end = dst + output_size;
-
-	/* symbol variables */
-	unsigned bits = 0;
-	unsigned bitcount = 0;
-
-	/* make sure that we have data that we want to compress */
-	if(input_size)
-	{
-		/* {A} load the first symbol */
-		int symbol = *src++;
-
-		while(src != src_end)
-		{
-			/* {B} load the symbol */
-			HUFFMAN_MACRO_LOADSYMBOL(symbol)
-
-			/* {C} fetch next symbol, this is done here because it will reduce dependency in the code */
-			symbol = *src++;
-
-			/* {B} write the symbol loaded at */
-			HUFFMAN_MACRO_WRITE()
-		}
-
-		/* write the last symbol loaded from {C} or {A} in the case of only 1 byte input buffer */
-		HUFFMAN_MACRO_LOADSYMBOL(symbol)
-		HUFFMAN_MACRO_WRITE()
-	}
-
-	/* write EOF symbol */
-	HUFFMAN_MACRO_LOADSYMBOL(HUFFMAN_EOF_SYMBOL)
-	HUFFMAN_MACRO_WRITE()
-
-	/* write out the last bits */
-	*dst++ = bits;
-
-	/* return the size of the output */
-	return (int)(dst - (const unsigned char *)output);
-
-	/* remove macros */
-#undef HUFFMAN_MACRO_LOADSYMBOL
-#undef HUFFMAN_MACRO_WRITE
-}
-
-/*****************************************************************/
-int huffman_decompress(HUFFMAN_STATE *huff, const void *input, int input_size, void *output, int output_size)
-{
-	/* setup buffer pointers */
-	unsigned char *dst = (unsigned char *)output;
-	unsigned char *src = (unsigned char *)input;
-	unsigned char *dst_end = dst + output_size;
-	unsigned char *src_end = src + input_size;
-
-	unsigned bits = 0;
-	unsigned bitcount = 0;
-
-	HUFFMAN_NODE *eof = &huff->nodes[HUFFMAN_EOF_SYMBOL];
-	HUFFMAN_NODE *node = 0;
-
-	while(1)
-	{
-		/* {A} try to load a node now, this will reduce dependency at location {D} */
-		node = 0;
-		if(bitcount >= HUFFMAN_LUTBITS)
-			node = huff->decode_lut[bits&HUFFMAN_LUTMASK];
-
-		/* {B} fill with new bits */
-		while(bitcount < 24 && src != src_end)
-		{
-			bits |= (*src++) << bitcount;
-			bitcount += 8;
-		}
-
-		/* {C} load symbol now if we didn't that earlier at location {A} */
-		if(!node)
-			node = huff->decode_lut[bits&HUFFMAN_LUTMASK];
-
-		/* {D} check if we hit a symbol already */
-		if(node->num_bits)
-		{
-			/* remove the bits for that symbol */
-			bits >>= node->num_bits;
-			bitcount -= node->num_bits;
-		}
-		else
-		{
-			/* remove the bits that the lut checked up for us */
-			bits >>= HUFFMAN_LUTBITS;
-			bitcount -= HUFFMAN_LUTBITS;
-
-			/* walk the tree bit by bit */
-			while(1)
-			{
-				/* traverse tree */
-				node = &huff->nodes[node->leafs[bits&1]];
-
-				/* remove bit */
-				bitcount--;
-				bits >>= 1;
-
-				/* check if we hit a symbol */
-				if(node->num_bits)
-					break;
-
-				/* no more bits, decoding error */
-				if(bitcount == 0)
-					return -1;
-			}
-		}
-
-		/* check for eof */
-		if(node == eof)
-			break;
-
-		/* output character */
-		if(dst == dst_end)
-			return -1;
-		*dst++ = node->symbol;
-	}
-
-	/* return the size of the decompressed buffer */
-	return (int)(dst - (const unsigned char *)output);
-}
diff --git a/src/engine/e_huffman.h b/src/engine/e_huffman.h
deleted file mode 100644
index 635c74a1..00000000
--- a/src/engine/e_huffman.h
+++ /dev/null
@@ -1,83 +0,0 @@
-#ifndef __HUFFMAN_HEADER__
-#define __HUFFMAN_HEADER__
-
-enum
-{
-	HUFFMAN_EOF_SYMBOL = 256,
-
-	HUFFMAN_MAX_SYMBOLS=HUFFMAN_EOF_SYMBOL+1,
-	HUFFMAN_MAX_NODES=HUFFMAN_MAX_SYMBOLS*2-1,
-	
-	HUFFMAN_LUTBITS = 10,
-	HUFFMAN_LUTSIZE = (1<<HUFFMAN_LUTBITS),
-	HUFFMAN_LUTMASK = (HUFFMAN_LUTSIZE-1)
-};
-
-typedef struct HUFFMAN_NODE
-{
-	/* symbol */
-	unsigned bits;
-	unsigned num_bits;
-
-	/* don't use pointers for this. shorts are smaller so we can fit more data into the cache */
-	unsigned short leafs[2];
-
-	/* what the symbol represents */
-	unsigned char symbol;
-} HUFFMAN_NODE;
-
-typedef struct HUFFMAN_STATE
-{
-	HUFFMAN_NODE nodes[HUFFMAN_MAX_NODES];
-	HUFFMAN_NODE *decode_lut[HUFFMAN_LUTSIZE];
-	HUFFMAN_NODE *start_node;
-	int num_nodes;
-} HUFFMAN_STATE;
-
-/*
-	Function: huffman_init
-		Inits the compressor/decompressor.
-
-	Parameters:
-		huff - Pointer to the state to init
-		frequencies - A pointer to an array of 256 entries of the frequencies of the bytes
-
-	Remarks:
-		- Does no allocation what so ever.
-		- You don't have to call any cleanup functions when you are done with it
-*/
-void huffman_init(HUFFMAN_STATE *huff, const unsigned *frequencies);
-
-/*
-	Function: huffman_compress
-		Compresses a buffer and outputs a compressed buffer.
-
-	Parameters:
-		huff - Pointer to the huffman state
-		input - Buffer to compress
-		input_size - Size of the buffer to compress
-		output - Buffer to put the compressed data into
-		output_size - Size of the output buffer
-
-	Returns:
-		Returns the size of the compressed data. Negative value on failure.
-*/
-int huffman_compress(HUFFMAN_STATE *huff, const void *input, int input_size, void *output, int output_size);
-
-/*
-	Function: huffman_decompress
-		Decompresses a buffer
-
-	Parameters:
-		huff - Pointer to the huffman state
-		input - Buffer to decompress
-		input_size - Size of the buffer to decompress
-		output - Buffer to put the uncompressed data into
-		output_size - Size of the output buffer
-
-	Returns:
-		Returns the size of the uncompressed data. Negative value on failure.
-*/
-int huffman_decompress(HUFFMAN_STATE *huff, const void *input, int input_size, void *output, int output_size);
-
-#endif /* __HUFFMAN_HEADER__ */
diff --git a/src/engine/e_if_client.h b/src/engine/e_if_client.h
deleted file mode 100644
index 86c6f5fc..00000000
--- a/src/engine/e_if_client.h
+++ /dev/null
@@ -1,579 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef ENGINE_IF_CLIENT_H
-#define ENGINE_IF_CLIENT_H
-
-/*
-	Title: Client Interface
-*/
-
-/*
-	Section: Constants
-*/
-
-enum
-{
-	/* Constants: Client States
-		CLIENTSTATE_OFFLINE - The client is offline.
-		CLIENTSTATE_CONNECTING - The client is trying to connect to a server.
-		CLIENTSTATE_LOADING - The client has connected to a server and is loading resources.
-		CLIENTSTATE_ONLINE - The client is connected to a server and running the game.
-		CLIENTSTATE_DEMOPLAYBACK - The client is playing a demo
-		CLIENTSTATE_QUITING - The client is quiting.
-	*/
-	CLIENTSTATE_OFFLINE=0,
-	CLIENTSTATE_CONNECTING,
-	CLIENTSTATE_LOADING,
-	CLIENTSTATE_ONLINE,
-	CLIENTSTATE_DEMOPLAYBACK,
-	CLIENTSTATE_QUITING,
-
-	/* Constants: Image Formats
-		IMG_AUTO - Lets the engine choose the format.
-		IMG_RGB - 8-Bit uncompressed RGB
-		IMG_RGBA - 8-Bit uncompressed RGBA
-		IMG_ALPHA - 8-Bit uncompressed alpha
-	*/
-	IMG_AUTO=-1,
-	IMG_RGB=0,
-	IMG_RGBA=1,
-	IMG_ALPHA=2,
-	
-	/* Constants: Texture Loading Flags
-		TEXLOAD_NORESAMPLE - Prevents the texture from any resampling
-	*/
-	TEXLOAD_NORESAMPLE=1,
-	
-	/* Constants: Server Browser Sorting
-		BROWSESORT_NAME - Sort by name.
-		BROWSESORT_PING - Sort by ping.
-		BROWSESORT_MAP - Sort by map
-		BROWSESORT_GAMETYPE - Sort by game type. DM, TDM etc.
-		BROWSESORT_PROGRESSION - Sort by progression.
-		BROWSESORT_NUMPLAYERS - Sort after how many players there are on the server.
-	*/
-	BROWSESORT_NAME = 0,
-	BROWSESORT_PING,
-	BROWSESORT_MAP,
-	BROWSESORT_GAMETYPE,
-	BROWSESORT_PROGRESSION,
-	BROWSESORT_NUMPLAYERS,
-	
-	BROWSEQUICK_SERVERNAME=1,
-	BROWSEQUICK_PLAYERNAME=2,
-	BROWSEQUICK_MAPNAME=4,
-	
-	BROWSETYPE_INTERNET = 0,
-	BROWSETYPE_LAN = 1,
-	BROWSETYPE_FAVORITES = 2
-};
-
-/*
-	Section: Structures
-*/
-
-/*
-	Structure: SERVER_INFO_PLAYER
-*/
-typedef struct
-{
-	char name[48];
-	int score;
-} SERVER_INFO_PLAYER;
-
-/*
-	Structure: SERVER_INFO
-*/
-typedef struct
-{
-	int sorted_index;
-	int server_index;
-	
-	NETADDR netaddr;
-	
-	int quicksearch_hit;
-	
-	int progression;
-	int max_players;
-	int num_players;
-	int flags;
-	int favorite;
-	int latency; /* in ms */
-	char gametype[16];
-	char name[64];
-	char map[32];
-	char version[32];
-	char address[24];
-	SERVER_INFO_PLAYER players[16];
-} SERVER_INFO;
-
-/*
-	Section: Functions
-*/
-
-/**********************************************************************************
-	Group: Time
-**********************************************************************************/
-/*
-	Function: client_tick
-		Returns the tick of the current snapshot.
-*/
-int client_tick();
-
-/*
-	Function: client_prevtick
-		Returns the tick of the previous snapshot.
-*/
-int client_prevtick();
-
-/*
-	Function: client_intratick
-		Returns the current intratick.
-	
-	Remarks:
-		The intratick is how far gone the time is from the previous snapshot to the current.
-		0.0 means that it on the previous snapshot. 0.5 means that it's halfway to the current,
-		and 1.0 means that it is on the current snapshot. It can go beyond 1.0 which means that
-		the client has started to extrapolate due to lack of data from the server.
-
-	See Also:
-		<client_tick>
-*/
-float client_intratick();
-
-/*
-	Function: client_predtick
-		Returns the current predicted tick.
-*/
-int client_predtick();
-
-/*
-	Function: client_predintratick
-		Returns the current preticted intra tick.
-	
-	Remarks:
-		This is the same as <client_intratick> but for the current predicted tick and
-		previous predicted tick.
-
-	See Also:
-		<client_intratick>
-*/
-float client_predintratick();
-
-/*
-	Function: client_ticktime
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-float client_ticktime();
-
-/*
-	Function: client_tickspeed
-		Returns how many ticks per second the client is doing.
-	
-	Remarks:
-		This will be the same as the server tick speed.
-*/
-int client_tickspeed();
-
-/*
-	Function: client_frametime
-		Returns how long time the last frame took to process.
-*/
-float client_frametime();
-
-/*
-	Function: client_localtime
-		Returns the clients local time.
-	
-	Remarks:
-		The local time is set to 0 when the client starts and when
-		it connects to a server. Can be used for client side effects.
-*/
-float client_localtime();
-
-/**********************************************************************************
-	Group: Server Browser
-**********************************************************************************/
-
-/*
-	Function: client_serverbrowse_refresh
-		Issues a refresh of the server browser.
-	
-	Arguments:
-		type - What type of servers to browse, internet, lan or favorites.
-	
-	Remarks:
-		This will cause a broadcast on the local network if the lan argument is set.
-		Otherwise it call ask all the master servers for their servers lists.
-*/
-void client_serverbrowse_refresh(int type);
-
-/*
-	Function: client_serverbrowse_sorted_get
-		Returns server info from the sorted list.
-	
-	Arguments:
-		index - Zero based index into the sorted list.
-	
-	See Also:
-		<client_serverbrowse_sorted_num>
-*/
-SERVER_INFO *client_serverbrowse_sorted_get(int index);
-
-/*
-	Function: client_serverbrowse_sorted_num
-		Returns how many servers there are in the sorted list.
-	
-	See Also:
-		<client_serverbrowse_sorted_get>
-*/
-int client_serverbrowse_sorted_num();
-
-/*
-	Function: client_serverbrowse_get
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-SERVER_INFO *client_serverbrowse_get(int index);
-
-/*
-	Function: client_serverbrowse_num
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int client_serverbrowse_num();
-
-/*
-	Function: client_serverbrowse_num_requests
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int client_serverbrowse_num_requests();
-
-/*
-	Function: client_serverbrowse_update
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void client_serverbrowse_update();
-
-/*
-	Function: client_serverbrowse_lan
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int client_serverbrowse_lan();
-
-/*
-	Function: client_serverbrowse_isfavorite
-		Asks the server browser is a netaddr is in the favorite list
-	
-	Arguments:
-		addr - Address of the server to ask about.
-		
-	Returns:
-		Returns zero if it's not in the list, non-zero if it is.
-*/
-int client_serverbrowse_isfavorite(NETADDR addr);
-
-/*
-	Function: client_serverbrowse_addfavorite
-		Adds a server to the favorite list
-	
-	Arguments:
-		addr - Address of the favorite server.
-*/
-void client_serverbrowse_addfavorite(NETADDR addr);
-
-/*
-	Function: client_serverbrowse_removefavorite
-		Removes a server to the favorite list
-	
-	Arguments:
-		addr - Address of the favorite server.
-*/
-void client_serverbrowse_removefavorite(NETADDR addr);
-
-/**********************************************************************************
-	Group: Actions
-**********************************************************************************/
-
-
-/*
-	Function: client_connect
-		Connects to a server at the specified address.
-	
-	Arguments:
-		address - Address of the server to connect to.
-	
-	See Also:
-		<client_disconnect>
-*/
-void client_connect(const char *address);
-
-/*
-	Function: client_disconnect
-		Disconnects from the current server.
-	
-	Remarks:
-		Does nothing if not connected to a server.
-
-	See Also:
-		<client_connect, client_quit>
-*/
-void client_disconnect();
-
-/*
-	Function: client_quit
-		Tells to client to shutdown.
-
-	See Also:
-		<client_disconnect>
-*/
-void client_quit();
-
-void client_entergame();
-
-/*
-	Function: client_rcon
-		Sends a command to the server to execute on it's console.
-	
-	Arguments:
-		cmd - The command to send.
-	
-	Remarks:
-		The client must have the correct rcon password to connect.
-
- 	See Also:
-		<client_rcon_auth, client_rcon_authed>
-*/
-void client_rcon(const char *cmd);
-
-/*
-	Function: client_rcon_auth
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<client_rcon, client_rcon_authed>
-*/
-void client_rcon_auth(const char *name, const char *password);
-
-/*
-	Function: client_rcon_authed
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<client_rcon, client_rcon_auth>
-*/
-int client_rcon_authed();
-
-/**********************************************************************************
-	Group: Other
-**********************************************************************************/
-/*
-	Function: client_latestversion
-		Returns 0 if there's no version difference
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-const char *client_latestversion();
-
-/*
-	Function: client_get_input
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int *client_get_input(int tick);
-
-/*
-	Function: client_direct_input
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void client_direct_input(int *input, int size);
-
-/*
-	Function: client_error_string
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-const char *client_error_string();
-
-/*
-	Function: client_connection_problems
-		Returns 1 if the client is connection problems.
-	
-	Remarks:
-		Connections problems usually means that the client havn't recvived any data
-		from the server in a while.
-*/
-int client_connection_problems();
-
-/*
-	Function: client_state
-		Returns the state of the client.
-		
-	See Also:
-		<Client States>
-*/
-int client_state();
-
-/*
-	Function: client_mapdownload_amount
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int client_mapdownload_amount();
-
-/*
-	Function: client_mapdownload_totalsize
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int client_mapdownload_totalsize();
-
-/*
-	Function: client_save_line
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void client_save_line(const char *line);
-
-
-
-
-
-
-enum
-{
-	BROWSESET_MASTER_ADD=1,
-	BROWSESET_FAV_ADD,
-	BROWSESET_TOKEN,
-	BROWSESET_OLD_INTERNET,
-	BROWSESET_OLD_LAN
-};
-
-void client_serverbrowse_set(NETADDR *addr, int type, int token, SERVER_INFO *info);
-
-int client_serverbrowse_refreshingmasters();
-
-
-typedef struct DEMOPLAYBACK_INFO
-{
-	int first_tick;
-	int last_tick;
-	int current_tick;
-	int paused;
-	float speed;
-} DEMOPLAYBACK_INFO;
-
-const char *client_demoplayer_play(const char *filename);
-const DEMOPLAYBACK_INFO *client_demoplayer_getinfo();
-void client_demoplayer_setpos(float percent);
-void client_demoplayer_setpause(int paused);
-void client_demoplayer_setspeed(float speed);
-const char *client_user_directory();
-void client_serverinfo(SERVER_INFO *serverinfo);
-void client_serverinfo_request();
-void client_serverbrowse_request(NETADDR *addr);
-#endif
diff --git a/src/engine/e_if_gfx.h b/src/engine/e_if_gfx.h
deleted file mode 100644
index 3d048e85..00000000
--- a/src/engine/e_if_gfx.h
+++ /dev/null
@@ -1,674 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef ENGINE_IF_GFX_H
-#define ENGINE_IF_GFX_H
-
-/*
-	Title: Graphics
-*/
-
-/*
-	Section: Structures
-*/
-
-/*
-	Structure: FONT
-*/
-struct FONT;
-
-/*
-	Structure: IMAGE_INFO
-*/
-typedef struct
-{
-	/* Variable: width
-		Contains the width of the image */
-	int width;
-	
-	/* Variable: height
-		Contains the height of the image */
-	int height;
-	
-	/* Variable: format
-		Contains the format of the image. See <Image Formats> for more information. */
-	int format;
-
-	/* Variable: data
-		Pointer to the image data. */
-	void *data;
-} IMAGE_INFO;
-
-/*
-	Structure: VIDEO_MODE
-*/
-typedef struct 
-{
-	int width, height;
-	int red, green, blue;
-} VIDEO_MODE;
-
-/*
-	Section: Functions
-*/
-
-/*
-	Group: Quads
-*/
-
-/*
-	Function: gfx_quads_begin
-		Begins a quad drawing session.
-		
-	Remarks:
-		This functions resets the rotation, color and subset.
-		End the session by using <gfx_quads_end>.
-		You can't change texture or blending mode during a session.
-		
-	See Also:
-		<gfx_quads_end>
-*/
-void gfx_quads_begin();
-
-/*
-	Function: gfx_quads_end
-		Ends a quad session.
-		
-	See Also:
-		<gfx_quads_begin>
-*/
-void gfx_quads_end();
-
-/*
-	Function: gfx_quads_setrotation
-		Sets the rotation to use when drawing a quad.
-		
-	Arguments:
-		angle - Angle in radians.
-		
-	Remarks:
-		The angle is reset when <gfx_quads_begin> is called.
-*/
-void gfx_quads_setrotation(float angle);
-
-/*
-	Function: gfx_quads_setsubset
-		Sets the uv coordinates to use.
-		
-	Arguments:
-		tl_u - Top-left U value.
-		tl_v - Top-left V value.
-		br_u - Bottom-right U value.
-		br_v - Bottom-right V value.
-		
-	Remarks:
-		O,0 is top-left of the texture and 1,1 is bottom-right.
-		The color is reset when <gfx_quads_begin> is called.
-*/
-void gfx_quads_setsubset(float tl_u, float tl_v, float br_u, float br_v);
-
-/*
-	Function: gfx_quads_setsubset_free
-		TODO
-		
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void gfx_quads_setsubset_free(
-	float x0, float y0,
-	float x1, float y1,
-	float x2, float y2,
-	float x3, float y3);
-
-/*
-	Function: gfx_quads_drawTL
-		Draws a quad by specifying the top-left point.
-		
-	Arguments:
-		x - X coordinate of the top-left corner.
-		y - Y coordinate of the top-left corner.
-		width - Width of the quad.
-		height - Height of the quad.
-		
-	Remarks:
-		Rotation still occurs from the center of the quad.
-		You must call <gfx_quads_begin> before calling this function.
-
-	See Also:
-		<gfx_quads_draw, gfx_quads_draw_freeform>
-*/
-void gfx_quads_drawTL(float x, float y, float width, float height);
-
-/*
-	Function: gfx_quads_draw
-		Draws a quad by specifying the center point.
-		
-	Arguments:
-		x - X coordinate of the center.
-		y - Y coordinate of the center.
-		width - Width of the quad.
-		height - Height of the quad.
-
-	Remarks:
-		You must call <gfx_quads_begin> before calling this function.
-
-	See Also:
-		<gfx_quads_drawTL, gfx_quads_draw_freeform>
-*/
-void gfx_quads_draw(float x, float y, float w, float h);
-
-/*
-	Function: gfx_quads_draw_freeform
-		Draws a quad by specifying the corner points.
-	
-	Arguments:
-		x0, y0 - Coordinates of the upper left corner.
-		x1, y1 - Coordinates of the upper right corner.
-		x2, y2 - Coordinates of the lower left corner. // TODO: DOUBLE CHECK!!!
-		x3, y3 - Coordinates of the lower right corner. // TODO: DOUBLE CHECK!!!
-	
-	See Also:
-		<gfx_quads_draw, gfx_quads_drawTL>
-*/
-void gfx_quads_draw_freeform(
-	float x0, float y0,
-	float x1, float y1,
-	float x2, float y2,
-	float x3, float y3);
-
-/*
-	Function: gfx_quads_text
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void gfx_quads_text(float x, float y, float size, float r, float g, float b, float a, const char *text);
-
-/*
-	Group: Lines
-*/
-
-/*
-	Function: gfx_lines_begin
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void gfx_lines_begin();
-
-/*
-	Function: gfx_lines_draw
-		TODO
-		
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void gfx_lines_draw(float x0, float y0, float x1, float y1);
-
-/*
-	Function: gfx_minimize
-		Minimizes the window.
-		
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void gfx_minimize();
-
-/*
-	Function: gfx_minimize
-		Maximizes the window.
-		
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void gfx_maximize();
-
-/*
-	Function: gfx_lines_end
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void gfx_lines_end();
-
-/*
-	Group: Text
-*/
-
-
-/*
-	Function: gfx_text
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-		returns the number of lines written
-	See Also:
-		<other_func>
-*/
-void gfx_text(void *font, float x, float y, float size, const char *text, int max_width);
-
-/*
-	Function: gfx_text_width
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-float gfx_text_width(void *font, float size, const char *text, int length);
-
-/*
-	Function: gfx_text_color
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void gfx_text_color(float r, float g, float b, float a);
-
-/*
-	Function: gfx_text_set_default_font
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void gfx_text_set_default_font(struct FONT *font);
-
-/*
-	Group: Other
-*/
-
-/*
-	Function: gfx_get_video_modes
-		Fetches a list of all the available video modes.
-		
-	Arguments:
-		list - An array to recive the modes. Must be able to contain maxcount number of modes.
-		maxcount - The maximum number of modes to fetch.
-	
-	Returns:
-		The number of video modes that was fetched.
-*/
-int gfx_get_video_modes(VIDEO_MODE *list, int maxcount);
-
-/* image loaders */
-
-/*
-	Function: gfx_load_png
-		Loads a PNG image from disk.
-	
-	Arguments:
-		img - Pointer to an structure to be filled out with the image information.
-		filename - Filename of the image to load.
-	
-	Returns:
-		Returns non-zero on success and zero on error.
-	
-	Remarks:
-		The caller are responsible for cleaning up the allocated memory in the IMAGE_INFO structure.
-	
-	See Also:
-		<gfx_load_texture>
-*/
-int gfx_load_png(IMAGE_INFO *img, const char *filename);
-
-/* textures */
-/*
-	Function: gfx_load_texture
-		Loads a texture from a file. TGA and PNG supported.
-	
-	Arguments:
-		filename - Null terminated string to the file to load.
-		store_format - What format to store on gfx card as.
-		flags - controls how the texture is uploaded
-	
-	Returns:
-		An ID to the texture. -1 on failure.
-
-	See Also:
-		<gfx_unload_texture, gfx_load_png>
-*/
-int gfx_load_texture(const char *filename, int store_format, int flags);
-
-/*
-	Function: gfx_load_texture_raw
-		Loads a texture from memory.
-	
-	Arguments:
-		w - Width of the texture.
-		h - Height of the texture.
-		data - Pointer to the pixel data.
-		format - Format of the pixel data.
-		store_format - The format to store the texture on the graphics card.
-		flags - controls how the texture is uploaded
-	
-	Returns:
-		An ID to the texture. -1 on failure.
-		
-	Remarks:
-		The pixel data should be in RGBA format with 8 bit per component.
-		So the total size of the data should be w*h*4.
-		
-	See Also:
-		<gfx_unload_texture>
-*/
-int gfx_load_texture_raw(int w, int h, int format, const void *data, int store_format, int flags);
-
-/*
-	Function: gfx_texture_set
-		Sets the active texture.
-	
-	Arguments:
-		id - ID to the texture to set.
-*/
-void gfx_texture_set(int id);
-
-/*
-	Function: gfx_unload_texture
-		Unloads a texture.
-	
-	Arguments:
-		id - ID to the texture to unload.
-		
-	See Also:
-		<gfx_load_texture_tga>, <gfx_load_texture_raw>
-		
-	Remarks:
-		NOT IMPLEMENTED
-*/
-int gfx_unload_texture(int id);
-
-/*
-	Function: gfx_clear
-		Clears the screen with the specified color.
-	
-	Arguments:
-		r - Red component.
-		g - Green component.
-		b - Red component.
-	
-	Remarks:
-		The value of the components are given in 0.0 - 1.0 ranges.
-*/
-void gfx_clear(float r, float g, float b);
-
-/*
-	Function: gfx_screenaspect
-		Returns the aspect ratio between width and height.
-
-	See Also:
-		<gfx_screenwidth>, <gfx_screenheight>
-*/
-float gfx_screenaspect();
-
-/*
-	Function: gfx_screenwidth
-		Returns the screen width.
-	
-	See Also:
-		<gfx_screenheight>
-*/
-int gfx_screenwidth();
-
-/*
-	Function: gfx_screenheight
-		Returns the screen height.
-	
-	See Also:
-		<gfx_screenwidth>
-*/
-int gfx_screenheight();
-
-/*
-	Function: gfx_mapscreen
-		Specifies the coordinate system for the screen.
-		
-	Arguments:
-		tl_x - Top-left X
-		tl_y - Top-left Y
-		br_x - Bottom-right X
-		br_y - Bottom-right y
-*/
-void gfx_mapscreen(float tl_x, float tl_y, float br_x, float br_y);
-
-/*
-	Function: gfx_blend_normal
-		Set the active blending mode to normal (src, 1-src).
-
-	Remarks:
-		This must be used before calling <gfx_quads_begin>.
-		This is equal to glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).
-	
-	See Also:
-		<gfx_blend_additive,gfx_blend_none>
-*/
-void gfx_blend_normal();
-
-/*
-	Function: gfx_blend_additive
-		Set the active blending mode to additive (src, one).
-
-	Remarks:
-		This must be used before calling <gfx_quads_begin>.
-		This is equal to glBlendFunc(GL_SRC_ALPHA, GL_ONE).
-	
-	See Also:
-		<gfx_blend_normal,gfx_blend_none>
-*/
-void gfx_blend_additive();
-
-/*
-	Function: gfx_blend_none
-		Disables blending
-
-	Remarks:
-		This must be used before calling <gfx_quads_begin>.
-	
-	See Also:
-		<gfx_blend_normal,gfx_blend_additive>
-*/
-void gfx_blend_none();
-
-
-/*
-	Function: gfx_setcolorvertex
-		Sets the color of a vertex.
-		
-	Arguments:
-		i - Index to the vertex.
-		r - Red value.
-		g - Green value.
-		b - Blue value.
-		a - Alpha value.
-		
-	Remarks:
-		The color values are from 0.0 to 1.0.
-		The color is reset when <gfx_quads_begin> is called.
-*/
-void gfx_setcolorvertex(int i, float r, float g, float b, float a);
-
-/*
-	Function: gfx_setcolor
-		Sets the color of all the vertices.
-		
-	Arguments:
-		r - Red value.
-		g - Green value.
-		b - Blue value.
-		a - Alpha value.
-		
-	Remarks:
-		The color values are from 0.0 to 1.0.
-		The color is reset when <gfx_quads_begin> is called.
-*/
-void gfx_setcolor(float r, float g, float b, float a);
-
-/*
-	Function: gfx_getscreen
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void gfx_getscreen(float *tl_x, float *tl_y, float *br_x, float *br_y);
-
-/*
-	Function: gfx_memory_usage
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int gfx_memory_usage();
-
-/*
-	Function: gfx_screenshot
-		TODO		
-	
-	Arguments:
-		filename - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void gfx_screenshot();
-
-/*
-	Function: gfx_screenshot_direct
-		TODO		
-	
-	Arguments:
-		filename - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void gfx_screenshot_direct(const char *filename);
-
-/*
-	Function: gfx_clip_enable
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void gfx_clip_enable(int x, int y, int w, int h);
-
-/*
-	Function: gfx_clip_disable
-		TODO	
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void gfx_clip_disable();
-
-
-enum
-{
-	TEXTFLAG_RENDER=1,
-	TEXTFLAG_ALLOW_NEWLINE=2,
-	TEXTFLAG_STOP_AT_END=4
-};
-
-typedef struct
-{
-	int flags;
-	int line_count;
-	int charcount;
-	
-	float start_x;
-	float start_y;
-	float line_width;
-	float x, y;
-	
-	struct FONT *font;
-	float font_size;
-} TEXT_CURSOR;
-
-void gfx_text_set_cursor(TEXT_CURSOR *cursor, float x, float y, float font_size, int flags);
-void gfx_text_ex(TEXT_CURSOR *cursor, const char *text, int length);
-
-
-struct FONT *gfx_font_load(const char *filename);
-void gfx_font_destroy(struct FONT *font);
-
-#endif
diff --git a/src/engine/e_if_inp.h b/src/engine/e_if_inp.h
deleted file mode 100644
index 919ac0eb..00000000
--- a/src/engine/e_if_inp.h
+++ /dev/null
@@ -1,244 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef ENGINE_IF_INP_H
-#define ENGINE_IF_INP_H
-
-/*
-	Section: Input
-*/
-
-
-/*
-	Structure: INPUT_EVENT
-*/
-enum
-{
-	INPFLAG_PRESS=1,
-	INPFLAG_RELEASE=2,
-	INPFLAG_REPEAT=4
-};
-
-typedef struct
-{
-	int flags;
-	int unicode;
-	int key;
-} INPUT_EVENT;
-
-/*
-	Function: inp_mouse_relative
-		Fetches the mouse movements.
-		
-	Arguments:
-		x - Pointer to the variable that should get the X movement.
-		y - Pointer to the variable that should get the Y movement.
-*/
-void inp_mouse_relative(int *x, int *y);
-
-/*
-	Function: inp_mouse_scroll
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int inp_mouse_scroll();
-
-/*
-	Function: inp_key_pressed
-		Checks if a key is pressed.
-		
-	Arguments:
-		key - Index to the key to check
-		
-	Returns:
-		Returns 1 if the button is pressed, otherwise 0.
-	
-	Remarks:
-		Check keys.h for the keys.
-*/
-int inp_key_pressed(int key);
-
-
-/* input */
-/*
-	Function: inp_key_was_pressed
-		TODO	
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int inp_key_was_pressed(int key);
-
-/*
-	Function: inp_key_down
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int inp_key_down(int key);
-
-
-/*
-	Function: inp_num_events
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int inp_num_events();
-
-/*
-	Function: inp_get_event
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-INPUT_EVENT inp_get_event(int index);
-
-/*
-	Function: inp_clear_events
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void inp_clear_events();
-
-/*
-	Function: inp_mouse_doubleclick
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int inp_mouse_doubleclick();
-
-/*
-	Function: inp_key_presses
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int inp_key_presses(int key);
-
-/*
-	Function: inp_key_releases
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int inp_key_releases(int key);
-
-/*
-	Function: inp_key_state
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int inp_key_state(int key);
-
-/*
-	Function: inp_key_name
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-const char *inp_key_name(int k);
-
-/*
-	Function: inp_key_code
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int inp_key_code(const char *key_name);
-
-
-
-/*
-	Function: inp_clear_key_states
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void inp_clear_key_states(); 
-
-void inp_update();
-void inp_init();
-void inp_mouse_mode_absolute();
-void inp_mouse_mode_relative();
-
-#endif
diff --git a/src/engine/e_if_modc.h b/src/engine/e_if_modc.h
deleted file mode 100644
index 8839d5f1..00000000
--- a/src/engine/e_if_modc.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef ENGINE_IF_MODC_H
-#define ENGINE_IF_MODC_H
-
-/**********************************************************************************
-	Section: Client Hooks
-*********************************************************************************/
-/*
-	Function: modc_console_init
-		TODO
-*/
-void modc_console_init();
-
-/*
-	Function: modc_rcon_line
-		TODO
-*/
-void modc_rcon_line(const char *line);
-
-/*
-	Function: modc_save_config
-		TODO
-*/
-void modc_save_config();
-
-/*
-	Function: modc_init
-		Called when the client starts.
-	
-	Remarks:
-		The game should load resources that are used during the entire
-		time of the game. No map is loaded.
-*/
-void modc_init();
-
-/*
-	Function: modc_newsnapshot
-		Called when the client progressed to a new snapshot.
-	
-	Remarks:
-		The client can check for items in the snapshot and perform one time
-		events like playing sounds, spawning client side effects etc.
-*/
-void modc_newsnapshot();
-
-/*
-	Function: modc_entergame
-		Called when the client has successfully connect to a server and
-		loaded a map.
-	
-	Remarks:
-		The client can check for items in the map and load them.
-*/
-void modc_entergame();
-
-/*
-	Function: modc_shutdown
-		Called when the client closes down.
-*/
-void modc_shutdown();
-
-/*
-	Function: modc_render
-		Called every frame to let the game render it self.
-*/
-void modc_render();
-
-/*
-	Function: modc_statechange
-		Called every time client changes state.
-*/
-void modc_statechange(int new_state, int old_state);
-
-/* undocumented callbacks */
-/*
-	Function: modc_connected
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void modc_connected();
-
-/*
-	Function: modc_message
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void modc_message(int msg);
-
-/*
-	Function: modc_predict
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void modc_predict();
-
-/*
-	Function: modc_snap_input
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int modc_snap_input(int *data);
-
-/*
-	Function: modc_net_version
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-const char *modc_net_version();
-
-#endif
diff --git a/src/engine/e_if_mods.h b/src/engine/e_if_mods.h
deleted file mode 100644
index 08d0ec37..00000000
--- a/src/engine/e_if_mods.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef ENGINE_IF_MOD_H
-#define ENGINE_IF_MOD_H
-
-/**********************************************************************************
-	Section: Server Hooks
-**********************************************************************************/
-/*
-	Function: mods_console_init
-		TODO
-*/
-void mods_console_init();
-
-/*
-	Function: mods_init
-		Called when the server is started.
-	
-	Remarks:
-		It's called after the map is loaded so all map items are available.
-*/
-void mods_init();
-
-/*
-	Function: mods_shutdown
-		Called when the server quits.
-	
-	Remarks:
-		Should be used to clean up all resources used.
-*/
-void mods_shutdown();
-
-/*
-	Function: mods_client_enter
-		Called when a client has joined the game.
-		
-	Arguments:
-		cid - Client ID. Is 0 - MAX_CLIENTS.
-	
-	Remarks:
-		It's called when the client is finished loading and should enter gameplay.
-*/
-void mods_client_enter(int cid);
-
-/*
-	Function: mods_client_drop
-		Called when a client drops from the server.
-
-	Arguments:
-		cid - Client ID. Is 0 - MAX_CLIENTS
-*/
-void mods_client_drop(int cid);
-
-/*
-	Function: mods_client_direct_input
-		Called when the server recives new input from a client.
-
-	Arguments:
-		cid - Client ID. Is 0 - MAX_CLIENTS.
-		input - Pointer to the input data.
-		size - Size of the data. (NOT IMPLEMENTED YET)
-*/
-void mods_client_direct_input(int cid, void *input);
-
-/*
-	Function: mods_client_predicted_input
-		Called when the server applys the predicted input on the client.
-
-	Arguments:
-		cid - Client ID. Is 0 - MAX_CLIENTS.
-		input - Pointer to the input data.
-		size - Size of the data. (NOT IMPLEMENTED YET)
-*/
-void mods_client_predicted_input(int cid, void *input);
-
-
-/*
-	Function: mods_tick
-		Called with a regular interval to progress the gameplay.
-		
-	Remarks:
-		The SERVER_TICK_SPEED tells the number of ticks per second.
-*/
-void mods_tick();
-
-/*
-	Function: mods_presnap
-		Called before the server starts to construct snapshots for the clients.
-*/
-void mods_presnap();
-
-/*
-	Function: mods_snap
-		Called to create the snapshot for a client.
-	
-	Arguments:
-		cid - Client ID. Is 0 - MAX_CLIENTS.
-	
-	Remarks:
-		The game should make a series of calls to <snap_new_item> to construct
-		the snapshot for the client.
-*/
-void mods_snap(int cid);
-
-/*
-	Function: mods_postsnap
-		Called after the server is done sending the snapshots.
-*/
-void mods_postsnap();
-
-
-/*
-	Function: mods_connected
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void mods_connected(int client_id);
-
-
-/*
-	Function: mods_net_version
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-const char *mods_net_version();
-
-/*
-	Function: mods_version
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-const char *mods_version();
-
-/*
-	Function: mods_message
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void mods_message(int msg, int client_id);
-
-#endif
diff --git a/src/engine/e_if_msg.h b/src/engine/e_if_msg.h
deleted file mode 100644
index d03a64a6..00000000
--- a/src/engine/e_if_msg.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef ENGINE_IF_MSG_H
-#define ENGINE_IF_MSG_H
-
-/*
-	Section: Messaging
-*/
-
-void msg_pack_start_system(int msg, int flags);
-
-/*
-	Function: msg_pack_start
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void msg_pack_start(int msg, int flags);
-
-/*
-	Function: msg_pack_int
-		TODO	
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void msg_pack_int(int i);
-
-/*
-	Function: msg_pack_string
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void msg_pack_string(const char *p, int limit);
-
-/*
-	Function: msg_pack_raw
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void msg_pack_raw(const void *data, int size);
-
-/*
-	Function: msg_pack_end
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void msg_pack_end();
-
-typedef struct
-{
-	int msg;
-	int flags;
-	const unsigned char *data;
-	int size;
-} MSG_INFO;
-
-const MSG_INFO *msg_get_info();
-
-/* message unpacking */
-int msg_unpack_start(const void *data, int data_size, int *is_system);
-
-/*
-	Function: msg_unpack_int
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int msg_unpack_int();
-
-/*
-	Function: msg_unpack_string
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-const char *msg_unpack_string();
-
-/*
-	Function: msg_unpack_raw
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-const unsigned char *msg_unpack_raw(int size);
-
-/*
-	Function: msg_unpack_error
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int msg_unpack_error();
-
-
-#endif
diff --git a/src/engine/e_if_other.h b/src/engine/e_if_other.h
deleted file mode 100644
index 3fbbd81e..00000000
--- a/src/engine/e_if_other.h
+++ /dev/null
@@ -1,385 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef ENGINE_IF_OTHER_H
-#define ENGINE_IF_OTHER_H
-
-/*
-	Title: Engine Interface
-*/
-
-#include <base/system.h>
-#include "e_keys.h"
-
-enum 
-{
-	SERVER_TICK_SPEED=50,
-	MAX_CLIENTS=16,
-	
-	SNAP_CURRENT=0,
-	SNAP_PREV=1,
-
-	MASK_NONE=0,
-	MASK_SET,
-	MASK_ZERO,
-
-	SNDFLAG_LOOP=1,
-	SNDFLAG_POS=2,
-	SNDFLAG_ALL=3,
-	
-	MAX_NAME_LENGTH=32
-};
-
-enum
-{
-	SRVFLAG_PASSWORD = 0x1,
-};
-
-/*
-	Structure: SNAP_ITEM
-*/
-typedef struct
-{
-	int type;
-	int id;
-	int datasize;
-} SNAP_ITEM;
-
-/*
-	Structure: CLIENT_INFO
-*/
-typedef struct
-{
-	const char *name;
-	int latency;
-} CLIENT_INFO;
-
-typedef struct PERFORMACE_INFO_t
-{
-	const char *name;
-	struct PERFORMACE_INFO_t *parent;
-	struct PERFORMACE_INFO_t *first_child;
-	struct PERFORMACE_INFO_t *next_child;
-	int tick;
-	int64 start;
-	int64 total;
-	int64 biggest;
-	int64 last_delta;
-} PERFORMACE_INFO;
-
-void perf_init();
-void perf_next();
-void perf_start(PERFORMACE_INFO *info);
-void perf_end();
-void perf_dump(PERFORMACE_INFO *top);
-
-int gfx_init();
-void gfx_shutdown();
-void gfx_swap();
-
-int gfx_window_active();
-int gfx_window_open();
-
-void gfx_set_vsync(int val);
-
-int snd_init();
-int snd_shutdown();
-int snd_update();
-
-int map_load(const char *mapname);
-void map_unload();
-
-void map_set(void *m);
-
-/*
-#include "e_if_client.h"
-#include "e_if_server.h"
-#include "e_if_snd.h"
-#include "e_if_gfx.h"
-#include "e_if_inp.h"
-#include "e_if_msg.h"
-#include "e_if_mod.h"*/
-
-/*
-	Section: Map
-*/
-
-/*
-	Function: map_is_loaded
-		Checks if a map is loaded.
-		
-	Returns:
-		Returns 1 if the button is pressed, otherwise 0.
-*/
-int map_is_loaded();
-
-/*
-	Function: map_num_items
-		Checks the number of items in the loaded map.
-		
-	Returns:
-		Returns the number of items. 0 if no map is loaded.
-*/
-int map_num_items();
-
-/*
-	Function: map_find_item
-		Searches the map for an item.
-	
-	Arguments:
-		type - Item type.
-		id - Item ID.
-	
-	Returns:
-		Returns a pointer to the item if it exists, otherwise it returns NULL.
-*/
-void *map_find_item(int type, int id);
-
-/*
-	Function: map_get_item
-		Gets an item from the loaded map from index.
-	
-	Arguments:
-		index - Item index.
-		type - Pointer that recives the item type (can be NULL).
-		id - Pointer that recives the item id (can be NULL).
-	
-	Returns:
-		Returns a pointer to the item if it exists, otherwise it returns NULL.
-*/
-void *map_get_item(int index, int *type, int *id);
-
-/*
-	Function: map_get_type
-		Gets the index range of an item type.
-	
-	Arguments:
-		type - Item type to search for.
-		start - Pointer that recives the starting index.
-		num - Pointer that recives the number of items.
-	
-	Returns:
-		If the item type is not in the map, start and num will be set to 0.
-*/
-void map_get_type(int type, int *start, int *num);
-
-/*
-	Function: map_get_data
-		Fetches a pointer to a raw data chunk in the map.
-	
-	Arguments:
-		index - Index to the data to fetch.
-	
-	Returns:
-		A pointer to the raw data, otherwise 0.
-*/
-void *map_get_data(int index);
-
-/*
-	Function: map_get_data_swapped
-		TODO
-		
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void *map_get_data_swapped(int index);
-
-/*
-	Section: Network (Server)
-*/
-/*
-	Function: snap_new_item
-		Creates a new item that should be sent.
-	
-	Arguments:
-		type - Type of the item.
-		id - ID of the item.
-		size - Size of the item.
-	
-	Returns:
-		A pointer to the item data, otherwise 0.
-	
-	Remarks:
-		The item data should only consist pf 4 byte integers as
-		they are subject to byte swapping. This means that the size
-		argument should be dividable by 4.
-*/
-void *snap_new_item(int type, int id, int size);
-
-/*
-	Section:Section: Network (Client)
-*/
-/*
-	Function: snap_num_items
-		Check the number of items in a snapshot.
-	
-	Arguments:
-		snapid - Snapshot ID to the data to fetch.
-			* SNAP_PREV for previous snapshot.
-			* SNAP_CUR for current snapshot.
-	
-	Returns:
-		The number of items in the snapshot.
-*/
-int snap_num_items(int snapid);
-
-/*
-	Function: snap_get_item
-		Gets an item from a snapshot.
-	
-	Arguments:
-		snapid - Snapshot ID to the data to fetch.
-			* SNAP_PREV for previous snapshot.
-			* SNAP_CUR for current snapshot.
-		index - Index of the item.
-		item - Pointer that recives the item info.
-	
-	Returns:
-		Returns a pointer to the item if it exists, otherwise NULL.
-*/
-void *snap_get_item(int snapid, int index, SNAP_ITEM *item);
-
-/*
-	Function: snap_find_item
-		Searches a snapshot for an item.
-	
-	Arguments:
-		snapid - Snapshot ID to the data to fetch.
-			* SNAP_PREV for previous snapshot.
-			* SNAP_CUR for current snapshot.
-		type - Type of the item.
-		id - ID of the item.
-	
-	Returns:
-		Returns a pointer to the item if it exists, otherwise NULL.
-*/
-void *snap_find_item(int snapid, int type, int id);
-
-/*
-	Function: snap_invalidate_item
-		Marks an item as invalid byt setting type and id to 0xffffffff.
-	
-	Arguments:
-		snapid - Snapshot ID to the data to fetch.
-			* SNAP_PREV for previous snapshot.
-			* SNAP_CUR for current snapshot.
-		index - Index of the item.
-*/
-void snap_invalidate_item(int snapid, int index);
-
-/*
-	Function: snap_input
-		Sets the input data to send to the server.
-	
-	Arguments:
-		data - Pointer to the data.
-		size - Size of the data.
-
-	Remarks:
-		The data should only consist of 4 bytes integer as they are
-		subject to byte swapping.
-*/
-void snap_input(void *data, int size);
-
-/*
-	Function: snap_set_staticsize
-		Tells the engine how big a specific item always will be. This
-		helps the engine to compress snapshots better.
-	
-	Arguments:
-		type - Item type
-		size - Size of the data.
-		
-	Remarks:
-		Size must be in a multiple of 4.
-*/
-void snap_set_staticsize(int type, int size);
-
-/* message packing */
-enum
-{
-	MSGFLAG_VITAL=1,
-	MSGFLAG_FLUSH=2,
-	MSGFLAG_NORECORD=4,
-	MSGFLAG_RECORD=8,
-	MSGFLAG_NOSEND=16
-};
-
-/* message sending */
-/*
-	Function: server_send_msg
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int server_send_msg(int client_id); /* client_id == -1 == broadcast */
-
-/*
-	Function: client_send_msg
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int client_send_msg();
-/* undocumented graphics stuff */
-
-/* server snap id */
-/*
-	Function: snap_new_id
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int snap_new_id();
-
-/*
-	Function: snap_free_id
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void snap_free_id(int id);
-
-/* other */
-/*
-	Function: map_unload_data
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void map_unload_data(int index);
-
-#endif
diff --git a/src/engine/e_if_server.h b/src/engine/e_if_server.h
deleted file mode 100644
index 1acd184c..00000000
--- a/src/engine/e_if_server.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef ENGINE_IF_SERVER_H
-#define ENGINE_IF_SERVER_H
-
-/*
-	Section: Server Interface
-*/
-
-/* server */
-/*
-	Function: server_getclientinfo
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int server_getclientinfo(int client_id, CLIENT_INFO *info);
-
-/*
-	Function: server_clientname
-		TODO	
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-const char *server_clientname(int client_id);
-
-/* grabs the latest input for the client. not withholding anything */
-
-/*
-	Function: server_latestinput
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int *server_latestinput(int client_id, int *size);
-
-/*
-	Function: server_setclientname
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void server_setclientname(int client_id, const char *name);
-
-/*
-	Function: server_setclientscore
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void server_setclientscore(int client_id, int score);
-
-/*
-	Function: server_setbrowseinfo
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void server_setbrowseinfo(const char *game_type, int progression);
-
-/*
-	Function: server_kick
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-void server_kick(int client_id, const char *reason);
-
-/*
-	Function: server_tick
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int server_tick();
-
-/*
-	Function: server_tickspeed
-		TODO
-	
-	Arguments:
-		arg1 - desc
-	
-	Returns:
-
-	See Also:
-		<other_func>
-*/
-int server_tickspeed();
-
-int server_ban_add(NETADDR addr, int seconds);
-int server_ban_remove(NETADDR addr);
-#endif
diff --git a/src/engine/e_if_snd.h b/src/engine/e_if_snd.h
deleted file mode 100644
index 48376bad..00000000
--- a/src/engine/e_if_snd.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef ENGINE_IF_SND_H
-#define ENGINE_IF_SND_H
-
-/*
-	Section: Sound
-*/
-
-/*
-	Function: snd_set_channel
-		Sets the parameters for a sound channel.
-	
-	Arguments:
-		cid - Channel ID
-		vol - Volume for the channel. 0.0 to 1.0.
-		pan - Panning for the channel. -1.0 is all left. 0.0 is equal distribution. 1.0 is all right.
-*/
-void snd_set_channel(int cid, float vol, float pan);
-
-/*
-	Function: snd_load_wv
-		Loads a wavpack compressed sound.
-	
-	Arguments:
-		filename - Filename of the file to load
-	
-	Returns:
-		The id of the loaded sound. -1 on failure.
-*/
-int snd_load_wv(const char *filename);
-
-/*
-	Function: snd_play_at
-		Plays a sound at a specified postition.
-	
-	Arguments:
-		cid - Channel id of the channel to use.
-		sid - Sound id of the sound to play.
-		flags - TODO
-		x - TODO
-		y - TODO
-	
-	Returns:
-		An id to the voice. -1 on failure.
-
-	See Also:
-		<snd_play, snd_stop>
-*/
-int snd_play_at(int cid, int sid, int flags, float x, float y);
-
-/*
-	Function: snd_play
-		Plays a sound.
-	
-	Arguments:
-	Arguments:
-		cid - Channel id of the channel to use.
-		sid - Sound id of the sound to play.
-		flags - TODO
-	
-	Returns:
-		An id to the voice. -1 on failure.
-
-	See Also:
-		<snd_play_at, snd_stop>
-*/
-int snd_play(int cid, int sid, int flags);
-
-/*
-	Function: snd_stop
-		Stops a currenly playing sound.
-	
-	Arguments:
-		id - The ID of the voice to stop.
-	
-	See Also:
-		<snd_play, snd_play_at>
-*/
-void snd_stop(int id);
-
-/*
-	Function: snd_set_listener_pos
-		Sets the listener posititon.
-	
-	Arguments:
-		x - TODO
-		y - TODO
-*/
-void snd_set_listener_pos(float x, float y);
-
-#endif
diff --git a/src/engine/e_jobs.cpp b/src/engine/e_jobs.cpp
deleted file mode 100644
index e87b395a..00000000
--- a/src/engine/e_jobs.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <base/system.h>
-#include "e_jobs.h"
-
-void worker_thread(void *user)
-{
-	JOBPOOL *pool = (JOBPOOL *)user;
-	
-	while(1)
-	{
-		JOB *job = 0;
-		
-		/* fetch job from queue */
-		lock_wait(pool->lock);
-		if(pool->first_job)
-		{
-			job = pool->first_job;
-			pool->first_job = pool->first_job->next;
-			if(pool->first_job)
-				pool->first_job->prev = 0;
-			else
-				pool->last_job = 0;
-		}
-		lock_release(pool->lock);
-		
-		/* do the job if we have one */
-		if(job)
-		{
-			job->status = JOBSTATUS_RUNNING;
-			job->result = job->func(job->func_data);
-			job->status = JOBSTATUS_DONE;
-		}
-		else
-			thread_sleep(10);
-	}
-	
-}
-
-int jobs_initpool(JOBPOOL *pool, int num_threads)
-{
-	int i;
-	
-	/* empty the pool */
-	mem_zero(pool, sizeof(JOBPOOL));
-	pool->lock = lock_create();
-	
-	/* start threads */
-	for(i = 0; i < num_threads; i++)
-		thread_create(worker_thread, pool);
-	return 0;
-}
-
-int jobs_add(JOBPOOL *pool, JOB *job, JOBFUNC func, void *data)
-{
-	mem_zero(job, sizeof(JOB));
-	job->func = func;
-	job->func_data = data;
-	
-	lock_wait(pool->lock);
-	
-	/* add job to queue */
-	job->prev = pool->last_job;
-	if(pool->last_job)
-		pool->last_job->next = job;
-	pool->last_job = job;
-	if(!pool->first_job)
-		pool->first_job = job;
-	
-	lock_release(pool->lock);
-	return 0;
-}
-
-int jobs_status(JOB *job)
-{
-	return job->status;
-}
diff --git a/src/engine/e_jobs.h b/src/engine/e_jobs.h
deleted file mode 100644
index 2b04a1e4..00000000
--- a/src/engine/e_jobs.h
+++ /dev/null
@@ -1,33 +0,0 @@
-
-typedef int (*JOBFUNC)(void *data);
-
-typedef struct JOB
-{
-	struct JOBPOOL *pool;
-	struct JOB *prev;
-	struct JOB *next;
-	volatile int status;
-	volatile int result;
-	JOBFUNC func;
-	void *func_data;
-} JOB;
-
-typedef struct JOBPOOL
-{
-	LOCK lock;
-	JOB *first_job;
-	JOB *last_job;
-} JOBPOOL;
-
-enum
-{
-	JOBSTATUS_PENDING=0,
-	JOBSTATUS_RUNNING,
-	JOBSTATUS_DONE
-	/*JOBSTATUS_ABORTING,*/
-	/*JOBSTATUS_ABORTED,*/
-};
-
-int jobs_initpool(JOBPOOL *pool, int num_threads);
-int jobs_add(JOBPOOL *pool, JOB *job, JOBFUNC func, void *data);
-int jobs_status(JOB *job);
diff --git a/src/engine/e_linereader.cpp b/src/engine/e_linereader.cpp
deleted file mode 100644
index 57ba9a85..00000000
--- a/src/engine/e_linereader.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-#include "e_linereader.h"
-
-void linereader_init(LINEREADER *lr, IOHANDLE io)
-{
-	lr->buffer_max_size = 4*1024;
-	lr->buffer_size = 0;
-	lr->buffer_pos = 0;
-	lr->io = io;
-}
-
-char *linereader_get(LINEREADER *lr)
-{
-	unsigned line_start = lr->buffer_pos;
-
-	while(1)
-	{
-		if(lr->buffer_pos >= lr->buffer_size)
-		{
-			/* fetch more */
-
-			/* move the remaining part to the front */
-			unsigned read;
-			unsigned left = lr->buffer_size - line_start;
-
-			if(line_start > lr->buffer_size)
-				left = 0;
-			if(left)
-				mem_move(lr->buffer, &lr->buffer[line_start], left);
-			lr->buffer_pos = left;
-
-			/* fill the buffer */
-			read = io_read(lr->io, &lr->buffer[lr->buffer_pos], lr->buffer_max_size-lr->buffer_pos);
-			lr->buffer_size = left + read;
-			line_start = 0;
-
-			if(!read)
-			{
-				if(left)
-				{
-					lr->buffer[left] = 0; /* return the last line */
-					lr->buffer_pos = left;
-					lr->buffer_size = left;
-					return lr->buffer;
-				}
-				else
-					return 0x0; /* we are done! */
-			}
-		}
-		else
-		{
-			if(lr->buffer[lr->buffer_pos] == '\n' || lr->buffer[lr->buffer_pos] == '\r')
-			{
-				/* line found */
-				lr->buffer[lr->buffer_pos] = 0;
-				lr->buffer_pos++;
-				return &lr->buffer[line_start];
-			}
-			else
-				lr->buffer_pos++;
-		}
-	}
-}
diff --git a/src/engine/e_linereader.h b/src/engine/e_linereader.h
deleted file mode 100644
index ca84960a..00000000
--- a/src/engine/e_linereader.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <base/system.h>
-
-/* buffered stream for reading lines, should perhaps be something smaller */
-typedef struct
-{
-	char buffer[4*1024];
-	unsigned buffer_pos;
-	unsigned buffer_size;
-	unsigned buffer_max_size;
-	IOHANDLE io;
-} LINEREADER;
-
-void linereader_init(LINEREADER *lr, IOHANDLE io);
-char *linereader_get(LINEREADER *lr);
diff --git a/src/engine/e_map.cpp b/src/engine/e_map.cpp
deleted file mode 100644
index a2048310..00000000
--- a/src/engine/e_map.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <base/system.h>
-#include "e_datafile.h"
-
-static DATAFILE *map = 0;
-
-void *map_get_data(int index)
-{
-	return datafile_get_data(map, index);
-}
-
-void *map_get_data_swapped(int index)
-{
-	return datafile_get_data_swapped(map, index);
-}
-
-void map_unload_data(int index)
-{
-	datafile_unload_data(map, index);
-}
-
-void *map_get_item(int index, int *type, int *id)
-{
-	return datafile_get_item(map, index, type, id);
-}
-
-void map_get_type(int type, int *start, int *num)
-{
-	datafile_get_type(map, type, start, num);
-}
-
-void *map_find_item(int type, int id)
-{
-	return datafile_find_item(map, type, id);
-}
-
-int map_num_items()
-{
-	return datafile_num_items(map);
-}
-
-void map_unload()
-{
-	datafile_unload(map);
-	map = 0x0;
-}
-
-int map_is_loaded()
-{
-	return map != 0;
-}
-
-int map_load(const char *mapname)
-{
-	char buf[512];
-	str_format(buf, sizeof(buf), "maps/%s.map", mapname);
-	map = datafile_load(buf);
-	return map != 0;
-}
-
-void map_set(void *m)
-{
-	if(map)
-		map_unload();
-	map = (DATAFILE*)m;
-}
diff --git a/src/engine/e_memheap.cpp b/src/engine/e_memheap.cpp
deleted file mode 100644
index fe157e86..00000000
--- a/src/engine/e_memheap.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <base/system.h>
-
-struct CHUNK
-{
-	char *memory;
-	char *current;
-	char *end;
-	CHUNK *next;
-};
-
-struct HEAP
-{
-	CHUNK *current;
-};
-
-/* how large each chunk should be */
-static const int chunksize = 1024*64;
-
-/* allocates a new chunk to be used */
-static CHUNK *memheap_newchunk()
-{
-	CHUNK *chunk;
-	char *mem;
-	
-	/* allocate memory */
-	mem = (char*)mem_alloc(sizeof(CHUNK)+chunksize, 1);
-	if(!mem)
-		return 0x0;
-
-	/* the chunk structure is located in the begining of the chunk */
-	/* init it and return the chunk */
-	chunk = (CHUNK*)mem;
-	chunk->memory = (char*)(chunk+1);
-	chunk->current = chunk->memory;
-	chunk->end = chunk->memory + chunksize;
-	chunk->next = (CHUNK *)0x0;
-	return chunk;
-}
-
-/******************/
-static void *memheap_allocate_from_chunk(CHUNK *chunk, unsigned int size)
-{
-	char *mem;
-	
-	/* check if we need can fit the allocation */
-	if(chunk->current + size > chunk->end)
-		return (void*)0x0;
-
-	/* get memory and move the pointer forward */
-	mem = chunk->current;
-	chunk->current += size;
-	return mem;
-}
-
-/* creates a heap */
-HEAP *memheap_create()
-{
-	CHUNK *chunk;
-	HEAP *heap;
-	
-	/* allocate a chunk and allocate the heap structure on that chunk */
-	chunk = memheap_newchunk();
-	heap = (HEAP *)memheap_allocate_from_chunk(chunk, sizeof(HEAP));
-	heap->current = chunk;
-	return heap;
-}
-
-/* destroys the heap */
-void memheap_destroy(HEAP *heap)
-{
-	CHUNK *chunk = heap->current;
-	CHUNK *next;
-	
-	while(chunk)
-	{
-		next = chunk->next;
-		mem_free(chunk);
-		chunk = next;
-	}
-}
-
-/* */
-void *memheap_allocate(HEAP *heap, unsigned int size)
-{
-	char *mem;
-
-	/* try to allocate from current chunk */
-	mem = (char *)memheap_allocate_from_chunk(heap->current, size);
-	if(!mem)
-	{
-		/* allocate new chunk and add it to the heap */
-		CHUNK *chunk = memheap_newchunk();
-		chunk->next = heap->current;
-		heap->current = chunk;
-		
-		/* try to allocate again */
-		mem = (char *)memheap_allocate_from_chunk(heap->current, size);
-	}
-	
-	return mem;
-}
diff --git a/src/engine/e_memheap.h b/src/engine/e_memheap.h
deleted file mode 100644
index b4391ec7..00000000
--- a/src/engine/e_memheap.h
+++ /dev/null
@@ -1,6 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-
-struct HEAP;
-HEAP *memheap_create();
-void memheap_destroy(HEAP *heap);
-void *memheap_allocate(HEAP *heap, unsigned int size);
diff --git a/src/engine/e_msg.cpp b/src/engine/e_msg.cpp
deleted file mode 100644
index 999a0ff0..00000000
--- a/src/engine/e_msg.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include "e_common_interface.h"
-#include "e_packer.h"
-
-/* message packing */
-static CPacker msg_packer;
-static MSG_INFO pack_info;
-static int packer_failed = 0;
-
-void msg_pack_int(int i) { msg_packer.AddInt(i); }
-void msg_pack_string(const char *p, int limit) { msg_packer.AddString(p, limit); }
-void msg_pack_raw(const void *data, int size) { msg_packer.AddRaw((const unsigned char *)data, size); }
-
-void msg_pack_start_system(int msg, int flags)
-{
-	msg_packer.Reset();
-	pack_info.msg = (msg<<1)|1;
-	pack_info.flags = flags;
-	packer_failed = 0;
-	
-	msg_pack_int(pack_info.msg);
-}
-
-void msg_pack_start(int msg, int flags)
-{
-	msg_packer.Reset();
-	pack_info.msg = msg<<1;
-	pack_info.flags = flags;
-	packer_failed = 0;
-	
-	msg_pack_int(pack_info.msg);
-}
-
-void msg_pack_end()
-{
-	if(msg_packer.Error())
-	{
-		packer_failed = 1;
-		pack_info.size = 0;
-		pack_info.data = (unsigned char *)"";
-	}
-	else
-	{
-		pack_info.size = msg_packer.Size();
-		pack_info.data = msg_packer.Data();
-	}
-}
-
-const MSG_INFO *msg_get_info()
-{
-	if(packer_failed)
-		return 0;
-	return &pack_info;
-}
-
-/* message unpacking */
-static CUnpacker msg_unpacker;
-int msg_unpack_start(const void *data, int data_size, int *system)
-{
-	int msg;
-	msg_unpacker.Reset((const unsigned char *)data, data_size);
-	msg = msg_unpack_int();
-	*system = msg&1;
-	return msg>>1;
-}
-
-int msg_unpack_int() { return msg_unpacker.GetInt(); }
-const char *msg_unpack_string() { return msg_unpacker.GetString(); }
-const unsigned char *msg_unpack_raw(int size)  { return msg_unpacker.GetRaw(size); }
-int msg_unpack_error() { return msg_unpacker.Error(); }
diff --git a/src/engine/e_protocol.h b/src/engine/e_protocol.h
deleted file mode 100644
index a1feb4cc..00000000
--- a/src/engine/e_protocol.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <base/system.h>
-
-/*
-	Connection diagram - How the initilization works.
-	
-	Client -> INFO -> Server
-		Contains version info, name, and some other info.
-		
-	Client <- MAP <- Server
-		Contains current map.
-	
-	Client -> READY -> Server
-		The client has loaded the map and is ready to go,
-		but the mod needs to send it's information aswell.
-		modc_connected is called on the client and
-		mods_connected is called on the server.
-		The client should call client_entergame when the
-		mod has done it's initilization.
-		
-	Client -> ENTERGAME -> Server
-		Tells the server to start sending snapshots.
-		client_entergame and server_client_enter is called.
-*/
-
-
-enum
-{
-	NETMSG_NULL=0,
-	
-	/* the first thing sent by the client
-	contains the version info for the client */
-	NETMSG_INFO=1,
-	
-	/* sent by server */
-	NETMSG_MAP_CHANGE,		/* sent when client should switch map */
-	NETMSG_MAP_DATA,		/* map transfer, contains a chunk of the map file */
-	NETMSG_SNAP,			/* normal snapshot, multiple parts */
-	NETMSG_SNAPEMPTY,		/* empty snapshot */
-	NETMSG_SNAPSINGLE,		/* ? */
-	NETMSG_SNAPSMALL,		/* */
-	NETMSG_INPUTTIMING,		/* reports how off the input was */
-	NETMSG_RCON_AUTH_STATUS,/* result of the authentication */
-	NETMSG_RCON_LINE,		/* line that should be printed to the remote console */
-
-	NETMSG_AUTH_CHALLANGE,	/* */
-	NETMSG_AUTH_RESULT,		/* */
-	
-	/* sent by client */
-	NETMSG_READY,			/* */
-	NETMSG_ENTERGAME,
-	NETMSG_INPUT,			/* contains the inputdata from the client */
-	NETMSG_RCON_CMD,		/* */ 
-	NETMSG_RCON_AUTH,		/* */
-	NETMSG_REQUEST_MAP_DATA,/* */
-
-	NETMSG_AUTH_START,		/* */
-	NETMSG_AUTH_RESPONSE,	/* */
-	
-	/* sent by both */
-	NETMSG_PING,
-	NETMSG_PING_REPLY,
-	NETMSG_ERROR
-};
-
-
-/* this should be revised */
-enum
-{
-	MAX_CLANNAME_LENGTH=32,
-	MAX_INPUT_SIZE=128,
-	MAX_SNAPSHOT_PACKSIZE=900
-};
diff --git a/src/engine/e_server_interface.h b/src/engine/e_server_interface.h
deleted file mode 100644
index c325b9a1..00000000
--- a/src/engine/e_server_interface.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef ENGINE_SERVER_INTERFACE_H
-#define ENGINE_SERVER_INTERFACE_H
-
-#include "e_if_other.h"
-#include "e_if_server.h"
-#include "e_if_msg.h"
-#include "e_if_mods.h"
-
-#include "e_console.h" /* TODO: clean this up*/
-
-#endif
diff --git a/src/engine/e_snapshot.cpp b/src/engine/e_snapshot.cpp
deleted file mode 100644
index 65487665..00000000
--- a/src/engine/e_snapshot.cpp
+++ /dev/null
@@ -1,571 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <stdlib.h>
-#include "e_snapshot.h"
-#include "e_engine.h"
-#include "e_compression.h"
-#include "e_common_interface.h"
-
-
-/* TODO: strange arbitrary number */
-static short item_sizes[64] = {0};
-
-void snap_set_staticsize(int itemtype, int size)
-{
-	item_sizes[itemtype] = size;
-}
-
-CSnapshotItem *CSnapshot::GetItem(int Index)
-{
-	return (CSnapshotItem *)(DataStart() + Offsets()[Index]);
-}
-
-int CSnapshot::GetItemSize(int Index)
-{
-    if(Index == m_NumItems-1)
-        return (m_DataSize - Offsets()[Index]) - sizeof(CSnapshotItem);
-    return (Offsets()[Index+1] - Offsets()[Index]) - sizeof(CSnapshotItem);
-}
-
-int CSnapshot::GetItemIndex(int Key)
-{
-    /* TODO: OPT: this should not be a linear search. very bad */
-    for(int i = 0; i < m_NumItems; i++)
-    {
-        if(GetItem(i)->Key() == Key)
-            return i;
-    }
-    return -1;
-}
-
-// TODO: clean up this
-typedef struct 
-{
-	int num;
-	int keys[64];
-	int index[64];
-} ITEMLIST;
-
-static ITEMLIST sorted[256];
-
-int CSnapshot::GenerateHash()
-{
-    for(int i = 0; i < 256; i++)
-    	sorted[i].num = 0;
-    	
-    for(int i = 0; i < m_NumItems; i++)
-    {
-    	int Key = GetItem(i)->Key();
-    	int HashID = ((Key>>8)&0xf0) | (Key&0xf);
-    	if(sorted[HashID].num != 64)
-    	{
-			sorted[HashID].index[sorted[HashID].num] = i;
-			sorted[HashID].keys[sorted[HashID].num] = Key;
-			sorted[HashID].num++;
-		}
-	}
-    return 0;
-}
-
-int CSnapshot::GetItemIndexHashed(int Key)
-{
-   	int HashID = ((Key>>8)&0xf0) | (Key&0xf);
-   	for(int i = 0; i < sorted[HashID].num; i++)
-   	{
-   		if(sorted[HashID].keys[i] == Key)
-   			return sorted[HashID].index[i];
-	}
-	
-	return -1;
-}
-
-
-
-static const int MAX_ITEMS = 512;
-static CSnapshotDelta empty = {0,0,0,{0}};
-
-CSnapshotDelta *CSnapshot::EmptyDelta()
-{
-	return &empty;
-}
-
-int CSnapshot::Crc()
-{
-	int crc = 0;
-	
-	for(int i = 0; i < m_NumItems; i++)
-	{
-		CSnapshotItem *pItem = GetItem(i);
-		int Size = GetItemSize(i);
-		
-		for(int b = 0; b < Size/4; b++)
-			crc += pItem->Data()[b];
-	}
-	return crc;
-}
-
-void CSnapshot::DebugDump()
-{
-	dbg_msg("snapshot", "data_size=%d num_items=%d", m_DataSize, m_NumItems);
-	for(int i = 0; i < m_NumItems; i++)
-	{
-		CSnapshotItem *pItem = GetItem(i);
-		int Size = GetItemSize(i);
-		dbg_msg("snapshot", "\ttype=%d id=%d", pItem->Type(), pItem->ID());
-		for(int b = 0; b < Size/4; b++)
-			dbg_msg("snapshot", "\t\t%3d %12d\t%08x", b, pItem->Data()[b], pItem->Data()[b]);
-	}
-}
-
-
-// TODO: remove these
-int snapshot_data_rate[0xffff] = {0};
-int snapshot_data_updates[0xffff] = {0};
-static int snapshot_current = 0;
-
-static int diff_item(int *past, int *current, int *out, int size)
-{
-	int needed = 0;
-	while(size)
-	{
-		*out = *current-*past;
-		needed |= *out;
-		out++;
-		past++;
-		current++;
-		size--;
-	}
-	
-	return needed;
-}
-
-static void undiff_item(int *past, int *diff, int *out, int size)
-{
-	while(size)
-	{
-		*out = *past+*diff;
-		
-		if(*diff == 0)
-			snapshot_data_rate[snapshot_current] += 1;
-		else
-		{
-			unsigned char buf[16];
-			unsigned char *end = vint_pack(buf,  *diff);
-			snapshot_data_rate[snapshot_current] += (int)(end - (unsigned char*)buf) * 8;
-		}
-		
-		out++;
-		past++;
-		diff++;
-		size--;
-	}
-}
-
-
-/* TODO: OPT: this should be made much faster */
-int CSnapshot::CreateDelta(CSnapshot *from, CSnapshot *to, void *dstdata)
-{
-	static PERFORMACE_INFO hash_scope = {"hash", 0};
-	CSnapshotDelta *delta = (CSnapshotDelta *)dstdata;
-	int *data = (int *)delta->m_pData;
-	int i, itemsize, pastindex;
-	CSnapshotItem *pFromItem;
-	CSnapshotItem *pCurItem;
-	CSnapshotItem *pPastItem;
-	int count = 0;
-	int size_count = 0;
-	
-	delta->m_NumDeletedItems = 0;
-	delta->m_NumUpdateItems = 0;
-	delta->m_NumTempItems = 0;
-	
-	perf_start(&hash_scope);
-	to->GenerateHash();
-	perf_end();
-
-	/* pack deleted stuff */
-	{
-		static PERFORMACE_INFO scope = {"delete", 0};
-		perf_start(&scope);
-		
-		for(i = 0; i < from->m_NumItems; i++)
-		{
-			pFromItem = from->GetItem(i);
-			if(to->GetItemIndexHashed(pFromItem->Key()) == -1)
-			{
-				/* deleted */
-				delta->m_NumDeletedItems++;
-				*data = pFromItem->Key();
-				data++;
-			}
-		}
-		
-		perf_end();
-	}
-	
-	perf_start(&hash_scope);
-	from->GenerateHash();
-	perf_end();
-	
-	/* pack updated stuff */
-	{
-		static PERFORMACE_INFO scope = {"update", 0};
-		int pastindecies[1024];
-		perf_start(&scope);
-
-		/* fetch previous indices */
-		/* we do this as a separate pass because it helps the cache */
-		{
-			static PERFORMACE_INFO scope = {"find", 0};
-			perf_start(&scope);
-			for(i = 0; i < to->m_NumItems; i++)
-			{
-				pCurItem = to->GetItem(i);  /* O(1) .. O(n) */
-				pastindecies[i] = from->GetItemIndexHashed(pCurItem->Key()); /* O(n) .. O(n^n)*/
-			}
-			perf_end();
-		}		
-			
-		for(i = 0; i < to->m_NumItems; i++)
-		{
-			/* do delta */
-			itemsize = to->GetItemSize(i); /* O(1) .. O(n) */
-			pCurItem = to->GetItem(i);  /* O(1) .. O(n) */
-			pastindex = pastindecies[i];
-			
-			if(pastindex != -1)
-			{
-				static PERFORMACE_INFO scope = {"diff", 0};
-				int *item_data_dst = data+3;
-				perf_start(&scope);
-		
-				pPastItem = from->GetItem(pastindex);
-				
-				if(item_sizes[pCurItem->Type()])
-					item_data_dst = data+2;
-				
-				if(diff_item((int*)pPastItem->Data(), (int*)pCurItem->Data(), item_data_dst, itemsize/4))
-				{
-					
-					*data++ = pCurItem->Type();
-					*data++ = pCurItem->ID();
-					if(!item_sizes[pCurItem->Type()])
-						*data++ = itemsize/4;
-					data += itemsize/4;
-					delta->m_NumUpdateItems++;
-				}
-				perf_end();
-			}
-			else
-			{
-				static PERFORMACE_INFO scope = {"copy", 0};
-				perf_start(&scope);
-				
-				*data++ = pCurItem->Type();
-				*data++ = pCurItem->ID();
-				if(!item_sizes[pCurItem->Type()])
-					*data++ = itemsize/4;
-				
-				mem_copy(data, pCurItem->Data(), itemsize);
-				size_count += itemsize;
-				data += itemsize/4;
-				delta->m_NumUpdateItems++;
-				count++;
-				
-				perf_end();
-			}
-		}
-		
-		perf_end();
-	}
-	
-	if(0)
-	{
-		dbg_msg("snapshot", "%d %d %d",
-			delta->m_NumDeletedItems,
-			delta->m_NumUpdateItems,
-			delta->m_NumTempItems);
-	}
-
-	/*
-	// TODO: pack temp stuff
-	
-	// finish
-	//mem_copy(delta->offsets, deleted, delta->num_deleted_items*sizeof(int));
-	//mem_copy(&(delta->offsets[delta->num_deleted_items]), update, delta->num_update_items*sizeof(int));
-	//mem_copy(&(delta->offsets[delta->num_deleted_items+delta->num_update_items]), temp, delta->num_temp_items*sizeof(int));
-	//mem_copy(delta->data_start(), data, data_size);
-	//delta->data_size = data_size;
-	* */
-	
-	if(!delta->m_NumDeletedItems && !delta->m_NumUpdateItems && !delta->m_NumTempItems)
-		return 0;
-	
-	return (int)((char*)data-(char*)dstdata);
-}
-
-static int range_check(void *end, void *ptr, int size)
-{
-	if((const char *)ptr + size > (const char *)end)
-		return -1;
-	return 0;
-}
-
-int CSnapshot::UnpackDelta(CSnapshot *from, CSnapshot *to, void *srcdata, int data_size)
-{
-	CSnapshotBuilder builder;
-	CSnapshotDelta *delta = (CSnapshotDelta *)srcdata;
-	int *data = (int *)delta->m_pData;
-	int *end = (int *)(((char *)srcdata + data_size));
-	
-	CSnapshotItem *fromitem;
-	int i, d, keep, itemsize;
-	int *deleted;
-	int id, type, key;
-	int fromindex;
-	int *newdata;
-			
-	builder.Init();
-	
-	/* unpack deleted stuff */
-	deleted = data;
-	data += delta->m_NumDeletedItems;
-	if(data > end)
-		return -1;
-
-	/* copy all non deleted stuff */
-	for(i = 0; i < from->m_NumItems; i++)
-	{
-		/* dbg_assert(0, "fail!"); */
-		fromitem = from->GetItem(i);
-		itemsize = from->GetItemSize(i); 
-		keep = 1;
-		for(d = 0; d < delta->m_NumDeletedItems; d++)
-		{
-			if(deleted[d] == fromitem->Key())
-			{
-				keep = 0;
-				break;
-			}
-		}
-		
-		if(keep)
-		{
-			/* keep it */
-			mem_copy(
-				builder.NewItem(fromitem->Type(), fromitem->ID(), itemsize),
-				fromitem->Data(), itemsize);
-		}
-	}
-		
-	/* unpack updated stuff */
-	for(i = 0; i < delta->m_NumUpdateItems; i++)
-	{
-		if(data+2 > end)
-			return -1;
-		
-		type = *data++;
-		id = *data++;
-		if(item_sizes[type])
-			itemsize = item_sizes[type];
-		else
-		{
-			if(data+1 > end)
-				return -2;
-			itemsize = (*data++) * 4;
-		}
-		snapshot_current = type;
-		
-		if(range_check(end, data, itemsize) || itemsize < 0) return -3;
-		
-		key = (type<<16)|id;
-		
-		/* create the item if needed */
-		newdata = builder.GetItemData(key);
-		if(!newdata)
-			newdata = (int *)builder.NewItem(key>>16, key&0xffff, itemsize);
-
-		/*if(range_check(end, newdata, itemsize)) return -4;*/
-			
-		fromindex = from->GetItemIndex(key);
-		if(fromindex != -1)
-		{
-			/* we got an update so we need to apply the diff */
-			undiff_item((int *)from->GetItem(fromindex)->Data(), data, newdata, itemsize/4);
-			snapshot_data_updates[snapshot_current]++;
-		}
-		else /* no previous, just copy the data */
-		{
-			mem_copy(newdata, data, itemsize);
-			snapshot_data_rate[snapshot_current] += itemsize*8;
-			snapshot_data_updates[snapshot_current]++;
-		}
-			
-		data += itemsize/4;
-	}
-	
-	/* finish up */
-	return builder.Finish(to);
-}
-
-/* CSnapshotStorage */
-
-void CSnapshotStorage::Init()
-{
-	m_pFirst = 0;
-	m_pLast = 0;
-}
-
-void CSnapshotStorage::PurgeAll()
-{
-	CHolder *pHolder = m_pFirst;
-	CHolder *pNext;
-
-	while(pHolder)
-	{
-		pNext = pHolder->m_pNext;
-		mem_free(pHolder);
-		pHolder = pNext;
-	}
-
-	/* no more snapshots in storage */
-	m_pFirst = 0;
-	m_pLast = 0;
-}
-
-void CSnapshotStorage::PurgeUntil(int Tick)
-{
-	CHolder *pHolder = m_pFirst;
-	CHolder *pNext;
-	
-	while(pHolder)
-	{
-		pNext = pHolder->m_pNext;
-		if(pHolder->m_Tick >= Tick)
-			return; /* no more to remove */
-		mem_free(pHolder);
-		
-		/* did we come to the end of the list? */
-        if (!pNext)
-            break;
-
-		m_pFirst = pNext;
-		pNext->m_pPrev = 0x0;
-		
-		pHolder = pNext;
-	}
-	
-	/* no more snapshots in storage */
-	m_pFirst = 0;
-	m_pLast = 0;
-}
-
-void CSnapshotStorage::Add(int Tick, int64 Tagtime, int DataSize, void *pData, int CreateAlt)
-{
-	/* allocate memory for holder + snapshot_data */
-	int TotalSize = sizeof(CHolder)+DataSize;
-	
-	if(CreateAlt)
-		TotalSize += DataSize;
-	
-	CHolder *pHolder = (CHolder *)mem_alloc(TotalSize, 1);
-	
-	/* set data */
-	pHolder->m_Tick = Tick;
-	pHolder->m_Tagtime = Tagtime;
-	pHolder->m_SnapSize = DataSize;
-	pHolder->m_pSnap = (CSnapshot*)(pHolder+1);
-	mem_copy(pHolder->m_pSnap, pData, DataSize);
-
-	if(CreateAlt) /* create alternative if wanted */
-	{
-		pHolder->m_pAltSnap = (CSnapshot*)(((char *)pHolder->m_pSnap) + DataSize);
-		mem_copy(pHolder->m_pAltSnap, pData, DataSize);
-	}
-	else
-		pHolder->m_pAltSnap = 0;
-		
-	
-	/* link */
-	pHolder->m_pNext = 0;
-	pHolder->m_pPrev = m_pLast;
-	if(m_pLast)
-		m_pLast->m_pNext = pHolder;
-	else
-		m_pFirst = pHolder;
-	m_pLast = pHolder;
-}
-
-int CSnapshotStorage::Get(int Tick, int64 *pTagtime, CSnapshot **ppData, CSnapshot **ppAltData)
-{
-	CHolder *pHolder = m_pFirst;
-	
-	while(pHolder)
-	{
-		if(pHolder->m_Tick == Tick)
-		{
-			if(pTagtime)
-				*pTagtime = pHolder->m_Tagtime;
-			if(ppData)
-				*ppData = pHolder->m_pSnap;
-			if(ppAltData)
-				*ppData = pHolder->m_pAltSnap;
-			return pHolder->m_SnapSize;
-		}
-		
-		pHolder = pHolder->m_pNext;
-	}
-	
-	return -1;
-}
-
-/* CSnapshotBuilder */
-
-void CSnapshotBuilder::Init()
-{
-	m_DataSize = 0;
-	m_NumItems = 0;
-}
-
-CSnapshotItem *CSnapshotBuilder::GetItem(int Index) 
-{
-	return (CSnapshotItem *)&(m_aData[m_aOffsets[Index]]);
-}
-
-int *CSnapshotBuilder::GetItemData(int key)
-{
-	int i;
-	for(i = 0; i < m_NumItems; i++)
-	{
-		if(GetItem(i)->Key() == key)
-			return (int *)GetItem(i)->Data();
-	}
-	return 0;
-}
-
-int CSnapshotBuilder::Finish(void *snapdata)
-{
-	/* flattern and make the snapshot */
-	CSnapshot *pSnap = (CSnapshot *)snapdata;
-	int OffsetSize = sizeof(int)*m_NumItems;
-	pSnap->m_DataSize = m_DataSize;
-	pSnap->m_NumItems = m_NumItems;
-	mem_copy(pSnap->Offsets(), m_aOffsets, OffsetSize);
-	mem_copy(pSnap->DataStart(), m_aData, m_DataSize);
-	return sizeof(CSnapshot) + OffsetSize + m_DataSize;
-}
-
-void *CSnapshotBuilder::NewItem(int Type, int ID, int Size)
-{
-	CSnapshotItem *pObj = (CSnapshotItem *)(m_aData + m_DataSize);
-
-	mem_zero(pObj, sizeof(CSnapshotItem) + Size);
-	pObj->m_TypeAndID = (Type<<16)|ID;
-	m_aOffsets[m_NumItems] = m_DataSize;
-	m_DataSize += sizeof(CSnapshotItem) + Size;
-	m_NumItems++;
-	
-	dbg_assert(m_DataSize < CSnapshot::MAX_SIZE, "too much data");
-	dbg_assert(m_NumItems < MAX_ITEMS, "too many items");
-
-	return pObj->Data();
-}
diff --git a/src/engine/editor.h b/src/engine/editor.h
new file mode 100644
index 00000000..32a5cc93
--- /dev/null
+++ b/src/engine/editor.h
@@ -0,0 +1,16 @@
+#ifndef ENGINE_EDITOR_H
+#define ENGINE_EDITOR_H
+#include "kernel.h"
+
+class IEditor : public IInterface
+{
+	MACRO_INTERFACE("editor", 0)
+public:
+
+	virtual ~IEditor() {}
+	virtual void Init() = 0;
+	virtual void UpdateAndRender() = 0;
+};
+
+extern IEditor *CreateEditor();
+#endif
diff --git a/src/engine/graphics.h b/src/engine/graphics.h
new file mode 100644
index 00000000..4d3c0bc0
--- /dev/null
+++ b/src/engine/graphics.h
@@ -0,0 +1,151 @@
+#ifndef ENGINE_GRAPHICS_H
+#define ENGINE_GRAPHICS_H
+
+#include "kernel.h"
+
+class CImageInfo
+{
+public:
+	enum
+	{
+		FORMAT_AUTO=-1,
+		FORMAT_RGB=0,
+		FORMAT_RGBA=1,
+		FORMAT_ALPHA=2,
+	};
+
+	/* Variable: width
+		Contains the width of the image */
+	int m_Width;
+	
+	/* Variable: height
+		Contains the height of the image */
+	int m_Height;
+	
+	/* Variable: format
+		Contains the format of the image. See <Image Formats> for more information. */
+	int m_Format;
+
+	/* Variable: data
+		Pointer to the image data. */
+	void *m_pData;
+};
+
+/*
+	Structure: CVideoMode
+*/
+class CVideoMode
+{
+public:
+	int m_Width, m_Height;
+	int m_Red, m_Green, m_Blue;
+};
+
+class IGraphics : public IInterface
+{
+	MACRO_INTERFACE("graphics", 0)
+protected:
+	int m_ScreenWidth;
+	int m_ScreenHeight;
+public:
+	/* Constants: Texture Loading Flags
+		TEXLOAD_NORESAMPLE - Prevents the texture from any resampling
+	*/
+	enum
+	{
+		TEXLOAD_NORESAMPLE=1,
+	};
+
+	int ScreenWidth() const { return m_ScreenWidth; }
+	int ScreenHeight() const { return m_ScreenHeight; }
+	float ScreenAspect() const { return (float)ScreenWidth()/(float)ScreenHeight(); }
+	
+	virtual void Clear(float r, float g, float b) = 0;
+	
+	virtual void ClipEnable(int x, int y, int w, int h) = 0;
+	virtual void ClipDisable() = 0;
+	
+	virtual void MapScreen(float TopLeftX, float TopLeftY, float BottomRightX, float BottomRightY) = 0;
+	virtual void GetScreen(float *pTopLeftX, float *pTopLeftY, float *pBottomRightX, float *pBottomRightY) = 0;
+	
+	// TODO: These should perhaps not be virtuals
+	virtual void BlendNone() = 0;
+	virtual void BlendNormal() = 0;
+	virtual void BlendAdditive() = 0;
+	virtual int MemoryUsage() const = 0;
+	
+	virtual int LoadPNG(CImageInfo *pImg, const char *pFilename) =0;
+	virtual int UnloadTexture(int Index) = 0;
+	virtual int LoadTextureRaw(int Width, int Height, int Format, const void *pData, int StoreFormat, int Flags) = 0;
+	virtual int LoadTexture(const char *pFilename, int StoreFormat, int Flags) = 0;
+	virtual void TextureSet(int TextureID) = 0;
+	
+	struct CLineItem
+	{
+		float m_X0, m_Y0, m_X1, m_Y1;
+		CLineItem() {}
+		CLineItem(float x0, float y0, float x1, float y1) : m_X0(x0), m_Y0(y0), m_X1(x1), m_Y1(y1) {}
+	};
+	virtual void LinesBegin() = 0;
+	virtual void LinesEnd() = 0;
+	virtual void LinesDraw(const CLineItem *pArray, int Num) = 0;
+	
+	virtual void QuadsBegin() = 0;
+	virtual void QuadsEnd() = 0;
+	virtual void QuadsSetRotation(float Angle) = 0;
+	virtual void QuadsSetSubset(float TopLeftY, float TopLeftV, float BottomRightU, float BottomRightV) = 0;
+	virtual void QuadsSetSubsetFree(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) = 0;
+	
+	struct CQuadItem
+	{
+		float m_X, m_Y, m_Width, m_Height;
+		CQuadItem() {}
+		CQuadItem(float x, float y, float w, float h) : m_X(x), m_Y(y), m_Width(w), m_Height(h) {}
+	};
+	virtual void QuadsDraw(CQuadItem *pArray, int Num) = 0;
+	virtual void QuadsDrawTL(const CQuadItem *pArray, int Num) = 0;
+	
+	struct CFreeformItem
+	{
+		float m_X0, m_Y0, m_X1, m_Y1, m_X2, m_Y2, m_X3, m_Y3;
+		CFreeformItem() {}
+		CFreeformItem(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
+			: m_X0(x0), m_Y0(y0), m_X1(x1), m_Y1(y1), m_X2(x2), m_Y2(y2), m_X3(x3), m_Y3(y3) {}
+	};
+	virtual void QuadsDrawFreeform(const CFreeformItem *pArray, int Num) = 0;
+	virtual void QuadsText(float x, float y, float Size, float r, float g, float b, float a, const char *pText) = 0;
+	
+	struct CColorVertex
+	{
+		int m_Index;
+		float m_R, m_G, m_B, m_A;
+		CColorVertex() {}
+		CColorVertex(int i, float r, float g, float b, float a) : m_Index(i), m_R(r), m_G(g), m_B(b), m_A(a) {}
+	};
+	virtual void SetColorVertex(const CColorVertex *pArray, int Num) = 0;
+	virtual void SetColor(float r, float g, float b, float a) = 0;
+	
+	virtual void TakeScreenshot() = 0;
+	virtual int GetVideoModes(CVideoMode *pModes, int MaxModes) = 0;
+
+	virtual void Swap() = 0;
+};
+
+class IEngineGraphics : public IGraphics
+{
+	MACRO_INTERFACE("enginegraphics", 0)
+public:
+	virtual bool Init() = 0;
+	virtual void Shutdown() = 0;
+	
+	virtual void Minimize() = 0;
+	virtual void Maximize() = 0;
+	
+	virtual int WindowActive() = 0;
+	virtual int WindowOpen() = 0;
+	
+};
+
+extern IEngineGraphics *CreateEngineGraphics();
+
+#endif
diff --git a/src/engine/input.h b/src/engine/input.h
new file mode 100644
index 00000000..168614c8
--- /dev/null
+++ b/src/engine/input.h
@@ -0,0 +1,89 @@
+#ifndef ENGINE_INPUT_H
+#define ENGINE_INPUT_H
+
+#include "kernel.h"
+
+extern const char g_aaKeyStrings[512][16];
+
+class IInput : public IInterface
+{
+	MACRO_INTERFACE("input", 0)
+public:
+	class CEvent
+	{
+	public:
+		int m_Flags;
+		int m_Unicode;
+		int m_Key;
+	};
+
+protected:
+	enum
+	{
+		INPUT_BUFFER_SIZE=32
+	};
+
+	// quick access to events
+	int m_NumEvents;
+	IInput::CEvent m_aInputEvents[INPUT_BUFFER_SIZE];
+
+	//quick access to input
+	struct
+	{
+		unsigned char m_Presses;
+		unsigned char m_Releases;
+	} m_aInputCount[2][1024];
+
+	unsigned char m_aInputState[2][1024];
+	int m_InputCurrent;
+
+	int KeyWasPressed(int Key) { return m_aInputState[m_InputCurrent^1][Key]; }
+
+public:	
+	enum
+	{
+		FLAG_PRESS=1,
+		FLAG_RELEASE=2,
+		FLAG_REPEAT=4
+	};
+
+	// events
+	int NumEvents() const { return m_NumEvents; }
+	void ClearEvents() { m_NumEvents = 0; }
+	CEvent GetEvent(int Index) const
+	{ 
+		if(Index < 0 || Index >= m_NumEvents)
+		{
+			IInput::CEvent e = {0,0};
+			return e;
+		}
+		return m_aInputEvents[Index];
+	}
+	
+	// keys
+	int KeyPressed(int Key) { return m_aInputState[m_InputCurrent][Key]; }
+	int KeyReleases(int Key) { return m_aInputCount[m_InputCurrent][Key].m_Releases; }
+	int KeyPresses(int Key) { return m_aInputCount[m_InputCurrent][Key].m_Presses; }
+	int KeyDown(int Key) { return KeyPressed(Key)&&!KeyWasPressed(Key); }
+	const char *KeyName(int Key) { return (Key >= 0 && Key < 512) ? g_aaKeyStrings[Key] : g_aaKeyStrings[0]; }
+	
+	//
+	virtual void MouseModeRelative() = 0;
+	virtual void MouseModeAbsolute() = 0;
+	virtual int MouseDoubleClick() = 0;
+	
+	virtual void MouseRelative(int *x, int *y) = 0;
+};
+
+
+class IEngineInput : public IInput
+{
+	MACRO_INTERFACE("engineinput", 0)
+public:
+	virtual void Init() = 0;
+	virtual void Update() = 0;
+};
+
+extern IEngineInput *CreateEngineInput();
+
+#endif
diff --git a/src/engine/kernel.h b/src/engine/kernel.h
new file mode 100644
index 00000000..6a72690f
--- /dev/null
+++ b/src/engine/kernel.h
@@ -0,0 +1,66 @@
+#ifndef ENGINE_KERNEL_H
+#define ENGINE_KERNEL_H
+
+#include <base/system.h>
+
+class IKernel;
+class IInterface;
+
+class IInterface
+{
+	// friend with the kernel implementation
+	friend class CKernel;
+	IKernel *m_pKernel;
+protected:
+	IKernel *Kernel() { return m_pKernel; }
+public:
+	IInterface() : m_pKernel(0) {}
+	virtual ~IInterface() {}
+	
+	//virtual unsigned InterfaceID() = 0;
+	//virtual const char *InterfaceName() = 0;
+};
+
+#define MACRO_INTERFACE(Name, ver) \
+	public: \
+		static const char *InterfaceName() { return Name; } \
+	private:
+	
+		//virtual unsigned InterfaceID() { return INTERFACE_ID; }
+		//virtual const char *InterfaceName() { return name; }
+
+
+// This kernel thingie makes the structure very flat and basiclly singletons.
+// I'm not sure if this is a good idea but it works for now.
+class IKernel
+{
+	// hide the implementation
+	virtual bool RegisterInterfaceImpl(const char *InterfaceName, IInterface *pInterface) = 0;
+	virtual bool ReregisterInterfaceImpl(const char *InterfaceName, IInterface *pInterface) = 0;
+	virtual IInterface *RequestInterfaceImpl(const char *InterfaceName) = 0;
+public:
+	static IKernel *Create();
+	virtual ~IKernel() {}
+
+	// templated access to handle pointer convertions and interface names
+	template<class TINTERFACE>
+	bool RegisterInterface(TINTERFACE *pInterface)
+	{
+		return RegisterInterfaceImpl(TINTERFACE::InterfaceName(), pInterface);
+	}
+	template<class TINTERFACE>
+	bool ReregisterInterface(TINTERFACE *pInterface)
+	{
+		return ReregisterInterfaceImpl(TINTERFACE::InterfaceName(), pInterface);
+	}
+	
+	// Usage example:
+	//		IMyInterface *pMyHandle = Kernel()->RequestInterface<IMyInterface>()
+	template<class TINTERFACE>
+	TINTERFACE *RequestInterface()
+	{
+		return reinterpret_cast<TINTERFACE *>(RequestInterfaceImpl(TINTERFACE::InterfaceName()));
+	}
+};
+
+#endif
diff --git a/src/engine/e_keys.h b/src/engine/keys.h
index cb4ca371..cb4ca371 100644
--- a/src/engine/e_keys.h
+++ b/src/engine/keys.h
diff --git a/src/engine/map.h b/src/engine/map.h
new file mode 100644
index 00000000..2c285f26
--- /dev/null
+++ b/src/engine/map.h
@@ -0,0 +1,32 @@
+#ifndef ENGINE_MAP_H
+#define ENGINE_MAP_H
+
+#include "kernel.h"
+
+class IMap : public IInterface
+{
+	MACRO_INTERFACE("map", 0)
+public:
+	virtual void *GetData(int Index) = 0;
+	virtual void *GetDataSwapped(int Index) = 0;
+	virtual void UnloadData(int Index) = 0;
+	virtual void *GetItem(int Index, int *Type, int *pId) = 0;
+	virtual void GetType(int Type, int *pStart, int *pNum) = 0;
+	virtual void *FindItem(int Type, int Id) = 0;
+	virtual int NumItems() = 0;
+};
+
+
+class IEngineMap : public IMap
+{
+	MACRO_INTERFACE("enginemap", 0)
+public:
+	virtual bool Load(const char *pMapName) = 0;
+	virtual bool IsLoaded() = 0;
+	virtual void Unload() = 0;
+	virtual unsigned Crc() = 0;
+};
+
+extern IEngineMap *CreateEngineMap();
+
+#endif
diff --git a/src/engine/masterserver.h b/src/engine/masterserver.h
new file mode 100644
index 00000000..9d16e85f
--- /dev/null
+++ b/src/engine/masterserver.h
@@ -0,0 +1,40 @@
+#ifndef ENGINE_MASTERSERVER_H
+#define ENGINE_MASTERSERVER_H
+
+#include "kernel.h"
+
+class IMasterServer : public IInterface
+{
+	MACRO_INTERFACE("masterserver", 0)
+public:
+
+	enum
+	{
+		MAX_MASTERSERVERS=4
+	};
+
+	virtual void Init(class CEngine *pEngine) = 0;
+	virtual void SetDefault() = 0;
+	virtual int Load() = 0;
+	virtual int Save() = 0;
+
+	virtual int RefreshAddresses() = 0;
+	virtual void Update() = 0;
+	virtual int IsRefreshing() = 0;
+	virtual void DumpServers() = 0;
+	virtual NETADDR GetAddr(int Index) = 0;
+	virtual const char *GetName(int Index) = 0;
+};
+
+class IEngineMasterServer : public IMasterServer
+{
+	MACRO_INTERFACE("enginemasterserver", 0)
+public:
+};
+
+extern IEngineMasterServer *CreateEngineMasterServer();
+
+#endif
+
+
+
diff --git a/src/engine/message.h b/src/engine/message.h
index 6de407ed..3ffc488f 100644
--- a/src/engine/message.h
+++ b/src/engine/message.h
@@ -1,8 +1,16 @@
+#ifndef ENGINE_MESSAGE_H
+#define ENGINE_MESSAGE_H
 
+#include <engine/shared/packer.h>
 
-class CMessage
+class CMsgPacker : public CPacker
 {
 public:
-	virtual bool Pack(void *pData, unsigned MaxDataSize);
-	virtual bool Unpack(const void *pData, unsigned DataSize);
+	CMsgPacker(int Type)
+	{
+		Reset();
+		AddInt(Type);
+	}
 };
+
+#endif
diff --git a/src/engine/server.h b/src/engine/server.h
new file mode 100644
index 00000000..52e6ec6a
--- /dev/null
+++ b/src/engine/server.h
@@ -0,0 +1,81 @@
+#ifndef ENGINE_SERVER_H
+#define ENGINE_SERVER_H
+#include "kernel.h"
+#include "message.h"
+
+class IServer : public IInterface
+{
+	MACRO_INTERFACE("server", 0)
+protected:
+	int m_CurrentGameTick;
+	int m_TickSpeed;
+
+public:
+	/*
+		Structure: CClientInfo
+	*/
+	struct CClientInfo
+	{
+		const char *m_pName;
+		int m_Latency;
+	};
+	
+	int Tick() const { return m_CurrentGameTick; }
+	int TickSpeed() const { return m_TickSpeed; }
+
+	virtual const char *ClientName(int ClientID) = 0;
+	virtual bool ClientIngame(int ClientID) = 0;
+	virtual int GetClientInfo(int ClientID, CClientInfo *pInfo) = 0;
+	virtual void GetClientIP(int ClientID, char *pIPString, int Size) = 0;
+	virtual int *LatestInput(int ClientID, int *pSize) = 0;
+	
+	virtual int SendMsg(CMsgPacker *pMsg, int Flags, int ClientID) = 0;
+
+	template<class T>
+	int SendPackMsg(T *pMsg, int Flags, int ClientID)
+	{
+		CMsgPacker Packer(pMsg->MsgID());
+		if(pMsg->Pack(&Packer))
+			return -1;
+		return SendMsg(&Packer, Flags, ClientID);
+	}
+	
+	virtual void SetBrowseInfo(char const *pGameType, int Progression) = 0;
+	virtual void SetClientName(int ClientID, char const *pName) = 0;
+	virtual void SetClientScore(int ClientID, int Score) = 0;
+	
+	virtual int SnapNewID() = 0;
+	virtual void SnapFreeID(int ID) = 0;
+	virtual void *SnapNewItem(int Type, int Id, int Size) = 0;
+
+	virtual void SnapSetStaticsize(int ItemType, int Size) = 0;
+};
+
+class IGameServer : public IInterface
+{
+	MACRO_INTERFACE("gameserver", 0)
+protected:
+public:
+	virtual void OnInit() = 0;
+	virtual void OnConsoleInit() = 0;
+	virtual void OnShutdown() = 0;
+	
+	virtual void OnTick() = 0;
+	virtual void OnPreSnap() = 0;
+	virtual void OnSnap(int ClientID) = 0;
+	virtual void OnPostSnap() = 0;
+	
+	virtual void OnMessage(int MsgId, CUnpacker *pUnpacker, int ClientID) = 0;
+
+	virtual void OnClientConnected(int ClientID) = 0;
+	virtual void OnClientEnter(int ClientID) = 0;
+	virtual void OnClientDrop(int ClientID) = 0;
+	virtual void OnClientDirectInput(int ClientID, void *pInput) = 0;
+	virtual void OnClientPredictedInput(int ClientID, void *pInput) = 0;
+	
+	virtual const char *Version() = 0;
+	virtual const char *NetVersion() = 0;
+};
+
+extern IGameServer *CreateGameServer();
+#endif
diff --git a/src/engine/server/es_register.cpp b/src/engine/server/es_register.cpp
deleted file mode 100644
index 0eb5dba5..00000000
--- a/src/engine/server/es_register.cpp
+++ /dev/null
@@ -1,271 +0,0 @@
-#include <string.h>
-#include <base/system.h>
-#include <engine/e_network.h>
-#include <engine/e_config.h>
-#include <engine/e_engine.h>
-
-#include <mastersrv/mastersrv.h>
-
-extern CNetServer *m_pNetServer;
-
-enum
-{
-	REGISTERSTATE_START=0,
-	REGISTERSTATE_UPDATE_ADDRS,
-	REGISTERSTATE_QUERY_COUNT,
-	REGISTERSTATE_HEARTBEAT,
-	REGISTERSTATE_REGISTERED,
-	REGISTERSTATE_ERROR
-};
-
-static int register_state = REGISTERSTATE_START;
-static int64 register_state_start = 0;
-static int register_first = 1;
-static int register_count = 0;
-
-static void register_new_state(int state)
-{
-	register_state = state;
-	register_state_start = time_get();
-}
-
-static void register_send_fwcheckresponse(NETADDR *pAddr)
-{
-	CNetChunk Packet;
-	Packet.m_ClientID = -1;
-	Packet.m_Address = *pAddr;
-	Packet.m_Flags = NETSENDFLAG_CONNLESS;
-	Packet.m_DataSize = sizeof(SERVERBROWSE_FWRESPONSE);
-	Packet.m_pData = SERVERBROWSE_FWRESPONSE;
-	m_pNetServer->Send(&Packet);
-}
-	
-static void register_send_heartbeat(NETADDR addr)
-{
-	static unsigned char data[sizeof(SERVERBROWSE_HEARTBEAT) + 2];
-	unsigned short port = config.sv_port;
-	CNetChunk Packet;
-	
-	mem_copy(data, SERVERBROWSE_HEARTBEAT, sizeof(SERVERBROWSE_HEARTBEAT));
-	
-	Packet.m_ClientID = -1;
-	Packet.m_Address = addr;
-	Packet.m_Flags = NETSENDFLAG_CONNLESS;
-	Packet.m_DataSize = sizeof(SERVERBROWSE_HEARTBEAT) + 2;
-	Packet.m_pData = &data;
-
-	/* supply the set port that the master can use if it has problems */	
-	if(config.sv_external_port)
-		port = config.sv_external_port;
-	data[sizeof(SERVERBROWSE_HEARTBEAT)] = port >> 8;
-	data[sizeof(SERVERBROWSE_HEARTBEAT)+1] = port&0xff;
-	m_pNetServer->Send(&Packet);
-}
-
-static void register_send_count_request(NETADDR Addr)
-{
-	CNetChunk Packet;
-	Packet.m_ClientID = -1;
-	Packet.m_Address = Addr;
-	Packet.m_Flags = NETSENDFLAG_CONNLESS;
-	Packet.m_DataSize = sizeof(SERVERBROWSE_GETCOUNT);
-	Packet.m_pData = SERVERBROWSE_GETCOUNT;
-	m_pNetServer->Send(&Packet);
-}
-
-typedef struct
-{
-	NETADDR addr;
-	int count;
-	int valid;
-	int64 last_send;
-} MASTERSERVER_INFO;
-
-static MASTERSERVER_INFO masterserver_info[MAX_MASTERSERVERS] = {{{0}}};
-static int register_registered_server = -1;
-
-void register_update()
-{
-	int64 now = time_get();
-	int64 freq = time_freq();
-	
-	if(!config.sv_register)
-		return;
-	
-	mastersrv_update();
-	
-	if(register_state == REGISTERSTATE_START)
-	{
-		register_count = 0;
-		register_first = 1;
-		register_new_state(REGISTERSTATE_UPDATE_ADDRS);
-		mastersrv_refresh_addresses();
-		dbg_msg("register", "refreshing ip addresses");
-	}
-	else if(register_state == REGISTERSTATE_UPDATE_ADDRS)
-	{
-		register_registered_server = -1;
-		
-		if(!mastersrv_refreshing())
-		{
-			int i;
-			for(i = 0; i < MAX_MASTERSERVERS; i++)
-			{
-				NETADDR addr = mastersrv_get(i);
-				masterserver_info[i].addr = addr;
-				masterserver_info[i].count = 0;
-				
-				if(!addr.ip[0] && !addr.ip[1] && !addr.ip[2] && !addr.ip[3])
-					masterserver_info[i].valid = 0;
-				else
-				{
-					masterserver_info[i].valid = 1;
-					masterserver_info[i].count = -1;
-					masterserver_info[i].last_send = 0;
-				}
-			}
-			
-			dbg_msg("register", "fetching server counts");
-			register_new_state(REGISTERSTATE_QUERY_COUNT);
-		}
-	}
-	else if(register_state == REGISTERSTATE_QUERY_COUNT)
-	{
-		int i;
-		int left = 0;
-		for(i = 0; i < MAX_MASTERSERVERS; i++)
-		{
-			if(!masterserver_info[i].valid)
-				continue;
-				
-			if(masterserver_info[i].count == -1)
-			{
-				left++;
-				if(masterserver_info[i].last_send+freq < now)
-				{
-					masterserver_info[i].last_send = now;
-					register_send_count_request(masterserver_info[i].addr);
-				}
-			}
-		}
-		
-		/* check if we are done or timed out */
-		if(left == 0 || now > register_state_start+freq*3)
-		{
-			/* choose server */
-			int best = -1;
-			int i;
-			for(i = 0; i < MAX_MASTERSERVERS; i++)
-			{
-				if(!masterserver_info[i].valid || masterserver_info[i].count == -1)
-					continue;
-					
-				if(best == -1 || masterserver_info[i].count < masterserver_info[best].count)
-					best = i;
-			}
-
-			/* server chosen */
-			register_registered_server = best;
-			if(register_registered_server == -1)
-			{
-				dbg_msg("register", "WARNING: No master servers. Retrying in 60 seconds");
-				register_new_state(REGISTERSTATE_ERROR);
-			}
-			else
-			{			
-				dbg_msg("register", "choosen '%s' as master, sending heartbeats", mastersrv_name(register_registered_server));
-				masterserver_info[register_registered_server].last_send = 0;
-				register_new_state(REGISTERSTATE_HEARTBEAT);
-			}
-		}
-	}
-	else if(register_state == REGISTERSTATE_HEARTBEAT)
-	{
-		/* check if we should send heartbeat */
-		if(now > masterserver_info[register_registered_server].last_send+freq*15)
-		{
-			masterserver_info[register_registered_server].last_send = now;
-			register_send_heartbeat(masterserver_info[register_registered_server].addr);
-		}
-		
-		if(now > register_state_start+freq*60)
-		{
-			dbg_msg("register", "WARNING: Master server is not responding, switching master");
-			register_new_state(REGISTERSTATE_START);
-		}
-	}
-	else if(register_state == REGISTERSTATE_REGISTERED)
-	{
-		if(register_first)
-			dbg_msg("register", "server registered");
-			
-		register_first = 0;
-		
-		/* check if we should send new heartbeat again */
-		if(now > register_state_start+freq)
-		{
-			if(register_count == 120) /* redo the whole process after 60 minutes to balance out the master servers */
-				register_new_state(REGISTERSTATE_START);
-			else
-			{
-				register_count++;
-				register_new_state(REGISTERSTATE_HEARTBEAT);
-			}
-		}
-	}
-	else if(register_state == REGISTERSTATE_ERROR)
-	{
-		/* check for restart */
-		if(now > register_state_start+freq*60)
-			register_new_state(REGISTERSTATE_START);
-	}
-}
-
-static void register_got_count(CNetChunk *pChunk)
-{
-	unsigned char *pData = (unsigned char *)pChunk->m_pData;
-	int Count = (pData[sizeof(SERVERBROWSE_COUNT)]<<8) | pData[sizeof(SERVERBROWSE_COUNT)+1];
-
-	for(int i = 0; i < MAX_MASTERSERVERS; i++)
-	{
-		if(net_addr_comp(&masterserver_info[i].addr, &pChunk->m_Address) == 0)
-		{
-			masterserver_info[i].count = Count;
-			break;
-		}
-	}
-}
-
-int register_process_packet(CNetChunk *pPacket)
-{
-	if(pPacket->m_DataSize == sizeof(SERVERBROWSE_FWCHECK) &&
-		memcmp(pPacket->m_pData, SERVERBROWSE_FWCHECK, sizeof(SERVERBROWSE_FWCHECK)) == 0)
-	{
-		register_send_fwcheckresponse(&pPacket->m_Address);
-		return 1;
-	}
-	else if(pPacket->m_DataSize == sizeof(SERVERBROWSE_FWOK) &&
-		memcmp(pPacket->m_pData, SERVERBROWSE_FWOK, sizeof(SERVERBROWSE_FWOK)) == 0)
-	{
-		if(register_first)
-			dbg_msg("register", "no firewall/nat problems detected");
-		register_new_state(REGISTERSTATE_REGISTERED);
-		return 1;
-	}
-	else if(pPacket->m_DataSize == sizeof(SERVERBROWSE_FWERROR) &&
-		memcmp(pPacket->m_pData, SERVERBROWSE_FWERROR, sizeof(SERVERBROWSE_FWERROR)) == 0)
-	{
-		dbg_msg("register", "ERROR: the master server reports that clients can not connect to this server.");
-		dbg_msg("register", "ERROR: configure your firewall/nat to let through udp on port %d.", config.sv_port);
-		register_new_state(REGISTERSTATE_ERROR);
-		return 1;
-	}
-	else if(pPacket->m_DataSize == sizeof(SERVERBROWSE_COUNT)+2 &&
-		memcmp(pPacket->m_pData, SERVERBROWSE_COUNT, sizeof(SERVERBROWSE_COUNT)) == 0)
-	{
-		register_got_count(pPacket);
-		return 1;
-	}
-
-	return 0;
-}
diff --git a/src/engine/server/es_server.cpp b/src/engine/server/es_server.cpp
deleted file mode 100644
index cc0e6e0f..00000000
--- a/src/engine/server/es_server.cpp
+++ /dev/null
@@ -1,1969 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <base/system.h>
-
-#include <engine/e_config.h>
-#include <engine/e_engine.h>
-#include <engine/e_server_interface.h>
-
-#include <engine/e_protocol.h>
-#include <engine/e_snapshot.h>
-
-#include <engine/e_compression.h>
-
-#include <engine/e_network.h>
-#include <engine/e_config.h>
-#include <engine/e_packer.h>
-#include <engine/e_datafile.h>
-#include <engine/e_demorec.h>
-
-#include <mastersrv/mastersrv.h>
-
-#if defined(CONF_FAMILY_WINDOWS) 
-	#define _WIN32_WINNT 0x0500 
-	#include <windows.h> 
-#endif
-
-
-extern int register_process_packet(CNetChunk *pPacket);
-extern int register_update();
-
-static const char *str_ltrim(const char *str)
-{
-	while(*str && *str <= 32)
-		str++;
-	return str;
-}
-
-static void str_rtrim(char *str)
-{
-	int i = str_length(str);
-	while(i >= 0)
-	{
-		if(str[i] > 32)
-			break;
-		str[i] = 0;
-		i--;
-	}
-}
-
-
-class CSnapIDPool
-{
-	enum
-	{
-		MAX_IDS = 16*1024,
-	};
-
-	class CID
-	{
-	public:
-		short m_Next;
-		short m_State; /* 0 = free, 1 = alloced, 2 = timed */
-		int m_Timeout;
-	};
-
-	CID m_aIDs[MAX_IDS];
-		
-	int m_FirstFree;
-	int m_FirstTimed;
-	int m_LastTimed;
-	int m_Usage;
-	int m_InUsage;
-
-public:	
-
-	CSnapIDPool()
-	{
-		Reset();
-	}
-	
-	void Reset()
-	{
-		for(int i = 0; i < MAX_IDS; i++)
-		{
-			m_aIDs[i].m_Next = i+1;
-			m_aIDs[i].m_State = 0;
-		}
-			
-		m_aIDs[MAX_IDS-1].m_Next = -1;
-		m_FirstFree = 0;
-		m_FirstTimed = -1;
-		m_LastTimed = -1;
-		m_Usage = 0;
-		m_InUsage = 0;
-	}
-	
-
-	void RemoveFirstTimeout()
-	{
-		int NextTimed = m_aIDs[m_FirstTimed].m_Next;
-		
-		/* add it to the free list */
-		m_aIDs[m_FirstTimed].m_Next = m_FirstFree;
-		m_aIDs[m_FirstTimed].m_State = 0;
-		m_FirstFree = m_FirstTimed;
-		
-		/* remove it from the timed list */
-		m_FirstTimed = NextTimed;
-		if(m_FirstTimed == -1)
-			m_LastTimed = -1;
-			
-		m_Usage--;
-	}
-
-	int NewID()
-	{
-		int64 now = time_get();
-		
-		/* process timed ids */
-		while(m_FirstTimed != -1 && m_aIDs[m_FirstTimed].m_Timeout < now)
-			RemoveFirstTimeout();
-		
-		int id = m_FirstFree;
-		dbg_assert(id != -1, "id error");
-		m_FirstFree = m_aIDs[m_FirstFree].m_Next;
-		m_aIDs[id].m_State = 1;
-		m_Usage++;
-		m_InUsage++;
-		return id;
-	}
-
-	void TimeoutIDs()
-	{
-		/* process timed ids */
-		while(m_FirstTimed != -1)
-			RemoveFirstTimeout();
-	}
-
-	void FreeID(int id)
-	{
-		dbg_assert(m_aIDs[id].m_State == 1, "id is not alloced");
-
-		m_InUsage--;
-		m_aIDs[id].m_State = 2;
-		m_aIDs[id].m_Timeout = time_get()+time_freq()*5;
-		m_aIDs[id].m_Next = -1;
-		
-		if(m_LastTimed != -1)
-		{
-			m_aIDs[m_LastTimed].m_Next = id;
-			m_LastTimed = id;
-		}
-		else
-		{
-			m_FirstTimed = id;
-			m_LastTimed = id;
-		}
-	}
-};
-
-#if 0
-class IGameServer
-{
-public:
-	/*
-		Function: mods_console_init
-			TODO
-	*/
-	virtual void ConsoleInit();
-
-	/*
-		Function: Init
-			Called when the server is started.
-		
-		Remarks:
-			It's called after the map is loaded so all map items are available.
-	*/
-	void Init() = 0;
-
-	/*
-		Function: Shutdown
-			Called when the server quits.
-		
-		Remarks:
-			Should be used to clean up all resources used.
-	*/
-	void Shutdown() = 0;
-
-	/*
-		Function: ClientEnter
-			Called when a client has joined the game.
-			
-		Arguments:
-			cid - Client ID. Is 0 - MAX_CLIENTS.
-		
-		Remarks:
-			It's called when the client is finished loading and should enter gameplay.
-	*/
-	void ClientEnter(int cid) = 0;
-
-	/*
-		Function: ClientDrop
-			Called when a client drops from the server.
-
-		Arguments:
-			cid - Client ID. Is 0 - MAX_CLIENTS
-	*/
-	void ClientDrop(int cid) = 0;
-
-	/*
-		Function: ClientDirectInput
-			Called when the server recives new input from a client.
-
-		Arguments:
-			cid - Client ID. Is 0 - MAX_CLIENTS.
-			input - Pointer to the input data.
-			size - Size of the data. (NOT IMPLEMENTED YET)
-	*/
-	void ClientDirectInput(int cid, void *input) = 0;
-
-	/*
-		Function: ClientPredictedInput
-			Called when the server applys the predicted input on the client.
-
-		Arguments:
-			cid - Client ID. Is 0 - MAX_CLIENTS.
-			input - Pointer to the input data.
-			size - Size of the data. (NOT IMPLEMENTED YET)
-	*/
-	void ClientPredictedInput(int cid, void *input) = 0;
-
-
-	/*
-		Function: Tick
-			Called with a regular interval to progress the gameplay.
-			
-		Remarks:
-			The SERVER_TICK_SPEED tells the number of ticks per second.
-	*/
-	void Tick() = 0;
-
-	/*
-		Function: Presnap
-			Called before the server starts to construct snapshots for the clients.
-	*/
-	void Presnap() = 0;
-
-	/*
-		Function: Snap
-			Called to create the snapshot for a client.
-		
-		Arguments:
-			cid - Client ID. Is 0 - MAX_CLIENTS.
-		
-		Remarks:
-			The game should make a series of calls to <snap_new_item> to construct
-			the snapshot for the client.
-	*/
-	void Snap(int cid) = 0;
-
-	/*
-		Function: PostSnap
-			Called after the server is done sending the snapshots.
-	*/
-	void PostSnap() = 0;
-
-	/*
-		Function: ClientConnected
-			TODO
-		
-		Arguments:
-			arg1 - desc
-		
-		Returns:
-
-		See Also:
-			<other_func>
-	*/
-	void ClientConnected(int client_id) = 0;
-
-
-	/*
-		Function: NetVersion
-			TODO
-		
-		Arguments:
-			arg1 - desc
-		
-		Returns:
-
-		See Also:
-			<other_func>
-	*/
-	const char *NetVersion() = 0;
-
-	/*
-		Function: Version
-			TODO
-		
-		Arguments:
-			arg1 - desc
-		
-		Returns:
-
-		See Also:
-			<other_func>
-	*/
-	const char *Version() = 0;
-
-	/*
-		Function: Message
-			TODO
-		
-		Arguments:
-			arg1 - desc
-		
-		Returns:
-
-		See Also:
-			<other_func>
-	*/
-	void Message(int msg, int client_id) = 0;
-};
-
-#endif
-/*
-class IServer
-{
-public:
-	BanAdd
-	BanRemove
-	TickSpeed
-	Tick
-	Kick
-	SetBrowseInfo
-	SetClientScore
-	SetClientName
-	GetClientInfo
-	LatestInput
-	ClientName
-	
-	SendMessage()
-	
-	Map
-	
-	virtual int NewSnapID() = 0;
-	virtual int FreeSnapID(int i) = 0;
-};*/
-
-class CServer
-{
-public:
-	/* */
-	class CClient
-	{
-	public:
-	
-		enum
-		{
-			STATE_EMPTY = 0,
-			STATE_AUTH,
-			STATE_CONNECTING,
-			STATE_READY,
-			STATE_INGAME,
-			
-			SNAPRATE_INIT=0,
-			SNAPRATE_FULL,
-			SNAPRATE_RECOVER
-		};
-	
-		class CInput
-		{
-		public:
-			int m_aData[MAX_INPUT_SIZE];
-			int m_GameTick; /* the tick that was chosen for the input */
-		};
-	
-		/* connection state info */
-		int m_State;
-		int m_Latency;
-		int m_SnapRate;
-		
-		int m_LastAckedSnapshot;
-		int m_LastInputTick;
-		CSnapshotStorage m_Snapshots;
-		
-		CInput m_LatestInput;
-		CInput m_aInputs[200]; /* TODO: handle input better */
-		int m_CurrentInput;
-		
-		char m_aName[MAX_NAME_LENGTH];
-		char m_aClan[MAX_CLANNAME_LENGTH];
-		int m_Score;
-		int m_Authed;
-		
-		void Reset()
-		{
-			/* reset input */
-			for(int i = 0; i < 200; i++)
-				m_aInputs[i].m_GameTick = -1;
-			m_CurrentInput = 0;
-			mem_zero(&m_LatestInput, sizeof(m_LatestInput));
-
-			m_Snapshots.PurgeAll();
-			m_LastAckedSnapshot = -1;
-			m_LastInputTick = -1;
-			m_SnapRate = CClient::SNAPRATE_INIT;
-			m_Score = 0;
-		}
-	};
-	
-	CClient m_aClients[MAX_CLIENTS];
-
-	CSnapshotBuilder m_SnapshotBuilder;
-	CSnapIDPool m_IDPool;
-	CNetServer m_NetServer;
-
-	int64 m_GameStartTime;
-	int m_CurrentTick;
-	int m_RunServer;
-
-	char m_aBrowseinfoGametype[16];
-	int m_BrowseinfoProgression;
-
-	int64 m_Lastheartbeat;
-	/*static NETADDR4 master_server;*/
-
-	char m_aCurrentMap[64];
-	int m_CurrentMapCrc;
-	unsigned char *m_pCurrentMapData;
-	int m_CurrentMapSize;	
-	
-	CServer()
-	{
-		m_CurrentTick = 0;
-		m_RunServer = 1;
-
-		mem_zero(m_aBrowseinfoGametype, sizeof(m_aBrowseinfoGametype));
-		m_BrowseinfoProgression = -1;
-
-		m_pCurrentMapData = 0;
-		m_CurrentMapSize = 0;	
-	}
-	
-
-	int TrySetClientName(int ClientID, const char *pName)
-	{
-		int i;
-		char aTrimmedName[64];
-
-		/* trim the name */
-		str_copy(aTrimmedName, str_ltrim(pName), sizeof(aTrimmedName));
-		str_rtrim(aTrimmedName);
-		dbg_msg("", "'%s' -> '%s'", pName, aTrimmedName);
-		pName = aTrimmedName;
-		
-		
-		/* check for empty names */
-		if(!pName[0])
-			return -1;
-		
-		/* make sure that two clients doesn't have the same name */
-		for(i = 0; i < MAX_CLIENTS; i++)
-			if(i != ClientID && m_aClients[i].m_State >= CClient::STATE_READY)
-			{
-				if(strcmp(pName, m_aClients[i].m_aName) == 0)
-					return -1;
-			}
-
-		/* set the client name */
-		str_copy(m_aClients[ClientID].m_aName, pName, MAX_NAME_LENGTH);
-		return 0;
-	}
-
-
-
-	void SetClientName(int ClientID, const char *pName)
-	{
-		if(ClientID < 0 || ClientID > MAX_CLIENTS || m_aClients[ClientID].m_State < CClient::STATE_READY)
-			return;
-			
-		if(!pName)
-			return;
-			
-		char aNameTry[MAX_NAME_LENGTH];
-		str_copy(aNameTry, pName, MAX_NAME_LENGTH);
-		if(TrySetClientName(ClientID, aNameTry))
-		{
-			/* auto rename */
-			for(int i = 1;; i++)
-			{
-				str_format(aNameTry, MAX_NAME_LENGTH, "(%d)%s", i, pName);
-				if(TrySetClientName(ClientID, aNameTry) == 0)
-					break;
-			}
-		}
-	}
-
-	void SetClientScore(int ClientID, int Score)
-	{
-		if(ClientID < 0 || ClientID > MAX_CLIENTS || m_aClients[ClientID].m_State < CClient::STATE_READY)
-			return;
-		m_aClients[ClientID].m_Score = Score;
-	}
-
-	void SetBrowseInfo(const char *pGameType, int Progression)
-	{
-		str_copy(m_aBrowseinfoGametype, pGameType, sizeof(m_aBrowseinfoGametype));
-		m_BrowseinfoProgression = Progression;
-		if(m_BrowseinfoProgression > 100)
-			m_BrowseinfoProgression = 100;
-		if(m_BrowseinfoProgression < -1)
-			m_BrowseinfoProgression = -1;
-	}
-
-	void Kick(int ClientID, const char *pReason)
-	{
-		if(ClientID < 0 || ClientID > MAX_CLIENTS)
-			return;
-			
-		if(m_aClients[ClientID].m_State != CClient::STATE_EMPTY)
-			m_NetServer.Drop(ClientID, pReason);
-	}
-
-	int Tick()
-	{
-		return m_CurrentTick;
-	}
-
-	int64 TickStartTime(int Tick)
-	{
-		return m_GameStartTime + (time_freq()*Tick)/SERVER_TICK_SPEED;
-	}
-
-	int TickSpeed()
-	{
-		return SERVER_TICK_SPEED;
-	}
-
-	int Init()
-	{
-		int i;
-		for(i = 0; i < MAX_CLIENTS; i++)
-		{
-			m_aClients[i].m_State = CClient::STATE_EMPTY;
-			m_aClients[i].m_aName[0] = 0;
-			m_aClients[i].m_aClan[0] = 0;
-			m_aClients[i].m_Snapshots.Init();
-		}
-
-		m_CurrentTick = 0;
-
-		return 0;
-	}
-
-	int GetClientInfo(int ClientID, CLIENT_INFO *pInfo)
-	{
-		dbg_assert(ClientID >= 0 && ClientID < MAX_CLIENTS, "client_id is not valid");
-		dbg_assert(pInfo != 0, "info can not be null");
-
-		if(m_aClients[ClientID].m_State == CClient::STATE_INGAME)
-		{
-			pInfo->name = m_aClients[ClientID].m_aName;
-			pInfo->latency = m_aClients[ClientID].m_Latency;
-			return 1;
-		}
-		return 0;
-	}
-
-	int SendMsg(int ClientID)
-	{
-		const MSG_INFO *pInfo = msg_get_info();
-		CNetChunk Packet;
-		if(!pInfo)
-			return -1;
-			
-		mem_zero(&Packet, sizeof(CNetChunk));
-		
-		Packet.m_ClientID = ClientID;
-		Packet.m_pData = pInfo->data;
-		Packet.m_DataSize = pInfo->size;
-
-		if(pInfo->flags&MSGFLAG_VITAL)
-			Packet.m_Flags |= NETSENDFLAG_VITAL;
-		if(pInfo->flags&MSGFLAG_FLUSH)
-			Packet.m_Flags |= NETSENDFLAG_FLUSH;
-		
-		/* write message to demo recorder */
-		if(!(pInfo->flags&MSGFLAG_NORECORD))
-			demorec_record_message(pInfo->data, pInfo->size);
-
-		if(!(pInfo->flags&MSGFLAG_NOSEND))
-		{
-			if(ClientID == -1)
-			{
-				/* broadcast */
-				int i;
-				for(i = 0; i < MAX_CLIENTS; i++)
-					if(m_aClients[i].m_State == CClient::STATE_INGAME)
-					{
-						Packet.m_ClientID = i;
-						m_NetServer.Send(&Packet);
-					}
-			}
-			else
-				m_NetServer.Send(&Packet);
-		}
-		return 0;
-	}
-
-	void DoSnapshot()
-	{
-		int i;
-		
-		{
-			static PERFORMACE_INFO scope = {"presnap", 0};
-			perf_start(&scope);
-			mods_presnap();
-			perf_end();
-		}
-		
-		/* create snapshot for demo recording */
-		if(demorec_isrecording())
-		{
-			char data[CSnapshot::MAX_SIZE];
-			int snapshot_size;
-
-			/* build snap and possibly add some messages */
-			m_SnapshotBuilder.Init();
-			mods_snap(-1);
-			snapshot_size = m_SnapshotBuilder.Finish(data);
-			
-			/* write snapshot */
-			demorec_record_snapshot(Tick(), data, snapshot_size);
-		}
-
-		/* create snapshots for all clients */
-		for(i = 0; i < MAX_CLIENTS; i++)
-		{
-			/* client must be ingame to recive snapshots */
-			if(m_aClients[i].m_State != CClient::STATE_INGAME)
-				continue;
-				
-			/* this client is trying to recover, don't spam snapshots */
-			if(m_aClients[i].m_SnapRate == CClient::SNAPRATE_RECOVER && (Tick()%50) != 0)
-				continue;
-				
-			/* this client is trying to recover, don't spam snapshots */
-			if(m_aClients[i].m_SnapRate == CClient::SNAPRATE_INIT && (Tick()%10) != 0)
-				continue;
-				
-			{
-				char data[CSnapshot::MAX_SIZE];
-				char deltadata[CSnapshot::MAX_SIZE];
-				char compdata[CSnapshot::MAX_SIZE];
-				int snapshot_size;
-				int crc;
-				static CSnapshot emptysnap;
-				CSnapshot *deltashot = &emptysnap;
-				int deltashot_size;
-				int delta_tick = -1;
-				int deltasize;
-				static PERFORMACE_INFO scope = {"build", 0};
-				perf_start(&scope);
-
-				m_SnapshotBuilder.Init();
-
-				{
-					static PERFORMACE_INFO scope = {"modsnap", 0};
-					perf_start(&scope);
-					mods_snap(i);
-					perf_end();
-				}
-
-				/* finish snapshot */
-				snapshot_size = m_SnapshotBuilder.Finish(data);
-				crc = ((CSnapshot*)data)->Crc();
-
-				/* remove old snapshos */
-				/* keep 3 seconds worth of snapshots */
-				m_aClients[i].m_Snapshots.PurgeUntil(m_CurrentTick-SERVER_TICK_SPEED*3);
-				
-				/* save it the snapshot */
-				m_aClients[i].m_Snapshots.Add(m_CurrentTick, time_get(), snapshot_size, data, 0);
-				
-				/* find snapshot that we can preform delta against */
-				emptysnap.m_DataSize = 0;
-				emptysnap.m_NumItems = 0;
-				
-				{
-					deltashot_size = m_aClients[i].m_Snapshots.Get(m_aClients[i].m_LastAckedSnapshot, 0, &deltashot, 0);
-					if(deltashot_size >= 0)
-						delta_tick = m_aClients[i].m_LastAckedSnapshot;
-					else
-					{
-						/* no acked package found, force client to recover rate */
-						if(m_aClients[i].m_SnapRate == CClient::SNAPRATE_FULL)
-							m_aClients[i].m_SnapRate = CClient::SNAPRATE_RECOVER;
-					}
-				}
-				
-				/* create delta */
-				{
-					static PERFORMACE_INFO scope = {"delta", 0};
-					perf_start(&scope);
-					deltasize = CSnapshot::CreateDelta(deltashot, (CSnapshot*)data, deltadata);
-					perf_end();
-				}
-
-				
-				if(deltasize)
-				{
-					/* compress it */
-					int snapshot_size;
-					const int max_size = MAX_SNAPSHOT_PACKSIZE;
-					int numpackets;
-					int n, left;
-
-					{				
-						static PERFORMACE_INFO scope = {"compress", 0};
-						/*char buffer[512];*/
-						perf_start(&scope);
-						snapshot_size = intpack_compress(deltadata, deltasize, compdata);
-						
-						/*str_hex(buffer, sizeof(buffer), compdata, snapshot_size);
-						dbg_msg("", "deltasize=%d -> %d : %s", deltasize, snapshot_size, buffer);*/
-						
-						perf_end();
-					}
-
-					numpackets = (snapshot_size+max_size-1)/max_size;
-					
-					for(n = 0, left = snapshot_size; left; n++)
-					{
-						int chunk = left < max_size ? left : max_size;
-						left -= chunk;
-
-						if(numpackets == 1)
-							msg_pack_start_system(NETMSG_SNAPSINGLE, MSGFLAG_FLUSH);
-						else
-							msg_pack_start_system(NETMSG_SNAP, MSGFLAG_FLUSH);
-							
-						msg_pack_int(m_CurrentTick);
-						msg_pack_int(m_CurrentTick-delta_tick); /* compressed with */
-						
-						if(numpackets != 1)
-						{
-							msg_pack_int(numpackets);
-							msg_pack_int(n);
-						}
-						
-						msg_pack_int(crc);
-						msg_pack_int(chunk);
-						msg_pack_raw(&compdata[n*max_size], chunk);
-						msg_pack_end();
-						SendMsg(i);
-					}
-				}
-				else
-				{
-					msg_pack_start_system(NETMSG_SNAPEMPTY, MSGFLAG_FLUSH);
-					msg_pack_int(m_CurrentTick);
-					msg_pack_int(m_CurrentTick-delta_tick); /* compressed with */
-					msg_pack_end();
-					SendMsg(i);
-				}
-				
-				perf_end();
-			}
-		}
-
-		mods_postsnap();
-	}
-
-
-	static int NewClientCallback(int cid, void *pUser)
-	{
-		CServer *pThis = (CServer *)pUser;
-		pThis->m_aClients[cid].m_State = CClient::STATE_AUTH;
-		pThis->m_aClients[cid].m_aName[0] = 0;
-		pThis->m_aClients[cid].m_aClan[0] = 0;
-		pThis->m_aClients[cid].m_Authed = 0;
-		pThis->m_aClients[cid].Reset();
-		return 0;
-	}
-
-	static int DelClientCallback(int cid, void *pUser)
-	{
-		CServer *pThis = (CServer *)pUser;
-		
-		/* notify the mod about the drop */
-		if(pThis->m_aClients[cid].m_State >= CClient::STATE_READY)
-			mods_client_drop(cid);
-		
-		pThis->m_aClients[cid].m_State = CClient::STATE_EMPTY;
-		pThis->m_aClients[cid].m_aName[0] = 0;
-		pThis->m_aClients[cid].m_aClan[0] = 0;
-		pThis->m_aClients[cid].m_Authed = 0;
-		pThis->m_aClients[cid].m_Snapshots.PurgeAll();
-		return 0;
-	}
-
-	void SendMap(int cid)
-	{
-		msg_pack_start_system(NETMSG_MAP_CHANGE, MSGFLAG_VITAL|MSGFLAG_FLUSH);
-		msg_pack_string(config.sv_map, 0);
-		msg_pack_int(m_CurrentMapCrc);
-		msg_pack_end();
-		server_send_msg(cid);
-	}
-
-	void SendRconLine(int cid, const char *pLine)
-	{
-		msg_pack_start_system(NETMSG_RCON_LINE, MSGFLAG_VITAL);
-		msg_pack_string(pLine, 512);
-		msg_pack_end();
-		server_send_msg(cid);
-	}
-
-	static void SendRconLineAuthed(const char *pLine, void *pUser)
-	{
-		CServer *pThis = (CServer *)pUser;
-		static volatile int reentry_guard = 0;
-		int i;
-		
-		if(reentry_guard) return;
-		reentry_guard++;
-		
-		for(i = 0; i < MAX_CLIENTS; i++)
-		{
-			if(pThis->m_aClients[i].m_State != CClient::STATE_EMPTY && pThis->m_aClients[i].m_Authed)
-				pThis->SendRconLine(i, pLine);
-		}
-		
-		reentry_guard--;
-	}
-	
-	void ProcessClientPacket(CNetChunk *pPacket)
-	{
-		int cid = pPacket->m_ClientID;
-		NETADDR addr;
-		
-		int sys;
-		int msg = msg_unpack_start(pPacket->m_pData, pPacket->m_DataSize, &sys);
-		
-		if(m_aClients[cid].m_State == CClient::STATE_AUTH)
-		{
-			if(sys && msg == NETMSG_INFO)
-			{
-				char version[64];
-				const char *password;
-				str_copy(version, msg_unpack_string(), 64);
-				if(strcmp(version, mods_net_version()) != 0)
-				{
-					/* OH FUCK! wrong version, drop him */
-					char reason[256];
-					str_format(reason, sizeof(reason), "wrong version. server is running '%s' and client '%s'.", mods_net_version(), version);
-					m_NetServer.Drop(cid, reason);
-					return;
-				}
-				
-				str_copy(m_aClients[cid].m_aName, msg_unpack_string(), MAX_NAME_LENGTH);
-				str_copy(m_aClients[cid].m_aClan, msg_unpack_string(), MAX_CLANNAME_LENGTH);
-				password = msg_unpack_string();
-				
-				if(config.password[0] != 0 && strcmp(config.password, password) != 0)
-				{
-					/* wrong password */
-					m_NetServer.Drop(cid, "wrong password");
-					return;
-				}
-				
-				m_aClients[cid].m_State = CClient::STATE_CONNECTING;
-				SendMap(cid);
-			}
-		}
-		else
-		{
-			if(sys)
-			{
-				/* system message */
-				if(msg == NETMSG_REQUEST_MAP_DATA)
-				{
-					int chunk = msg_unpack_int();
-					int chunk_size = 1024-128;
-					int offset = chunk * chunk_size;
-					int last = 0;
-					
-					/* drop faulty map data requests */
-					if(chunk < 0 || offset > m_CurrentMapSize)
-						return;
-					
-					if(offset+chunk_size >= m_CurrentMapSize)
-					{
-						chunk_size = m_CurrentMapSize-offset;
-						if(chunk_size < 0)
-							chunk_size = 0;
-						last = 1;
-					}
-					
-					msg_pack_start_system(NETMSG_MAP_DATA, MSGFLAG_VITAL|MSGFLAG_FLUSH);
-					msg_pack_int(last);
-					msg_pack_int(m_CurrentMapSize);
-					msg_pack_int(chunk_size);
-					msg_pack_raw(&m_pCurrentMapData[offset], chunk_size);
-					msg_pack_end();
-					server_send_msg(cid);
-					
-					if(config.debug)
-						dbg_msg("server", "sending chunk %d with size %d", chunk, chunk_size);
-				}
-				else if(msg == NETMSG_READY)
-				{
-					if(m_aClients[cid].m_State == CClient::STATE_CONNECTING)
-					{
-						addr = m_NetServer.ClientAddr(cid);
-						
-						dbg_msg("server", "player is ready. cid=%x ip=%d.%d.%d.%d",
-							cid,
-							addr.ip[0], addr.ip[1], addr.ip[2], addr.ip[3]
-							);
-						m_aClients[cid].m_State = CClient::STATE_READY;
-						mods_connected(cid);
-					}
-				}
-				else if(msg == NETMSG_ENTERGAME)
-				{
-					if(m_aClients[cid].m_State == CClient::STATE_READY)
-					{
-						addr = m_NetServer.ClientAddr(cid);
-						
-						dbg_msg("server", "player has entered the game. cid=%x ip=%d.%d.%d.%d",
-							cid,
-							addr.ip[0], addr.ip[1], addr.ip[2], addr.ip[3]
-							);
-						m_aClients[cid].m_State = CClient::STATE_INGAME;
-						mods_client_enter(cid);
-					}
-				}
-				else if(msg == NETMSG_INPUT)
-				{
-					int tick, size, i;
-					CClient::CInput *pInput;
-					int64 tagtime;
-					
-					m_aClients[cid].m_LastAckedSnapshot = msg_unpack_int();
-					tick = msg_unpack_int();
-					size = msg_unpack_int();
-					
-					/* check for errors */
-					if(msg_unpack_error() || size/4 > MAX_INPUT_SIZE)
-						return;
-
-					if(m_aClients[cid].m_LastAckedSnapshot > 0)
-						m_aClients[cid].m_SnapRate = CClient::SNAPRATE_FULL;
-						
-					if(m_aClients[cid].m_Snapshots.Get(m_aClients[cid].m_LastAckedSnapshot, &tagtime, 0, 0) >= 0)
-						m_aClients[cid].m_Latency = (int)(((time_get()-tagtime)*1000)/time_freq());
-
-					/* add message to report the input timing */
-					/* skip packets that are old */
-					if(tick > m_aClients[cid].m_LastInputTick)
-					{
-						int time_left = ((TickStartTime(tick)-time_get())*1000) / time_freq();
-						msg_pack_start_system(NETMSG_INPUTTIMING, 0);
-						msg_pack_int(tick);
-						msg_pack_int(time_left);
-						msg_pack_end();
-						server_send_msg(cid);
-					}
-
-					m_aClients[cid].m_LastInputTick = tick;
-
-					pInput = &m_aClients[cid].m_aInputs[m_aClients[cid].m_CurrentInput];
-					
-					if(tick <= server_tick())
-						tick = server_tick()+1;
-
-					pInput->m_GameTick = tick;
-					
-					for(i = 0; i < size/4; i++)
-						pInput->m_aData[i] = msg_unpack_int();
-					
-					mem_copy(m_aClients[cid].m_LatestInput.m_aData, pInput->m_aData, MAX_INPUT_SIZE*sizeof(int));
-					
-					m_aClients[cid].m_CurrentInput++;
-					m_aClients[cid].m_CurrentInput %= 200;
-				
-					/* call the mod with the fresh input data */
-					if(m_aClients[cid].m_State == CClient::STATE_INGAME)
-						mods_client_direct_input(cid, m_aClients[cid].m_LatestInput.m_aData);
-				}
-				else if(msg == NETMSG_RCON_CMD)
-				{
-					const char *cmd = msg_unpack_string();
-					
-					if(msg_unpack_error() == 0 && m_aClients[cid].m_Authed)
-					{
-						dbg_msg("server", "cid=%d rcon='%s'", cid, cmd);
-						console_execute_line(cmd);
-					}
-				}
-				else if(msg == NETMSG_RCON_AUTH)
-				{
-					const char *pw;
-					msg_unpack_string(); /* login name, not used */
-					pw = msg_unpack_string();
-					
-					if(msg_unpack_error() == 0)
-					{
-						if(config.sv_rcon_password[0] == 0)
-						{
-							SendRconLine(cid, "No rcon password set on server. Set sv_rcon_password to enable the remote console.");
-						}
-						else if(strcmp(pw, config.sv_rcon_password) == 0)
-						{
-							msg_pack_start_system(NETMSG_RCON_AUTH_STATUS, MSGFLAG_VITAL);
-							msg_pack_int(1);
-							msg_pack_end();
-							server_send_msg(cid);
-							
-							m_aClients[cid].m_Authed = 1;
-							SendRconLine(cid, "Authentication successful. Remote console access granted.");
-							dbg_msg("server", "cid=%d authed", cid);
-						}
-						else
-						{
-							SendRconLine(cid, "Wrong password.");
-						}
-					}
-				}
-				else if(msg == NETMSG_PING)
-				{
-					msg_pack_start_system(NETMSG_PING_REPLY, 0);
-					msg_pack_end();
-					server_send_msg(cid);
-				}
-				else
-				{
-					char hex[] = "0123456789ABCDEF";
-					char buf[512];
-					int b;
-
-					for(b = 0; b < pPacket->m_DataSize && b < 32; b++)
-					{
-						buf[b*3] = hex[((const unsigned char *)pPacket->m_pData)[b]>>4];
-						buf[b*3+1] = hex[((const unsigned char *)pPacket->m_pData)[b]&0xf];
-						buf[b*3+2] = ' ';
-						buf[b*3+3] = 0;
-					}
-
-					dbg_msg("server", "strange message cid=%d msg=%d data_size=%d", cid, msg, pPacket->m_DataSize);
-					dbg_msg("server", "%s", buf);
-					
-				}
-			}
-			else
-			{
-				/* game message */
-				if(m_aClients[cid].m_State >= CClient::STATE_READY)
-					mods_message(msg, cid);
-			}
-		}
-	}
-		
-	void SendServerInfo(NETADDR *addr, int token)
-	{
-		CNetChunk Packet;
-		CPacker p;
-		char buf[128];
-
-		/* count the players */	
-		int player_count = 0;
-		int i;
-		for(i = 0; i < MAX_CLIENTS; i++)
-		{
-			if(m_aClients[i].m_State != CClient::STATE_EMPTY)
-				player_count++;
-		}
-		
-		p.Reset();
-
-		if(token >= 0)
-		{
-			/* new token based format */
-			p.AddRaw(SERVERBROWSE_INFO, sizeof(SERVERBROWSE_INFO));
-			str_format(buf, sizeof(buf), "%d", token);
-			p.AddString(buf, 6);
-		}
-		else
-		{
-			/* old format */
-			p.AddRaw(SERVERBROWSE_OLD_INFO, sizeof(SERVERBROWSE_OLD_INFO));
-		}
-		
-		p.AddString(mods_version(), 32);
-		p.AddString(config.sv_name, 64);
-		p.AddString(config.sv_map, 32);
-
-		/* gametype */
-		p.AddString(m_aBrowseinfoGametype, 16);
-
-		/* flags */
-		i = 0;
-		if(config.password[0])   /* password set */
-			i |= SRVFLAG_PASSWORD;
-		str_format(buf, sizeof(buf), "%d", i);
-		p.AddString(buf, 2);
-
-		/* progression */
-		str_format(buf, sizeof(buf), "%d", m_BrowseinfoProgression);
-		p.AddString(buf, 4);
-		
-		str_format(buf, sizeof(buf), "%d", player_count); p.AddString(buf, 3);  /* num players */
-		str_format(buf, sizeof(buf), "%d", m_NetServer.MaxClients()); p.AddString(buf, 3); /* max players */
-
-		for(i = 0; i < MAX_CLIENTS; i++)
-		{
-			if(m_aClients[i].m_State != CClient::STATE_EMPTY)
-			{
-				p.AddString(m_aClients[i].m_aName, 48);  /* player name */
-				str_format(buf, sizeof(buf), "%d", m_aClients[i].m_Score); p.AddString(buf, 6);  /* player score */
-			}
-		}
-		
-		
-		Packet.m_ClientID = -1;
-		Packet.m_Address = *addr;
-		Packet.m_Flags = NETSENDFLAG_CONNLESS;
-		Packet.m_DataSize = p.Size();
-		Packet.m_pData = p.Data();
-		m_NetServer.Send(&Packet);
-	}
-
-	int BanAdd(NETADDR Addr, int Seconds)
-	{
-		return m_NetServer.BanAdd(Addr, Seconds);	
-	}
-
-	int BanRemove(NETADDR Addr)
-	{
-		return m_NetServer.BanRemove(Addr);
-	}
-		
-
-	void PumpNetwork()
-	{
-		CNetChunk Packet;
-
-		m_NetServer.Update();
-		
-		/* process packets */
-		while(m_NetServer.Recv(&Packet))
-		{
-			if(Packet.m_ClientID == -1)
-			{
-				/* stateless */
-				if(!register_process_packet(&Packet))
-				{
-					if(Packet.m_DataSize == sizeof(SERVERBROWSE_GETINFO)+1 &&
-						memcmp(Packet.m_pData, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO)) == 0)
-					{
-						SendServerInfo(&Packet.m_Address, ((unsigned char *)Packet.m_pData)[sizeof(SERVERBROWSE_GETINFO)]);
-					}
-					
-					
-					if(Packet.m_DataSize == sizeof(SERVERBROWSE_OLD_GETINFO) &&
-						memcmp(Packet.m_pData, SERVERBROWSE_OLD_GETINFO, sizeof(SERVERBROWSE_OLD_GETINFO)) == 0)
-					{
-						SendServerInfo(&Packet.m_Address, -1);
-					}
-				}
-			}
-			else
-				ProcessClientPacket(&Packet);
-		}
-	}
-
-	int LoadMap(const char *pMapName)
-	{
-		DATAFILE *df;
-		char buf[512];
-		str_format(buf, sizeof(buf), "maps/%s.map", pMapName);
-		df = datafile_load(buf);
-		if(!df)
-			return 0;
-		
-		/* stop recording when we change map */
-		demorec_record_stop();
-		
-		/* reinit snapshot ids */
-		m_IDPool.TimeoutIDs();
-		
-		/* get the crc of the map */
-		m_CurrentMapCrc = datafile_crc(buf);
-		dbg_msg("server", "%s crc is %08x", buf, m_CurrentMapCrc);
-			
-		str_copy(m_aCurrentMap, pMapName, sizeof(m_aCurrentMap));
-		map_set(df);
-		
-		/* load compelate map into memory for download */
-		{
-			IOHANDLE file = engine_openfile(buf, IOFLAG_READ);
-			m_CurrentMapSize = (int)io_length(file);
-			if(m_pCurrentMapData)
-				mem_free(m_pCurrentMapData);
-			m_pCurrentMapData = (unsigned char *)mem_alloc(m_CurrentMapSize, 1);
-			io_read(file, m_pCurrentMapData, m_CurrentMapSize);
-			io_close(file);
-		}
-		return 1;
-	}
-
-	int Run()
-	{
-		NETADDR bindaddr;
-
-		//snap_init_id();
-		net_init();
-		
-		/* */
-		console_register_print_callback(SendRconLineAuthed, this);
-
-		/* load map */
-		if(!LoadMap(config.sv_map))
-		{
-			dbg_msg("server", "failed to load map. mapname='%s'", config.sv_map);
-			return -1;
-		}
-		
-		/* start server */
-		/* TODO: IPv6 support */
-		if(config.sv_bindaddr[0] && net_host_lookup(config.sv_bindaddr, &bindaddr, NETTYPE_IPV4) == 0)
-		{
-			/* sweet! */
-			bindaddr.port = config.sv_port;
-		}
-		else
-		{
-			mem_zero(&bindaddr, sizeof(bindaddr));
-			bindaddr.port = config.sv_port;
-		}
-		
-		
-		if(!m_NetServer.Open(bindaddr, config.sv_max_clients, 0))
-		{
-			dbg_msg("server", "couldn't open socket. port might already be in use");
-			return -1;
-		}
-
-		m_NetServer.SetCallbacks(NewClientCallback, DelClientCallback, this);
-		
-		dbg_msg("server", "server name is '%s'", config.sv_name);
-		
-		mods_init();
-		dbg_msg("server", "version %s", mods_net_version());
-
-		/* start game */
-		{
-			int64 reporttime = time_get();
-			int reportinterval = 3;
-		
-			m_Lastheartbeat = 0;
-			m_GameStartTime = time_get();
-		
-			if(config.debug)
-				dbg_msg("server", "baseline memory usage %dk", mem_stats()->allocated/1024);
-
-			while(m_RunServer)
-			{
-				static PERFORMACE_INFO rootscope = {"root", 0};
-				int64 t = time_get();
-				int new_ticks = 0;
-				
-				perf_start(&rootscope);
-				
-				/* load new map TODO: don't poll this */
-				if(strcmp(config.sv_map, m_aCurrentMap) != 0 || config.sv_map_reload)
-				{
-					config.sv_map_reload = 0;
-					
-					/* load map */
-					if(LoadMap(config.sv_map))
-					{
-						int c;
-						
-						/* new map loaded */
-						mods_shutdown();
-						
-						for(c = 0; c < MAX_CLIENTS; c++)
-						{
-							if(m_aClients[c].m_State == CClient::STATE_EMPTY)
-								continue;
-							
-							SendMap(c);
-							m_aClients[c].Reset();
-							m_aClients[c].m_State = CClient::STATE_CONNECTING;
-						}
-						
-						m_GameStartTime = time_get();
-						m_CurrentTick = 0;
-						mods_init();
-					}
-					else
-					{
-						dbg_msg("server", "failed to load map. mapname='%s'", config.sv_map);
-						config_set_sv_map(&config, m_aCurrentMap);
-					}
-				}
-				
-				while(t > TickStartTime(m_CurrentTick+1))
-				{
-					m_CurrentTick++;
-					new_ticks++;
-					
-					/* apply new input */
-					{
-						static PERFORMACE_INFO scope = {"input", 0};
-						int c, i;
-						
-						perf_start(&scope);
-						
-						for(c = 0; c < MAX_CLIENTS; c++)
-						{
-							if(m_aClients[c].m_State == CClient::STATE_EMPTY)
-								continue;
-							for(i = 0; i < 200; i++)
-							{
-								if(m_aClients[c].m_aInputs[i].m_GameTick == server_tick())
-								{
-									if(m_aClients[c].m_State == CClient::STATE_INGAME)
-										mods_client_predicted_input(c, m_aClients[c].m_aInputs[i].m_aData);
-									break;
-								}
-							}
-						}
-						
-						perf_end();
-					}
-					
-					/* progress game */
-					{
-						static PERFORMACE_INFO scope = {"tick", 0};
-						perf_start(&scope);
-						mods_tick();
-						perf_end();
-					}
-				}
-				
-				/* snap game */
-				if(new_ticks)
-				{
-					if(config.sv_high_bandwidth || (m_CurrentTick%2) == 0)
-					{
-						static PERFORMACE_INFO scope = {"snap", 0};
-						perf_start(&scope);
-						DoSnapshot();
-						perf_end();
-					}
-				}
-				
-				/* master server stuff */
-				register_update();
-		
-
-				{
-					static PERFORMACE_INFO scope = {"net", 0};
-					perf_start(&scope);
-					PumpNetwork();
-					perf_end();
-				}
-
-				perf_end();
-		
-				if(reporttime < time_get())
-				{
-					if(config.debug)
-					{
-						/*
-						static NETSTATS prev_stats;
-						NETSTATS stats;
-						netserver_stats(net, &stats);
-						
-						perf_next();
-						
-						if(config.dbg_pref)
-							perf_dump(&rootscope);
-
-						dbg_msg("server", "send=%8d recv=%8d",
-							(stats.send_bytes - prev_stats.send_bytes)/reportinterval,
-							(stats.recv_bytes - prev_stats.recv_bytes)/reportinterval);
-							
-						prev_stats = stats;
-						*/
-					}
-		
-					reporttime += time_freq()*reportinterval;
-				}
-				
-				/* wait for incomming data */
-				net_socket_read_wait(m_NetServer.Socket(), 5);
-			}
-		}
-
-		mods_shutdown();
-		map_unload();
-
-		if(m_pCurrentMapData)
-			mem_free(m_pCurrentMapData);
-		return 0;
-	}
-
-	static void ConKick(void *pResult, void *pUser)
-	{
-		((CServer *)pUser)->Kick(console_arg_int(pResult, 0), "kicked by console");
-	}
-
-	static int str_allnum(const char *str)
-	{
-		while(*str)
-		{
-			if(!(*str >= '0' && *str <= '9'))
-				return 0;
-			str++;
-		}
-		return 1;
-	}
-
-	static void ConBan(void *pResult, void *pUser)
-	{
-		NETADDR addr;
-		char addrstr[128];
-		const char *str = console_arg_string(pResult, 0);
-		int minutes = 30;
-		
-		if(console_arg_num(pResult) > 1)
-			minutes = console_arg_int(pResult, 1);
-		
-		if(net_addr_from_str(&addr, str) == 0)
-			((CServer *)pUser)->BanAdd(addr, minutes*60);
-		else if(str_allnum(str))
-		{
-			NETADDR addr;
-			int cid = atoi(str);
-
-			if(cid < 0 || cid > MAX_CLIENTS || ((CServer *)pUser)->m_aClients[cid].m_State == CClient::STATE_EMPTY)
-			{
-				dbg_msg("server", "invalid client id");
-				return;
-			}
-
-			addr = ((CServer *)pUser)->m_NetServer.ClientAddr(cid);
-			((CServer *)pUser)->BanAdd(addr, minutes*60);
-		}
-		
-		addr.port = 0;
-		net_addr_str(&addr, addrstr, sizeof(addrstr));
-		
-		if(minutes)
-			dbg_msg("server", "banned %s for %d minutes", addrstr, minutes);
-		else
-			dbg_msg("server", "banned %s for life", addrstr);
-	}
-
-	static void ConUnban(void *result, void *pUser)
-	{
-		NETADDR addr;
-		const char *str = console_arg_string(result, 0);
-		
-		if(net_addr_from_str(&addr, str) == 0)
-			((CServer *)pUser)->BanRemove(addr);
-		else
-			dbg_msg("server", "invalid network address");
-	}
-
-	static void ConBans(void *pResult, void *pUser)
-	{
-		unsigned now = time_timestamp();
-		
-		int num = ((CServer *)pUser)->m_NetServer.BanNum();
-		for(int i = 0; i < num; i++)
-		{
-			CNetServer::CBanInfo Info;
-			((CServer *)pUser)->m_NetServer.BanGet(i, &Info);
-			NETADDR Addr = Info.m_Addr;
-			
-			if(Info.m_Expires == -1)
-			{
-				dbg_msg("server", "#%d %d.%d.%d.%d for life", i, Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3]);
-			}
-			else
-			{
-				unsigned t = Info.m_Expires - now;
-				dbg_msg("server", "#%d %d.%d.%d.%d for %d minutes and %d seconds", i, Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3], t/60, t%60);
-			}
-		}
-		dbg_msg("server", "%d ban(s)", num);
-	}
-
-	static void ConStatus(void *pResult, void *pUser)
-	{
-		int i;
-		NETADDR addr;
-		for(i = 0; i < MAX_CLIENTS; i++)
-		{
-			if(((CServer *)pUser)->m_aClients[i].m_State == CClient::STATE_INGAME)
-			{
-				addr = ((CServer *)pUser)->m_NetServer.ClientAddr(i);
-				dbg_msg("server", "id=%d addr=%d.%d.%d.%d:%d name='%s' score=%d",
-					i, addr.ip[0], addr.ip[1], addr.ip[2], addr.ip[3], addr.port,
-					((CServer *)pUser)->m_aClients[i].m_aName, ((CServer *)pUser)->m_aClients[i].m_Score);
-			}
-		}
-	}
-
-	static void ConShutdown(void *pResult, void *pUser)
-	{
-		((CServer *)pUser)->m_RunServer = 0;
-	}
-
-	static void ConRecord(void *pResult, void *pUser)
-	{
-		char filename[512];
-		str_format(filename, sizeof(filename), "demos/%s.demo", console_arg_string(pResult, 0));
-		demorec_record_start(filename, mods_net_version(), ((CServer *)pUser)->m_aCurrentMap, ((CServer *)pUser)->m_CurrentMapCrc, "server");
-	}
-
-	static void ConStopRecord(void *pResult, void *pUser)
-	{
-		demorec_record_stop();
-	}
-	
-
-	void RegisterCommands()
-	{
-		MACRO_REGISTER_COMMAND("kick", "i", CFGFLAG_SERVER, ConKick, this, "");
-		MACRO_REGISTER_COMMAND("ban", "s?i", CFGFLAG_SERVER, ConBan, this, "");
-		MACRO_REGISTER_COMMAND("unban", "s", CFGFLAG_SERVER, ConUnban, this, "");
-		MACRO_REGISTER_COMMAND("bans", "", CFGFLAG_SERVER, ConBans, this, "");
-		MACRO_REGISTER_COMMAND("status", "", CFGFLAG_SERVER, ConStatus, this, "");
-		MACRO_REGISTER_COMMAND("shutdown", "", CFGFLAG_SERVER, ConShutdown, this, "");
-
-		MACRO_REGISTER_COMMAND("record", "s", CFGFLAG_SERVER, ConRecord, this, "");
-		MACRO_REGISTER_COMMAND("stoprecord", "", CFGFLAG_SERVER, ConStopRecord, this, "");
-	}	
-	
-};
-
-
-// UGLY UGLY HACK for now
-CServer g_Server;
-CNetServer *m_pNetServer;
-
-int server_tick() { return g_Server.Tick(); }
-int server_tickspeed() { return g_Server.TickSpeed(); }
-int snap_new_id() { return g_Server.m_IDPool.NewID(); }
-void snap_free_id(int id) { return g_Server.m_IDPool.FreeID(id); }
-int server_send_msg(int client_id) { return g_Server.SendMsg(client_id); }
-void server_setbrowseinfo(const char *game_type, int progression) { g_Server.SetBrowseInfo(game_type, progression); }
-void server_setclientname(int client_id, const char *name) { g_Server.SetClientName(client_id, name); }
-void server_setclientscore(int client_id, int score) { g_Server.SetClientScore(client_id, score); }
-
-int server_getclientinfo(int client_id, CLIENT_INFO *info) { return g_Server.GetClientInfo(client_id, info); }
-
-void *snap_new_item(int type, int id, int size)
-{
-	dbg_assert(type >= 0 && type <=0xffff, "incorrect type");
-	dbg_assert(id >= 0 && id <=0xffff, "incorrect id");
-	return g_Server.m_SnapshotBuilder.NewItem(type, id, size);
-}
-
-int *server_latestinput(int client_id, int *size)
-{
-	if(client_id < 0 || client_id > MAX_CLIENTS || g_Server.m_aClients[client_id].m_State < CServer::CClient::STATE_READY)
-		return 0;
-	return g_Server.m_aClients[client_id].m_LatestInput.m_aData;
-}
-
-const char *server_clientname(int client_id)
-{
-	if(client_id < 0 || client_id > MAX_CLIENTS || g_Server.m_aClients[client_id].m_State < CServer::CClient::STATE_READY)
-		return "(invalid client)";
-	return g_Server.m_aClients[client_id].m_aName;
-}
-
-#if 0
-
-
-static void reset_client(int cid)
-{
-	/* reset input */
-	int i;
-	for(i = 0; i < 200; i++)
-		m_aClients[cid].m_aInputs[i].m_GameTick = -1;
-	m_aClients[cid].m_CurrentInput = 0;
-	mem_zero(&m_aClients[cid].m_Latestinput, sizeof(m_aClients[cid].m_Latestinput));
-
-	m_aClients[cid].m_Snapshots.PurgeAll();
-	m_aClients[cid].m_LastAckedSnapshot = -1;
-	m_aClients[cid].m_LastInputTick = -1;
-	m_aClients[cid].m_SnapRate = CClient::SNAPRATE_INIT;
-	m_aClients[cid].m_Score = 0;
-
-}
-
-
-static int new_client_callback(int cid, void *user)
-{
-	m_aClients[cid].state = CClient::STATE_AUTH;
-	m_aClients[cid].name[0] = 0;
-	m_aClients[cid].clan[0] = 0;
-	m_aClients[cid].authed = 0;
-	reset_client(cid);
-	return 0;
-}
-
-static int del_client_callback(int cid, void *user)
-{
-	/* notify the mod about the drop */
-	if(m_aClients[cid].state >= CClient::STATE_READY)
-		mods_client_drop(cid);
-	
-	m_aClients[cid].state = CClient::STATE_EMPTY;
-	m_aClients[cid].name[0] = 0;
-	m_aClients[cid].clan[0] = 0;
-	m_aClients[cid].authed = 0;
-	m_aClients[cid].snapshots.PurgeAll();
-	return 0;
-}
-static void server_send_map(int cid)
-{
-	msg_pack_start_system(NETMSG_MAP_CHANGE, MSGFLAG_VITAL|MSGFLAG_FLUSH);
-	msg_pack_string(config.sv_map, 0);
-	msg_pack_int(current_map_crc);
-	msg_pack_end();
-	server_send_msg(cid);
-}
-
-static void server_send_rcon_line(int cid, const char *line)
-{
-	msg_pack_start_system(NETMSG_RCON_LINE, MSGFLAG_VITAL);
-	msg_pack_string(line, 512);
-	msg_pack_end();
-	server_send_msg(cid);
-}
-
-static void server_send_rcon_line_authed(const char *line, void *user_data)
-{
-	static volatile int reentry_guard = 0;
-	int i;
-	
-	if(reentry_guard) return;
-	reentry_guard++;
-	
-	for(i = 0; i < MAX_CLIENTS; i++)
-	{
-		if(m_aClients[i].state != CClient::STATE_EMPTY && m_aClients[i].authed)
-			server_send_rcon_line(i, line);
-	}
-	
-	reentry_guard--;
-}
-
-static void server_pump_network()
-{
-	CNetChunk Packet;
-
-	m_NetServer.Update();
-	
-	/* process packets */
-	while(m_NetServer.Recv(&Packet))
-	{
-		if(Packet.m_ClientID == -1)
-		{
-			/* stateless */
-			if(!register_process_packet(&Packet))
-			{
-				if(Packet.m_DataSize == sizeof(SERVERBROWSE_GETINFO)+1 &&
-					memcmp(Packet.m_pData, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO)) == 0)
-				{
-					server_send_serverinfo(&Packet.m_Address, ((unsigned char *)Packet.m_pData)[sizeof(SERVERBROWSE_GETINFO)]);
-				}
-				
-				
-				if(Packet.m_DataSize == sizeof(SERVERBROWSE_OLD_GETINFO) &&
-					memcmp(Packet.m_pData, SERVERBROWSE_OLD_GETINFO, sizeof(SERVERBROWSE_OLD_GETINFO)) == 0)
-				{
-					server_send_serverinfo(&Packet.m_Address, -1);
-				}
-			}
-		}
-		else
-			server_process_client_packet(&Packet);
-	}
-}
-
-static int server_load_map(const char *mapname)
-{
-	DATAFILE *df;
-	char buf[512];
-	str_format(buf, sizeof(buf), "maps/%s.map", mapname);
-	df = datafile_load(buf);
-	if(!df)
-		return 0;
-	
-	/* stop recording when we change map */
-	demorec_record_stop();
-	
-	/* reinit snapshot ids */
-	snap_timeout_ids();
-	
-	/* get the crc of the map */
-	current_map_crc = datafile_crc(buf);
-	dbg_msg("server", "%s crc is %08x", buf, current_map_crc);
-		
-	str_copy(current_map, mapname, sizeof(current_map));
-	map_set(df);
-	
-	/* load compelate map into memory for download */
-	{
-		IOHANDLE file = engine_openfile(buf, IOFLAG_READ);
-		current_map_size = (int)io_length(file);
-		if(current_map_data)
-			mem_free(current_map_data);
-		current_map_data = (unsigned char *)mem_alloc(current_map_size, 1);
-		io_read(file, current_map_data, current_map_size);
-		io_close(file);
-	}
-	return 1;
-}
-
-static int server_run()
-{
-	NETADDR bindaddr;
-
-	snap_init_id();
-	net_init();
-	
-	/* */
-	console_register_print_callback(server_send_rcon_line_authed, 0);
-
-	/* load map */
-	if(!server_load_map(config.sv_map))
-	{
-		dbg_msg("server", "failed to load map. mapname='%s'", config.sv_map);
-		return -1;
-	}
-	
-	/* start server */
-	/* TODO: IPv6 support */
-	if(config.sv_bindaddr[0] && net_host_lookup(config.sv_bindaddr, &bindaddr, NETTYPE_IPV4) == 0)
-	{
-		/* sweet! */
-		bindaddr.port = config.sv_port;
-	}
-	else
-	{
-		mem_zero(&bindaddr, sizeof(bindaddr));
-		bindaddr.port = config.sv_port;
-	}
-	
-	
-	if(!m_NetServer.Open(bindaddr, config.sv_max_clients, 0))
-	{
-		dbg_msg("server", "couldn't open socket. port might already be in use");
-		return -1;
-	}
-
-	m_NetServer.SetCallbacks(new_client_callback, del_client_callback, this);
-	
-	dbg_msg("server", "server name is '%s'", config.sv_name);
-	
-	mods_init();
-	dbg_msg("server", "version %s", mods_net_version());
-
-	/* start game */
-	{
-		int64 reporttime = time_get();
-		int reportinterval = 3;
-	
-		lastheartbeat = 0;
-		game_start_time = time_get();
-	
-		if(config.debug)
-			dbg_msg("server", "baseline memory usage %dk", mem_stats()->allocated/1024);
-
-		while(run_server)
-		{
-			static PERFORMACE_INFO rootscope = {"root", 0};
-			int64 t = time_get();
-			int new_ticks = 0;
-			
-			perf_start(&rootscope);
-			
-			/* load new map TODO: don't poll this */
-			if(strcmp(config.sv_map, current_map) != 0 || config.sv_map_reload)
-			{
-				config.sv_map_reload = 0;
-				
-				/* load map */
-				if(server_load_map(config.sv_map))
-				{
-					int c;
-					
-					/* new map loaded */
-					mods_shutdown();
-					
-					for(c = 0; c < MAX_CLIENTS; c++)
-					{
-						if(m_aClients[c].state == CClient::STATE_EMPTY)
-							continue;
-						
-						server_send_map(c);
-						reset_client(c);
-						m_aClients[c].state = CClient::STATE_CONNECTING;
-					}
-					
-					game_start_time = time_get();
-					current_tick = 0;
-					mods_init();
-				}
-				else
-				{
-					dbg_msg("server", "failed to load map. mapname='%s'", config.sv_map);
-					config_set_sv_map(&config, current_map);
-				}
-			}
-			
-			while(t > server_tick_start_time(current_tick+1))
-			{
-				current_tick++;
-				new_ticks++;
-				
-				/* apply new input */
-				{
-					static PERFORMACE_INFO scope = {"input", 0};
-					int c, i;
-					
-					perf_start(&scope);
-					
-					for(c = 0; c < MAX_CLIENTS; c++)
-					{
-						if(m_aClients[c].state == CClient::STATE_EMPTY)
-							continue;
-						for(i = 0; i < 200; i++)
-						{
-							if(m_aClients[c].inputs[i].game_tick == server_tick())
-							{
-								if(m_aClients[c].state == CClient::STATE_INGAME)
-									mods_client_predicted_input(c, m_aClients[c].inputs[i].data);
-								break;
-							}
-						}
-					}
-					
-					perf_end();
-				}
-				
-				/* progress game */
-				{
-					static PERFORMACE_INFO scope = {"tick", 0};
-					perf_start(&scope);
-					mods_tick();
-					perf_end();
-				}
-			}
-			
-			/* snap game */
-			if(new_ticks)
-			{
-				if(config.sv_high_bandwidth || (current_tick%2) == 0)
-				{
-					static PERFORMACE_INFO scope = {"snap", 0};
-					perf_start(&scope);
-					server_do_snap();
-					perf_end();
-				}
-			}
-			
-			/* master server stuff */
-			register_update();
-	
-
-			{
-				static PERFORMACE_INFO scope = {"net", 0};
-				perf_start(&scope);
-				server_pump_network();
-				perf_end();
-			}
-
-			perf_end();
-	
-			if(reporttime < time_get())
-			{
-				if(config.debug)
-				{
-					/*
-					static NETSTATS prev_stats;
-					NETSTATS stats;
-					netserver_stats(net, &stats);
-					
-					perf_next();
-					
-					if(config.dbg_pref)
-						perf_dump(&rootscope);
-
-					dbg_msg("server", "send=%8d recv=%8d",
-						(stats.send_bytes - prev_stats.send_bytes)/reportinterval,
-						(stats.recv_bytes - prev_stats.recv_bytes)/reportinterval);
-						
-					prev_stats = stats;
-					*/
-				}
-	
-				reporttime += time_freq()*reportinterval;
-			}
-			
-			/* wait for incomming data */
-			net_socket_read_wait(m_NetServer.Socket(), 5);
-		}
-	}
-
-	mods_shutdown();
-	map_unload();
-
-	if(current_map_data)
-		mem_free(current_map_data);
-	return 0;
-}
-
-
-#endif
-
-int main(int argc, char **argv)
-{
-	
-	m_pNetServer = &g_Server.m_NetServer;
-#if defined(CONF_FAMILY_WINDOWS)
-	int i;
-	for(i = 1; i < argc; i++)
-	{
-		if(strcmp("-s", argv[i]) == 0 || strcmp("--silent", argv[i]) == 0)
-		{
-			ShowWindow(GetConsoleWindow(), SW_HIDE);
-			break;
-		}
-	}
-#endif
-
-	/* init the engine */
-	dbg_msg("server", "starting...");
-	engine_init("Teeworlds");
-	
-	/* register all console commands */
-	
-	g_Server.RegisterCommands();
-	mods_console_init();
-	
-	/* parse the command line arguments */
-	engine_parse_arguments(argc, argv);
-	
-	/* run the server */
-	g_Server.Run();
-	return 0;
-}
-
diff --git a/src/engine/server/register.cpp b/src/engine/server/register.cpp
new file mode 100644
index 00000000..959b9288
--- /dev/null
+++ b/src/engine/server/register.cpp
@@ -0,0 +1,264 @@
+#include <base/system.h>
+#include <engine/shared/network.h>
+#include <engine/shared/config.h>
+#include <engine/shared/engine.h>
+#include <engine/masterserver.h>
+
+#include <mastersrv/mastersrv.h>
+
+#include "register.h"
+
+CRegister::CRegister()
+{
+	m_pNetServer = 0;
+	m_pMasterServer = 0;
+
+	m_RegisterState = REGISTERSTATE_START;
+	m_RegisterStateStart = 0;
+	m_RegisterFirst = 1;
+	m_RegisterCount = 0;
+
+	mem_zero(m_aMasterserverInfo, sizeof(m_aMasterserverInfo));
+	m_RegisterRegisteredServer = -1;
+}
+
+void CRegister::RegisterNewState(int State)
+{
+	m_RegisterState = State;
+	m_RegisterStateStart = time_get();
+}
+
+void CRegister::RegisterSendFwcheckresponse(NETADDR *pAddr)
+{
+	CNetChunk Packet;
+	Packet.m_ClientID = -1;
+	Packet.m_Address = *pAddr;
+	Packet.m_Flags = NETSENDFLAG_CONNLESS;
+	Packet.m_DataSize = sizeof(SERVERBROWSE_FWRESPONSE);
+	Packet.m_pData = SERVERBROWSE_FWRESPONSE;
+	m_pNetServer->Send(&Packet);
+}
+	
+void CRegister::RegisterSendHeartbeat(NETADDR Addr)
+{
+	static unsigned char aData[sizeof(SERVERBROWSE_HEARTBEAT) + 2];
+	unsigned short Port = g_Config.m_SvPort;
+	CNetChunk Packet;
+	
+	mem_copy(aData, SERVERBROWSE_HEARTBEAT, sizeof(SERVERBROWSE_HEARTBEAT));
+	
+	Packet.m_ClientID = -1;
+	Packet.m_Address = Addr;
+	Packet.m_Flags = NETSENDFLAG_CONNLESS;
+	Packet.m_DataSize = sizeof(SERVERBROWSE_HEARTBEAT) + 2;
+	Packet.m_pData = &aData;
+
+	// supply the set port that the master can use if it has problems
+	if(g_Config.m_SvExternalPort)
+		Port = g_Config.m_SvExternalPort;
+	aData[sizeof(SERVERBROWSE_HEARTBEAT)] = Port >> 8;
+	aData[sizeof(SERVERBROWSE_HEARTBEAT)+1] = Port&0xff;
+	m_pNetServer->Send(&Packet);
+}
+
+void CRegister::RegisterSendCountRequest(NETADDR Addr)
+{
+	CNetChunk Packet;
+	Packet.m_ClientID = -1;
+	Packet.m_Address = Addr;
+	Packet.m_Flags = NETSENDFLAG_CONNLESS;
+	Packet.m_DataSize = sizeof(SERVERBROWSE_GETCOUNT);
+	Packet.m_pData = SERVERBROWSE_GETCOUNT;
+	m_pNetServer->Send(&Packet);
+}
+
+void CRegister::RegisterGotCount(CNetChunk *pChunk)
+{
+	unsigned char *pData = (unsigned char *)pChunk->m_pData;
+	int Count = (pData[sizeof(SERVERBROWSE_COUNT)]<<8) | pData[sizeof(SERVERBROWSE_COUNT)+1];
+
+	for(int i = 0; i < IMasterServer::MAX_MASTERSERVERS; i++)
+	{
+		if(net_addr_comp(&m_aMasterserverInfo[i].m_Addr, &pChunk->m_Address) == 0)
+		{
+			m_aMasterserverInfo[i].m_Count = Count;
+			break;
+		}
+	}
+}
+
+void CRegister::Init(CNetServer *pNetServer, IEngineMasterServer *pMasterServer)
+{
+	m_pNetServer = pNetServer;
+	m_pMasterServer = pMasterServer;
+}
+
+void CRegister::RegisterUpdate()
+{
+	int64 Now = time_get();
+	int64 Freq = time_freq();
+
+	if(!g_Config.m_SvRegister)
+		return;
+
+	m_pMasterServer->Update();
+
+	if(m_RegisterState == REGISTERSTATE_START)
+	{
+		m_RegisterCount = 0;
+		m_RegisterFirst = 1;
+		RegisterNewState(REGISTERSTATE_UPDATE_ADDRS);
+		m_pMasterServer->RefreshAddresses();
+		dbg_msg("register", "refreshing ip addresses");
+	}
+	else if(m_RegisterState == REGISTERSTATE_UPDATE_ADDRS)
+	{
+		m_RegisterRegisteredServer = -1;
+	
+		if(!m_pMasterServer->IsRefreshing())
+		{
+			int i;
+			for(i = 0; i < IMasterServer::MAX_MASTERSERVERS; i++)
+			{
+				NETADDR addr = m_pMasterServer->GetAddr(i);
+				m_aMasterserverInfo[i].m_Addr = addr;
+				m_aMasterserverInfo[i].m_Count = 0;
+			
+				if(!addr.ip[0] && !addr.ip[1] && !addr.ip[2] && !addr.ip[3])
+					m_aMasterserverInfo[i].m_Valid = 0;
+				else
+				{
+					m_aMasterserverInfo[i].m_Valid = 1;
+					m_aMasterserverInfo[i].m_Count = -1;
+					m_aMasterserverInfo[i].m_LastSend = 0;
+				}
+			}
+			
+			dbg_msg("register", "fetching server counts");
+			RegisterNewState(REGISTERSTATE_QUERY_COUNT);
+		}
+	}
+	else if(m_RegisterState == REGISTERSTATE_QUERY_COUNT)
+	{
+		int Left = 0;
+		for(int i = 0; i < IMasterServer::MAX_MASTERSERVERS; i++)
+		{
+			if(!m_aMasterserverInfo[i].m_Valid)
+				continue;
+				
+			if(m_aMasterserverInfo[i].m_Count == -1)
+			{
+				Left++;
+				if(m_aMasterserverInfo[i].m_LastSend+Freq < Now)
+				{
+					m_aMasterserverInfo[i].m_LastSend = Now;
+					RegisterSendCountRequest(m_aMasterserverInfo[i].m_Addr);
+				}
+			}
+		}
+		
+		// check if we are done or timed out
+		if(Left == 0 || Now > m_RegisterStateStart+Freq*3)
+		{
+			// choose server
+			int Best = -1;
+			int i;
+			for(i = 0; i < IMasterServer::MAX_MASTERSERVERS; i++)
+			{
+				if(!m_aMasterserverInfo[i].m_Valid || m_aMasterserverInfo[i].m_Count == -1)
+					continue;
+					
+				if(Best == -1 || m_aMasterserverInfo[i].m_Count < m_aMasterserverInfo[Best].m_Count)
+					Best = i;
+			}
+
+			// server chosen
+			m_RegisterRegisteredServer = Best;
+			if(m_RegisterRegisteredServer == -1)
+			{
+				dbg_msg("register", "WARNING: No master servers. Retrying in 60 seconds");
+				RegisterNewState(REGISTERSTATE_ERROR);
+			}
+			else
+			{			
+				dbg_msg("register", "choosen '%s' as master, sending heartbeats", m_pMasterServer->GetName(m_RegisterRegisteredServer));
+				m_aMasterserverInfo[m_RegisterRegisteredServer].m_LastSend = 0;
+				RegisterNewState(REGISTERSTATE_HEARTBEAT);
+			}
+		}
+	}
+	else if(m_RegisterState == REGISTERSTATE_HEARTBEAT)
+	{
+		// check if we should send heartbeat
+		if(Now > m_aMasterserverInfo[m_RegisterRegisteredServer].m_LastSend+Freq*15)
+		{
+			m_aMasterserverInfo[m_RegisterRegisteredServer].m_LastSend = Now;
+			RegisterSendHeartbeat(m_aMasterserverInfo[m_RegisterRegisteredServer].m_Addr);
+		}
+		
+		if(Now > m_RegisterStateStart+Freq*60)
+		{
+			dbg_msg("register", "WARNING: Master server is not responding, switching master");
+			RegisterNewState(REGISTERSTATE_START);
+		}
+	}
+	else if(m_RegisterState == REGISTERSTATE_REGISTERED)
+	{
+		if(m_RegisterFirst)
+			dbg_msg("register", "server registered");
+			
+		m_RegisterFirst = 0;
+		
+		// check if we should send new heartbeat again
+		if(Now > m_RegisterStateStart+Freq)
+		{
+			if(m_RegisterCount == 120) // redo the whole process after 60 minutes to balance out the master servers
+				RegisterNewState(REGISTERSTATE_START);
+			else
+			{
+				m_RegisterCount++;
+				RegisterNewState(REGISTERSTATE_HEARTBEAT);
+			}
+		}
+	}
+	else if(m_RegisterState == REGISTERSTATE_ERROR)
+	{
+		// check for restart
+		if(Now > m_RegisterStateStart+Freq*60)
+			RegisterNewState(REGISTERSTATE_START);
+	}
+}
+
+int CRegister::RegisterProcessPacket(CNetChunk *pPacket)
+{
+	if(pPacket->m_DataSize == sizeof(SERVERBROWSE_FWCHECK) &&
+		mem_comp(pPacket->m_pData, SERVERBROWSE_FWCHECK, sizeof(SERVERBROWSE_FWCHECK)) == 0)
+	{
+		RegisterSendFwcheckresponse(&pPacket->m_Address);
+		return 1;
+	}
+	else if(pPacket->m_DataSize == sizeof(SERVERBROWSE_FWOK) &&
+		mem_comp(pPacket->m_pData, SERVERBROWSE_FWOK, sizeof(SERVERBROWSE_FWOK)) == 0)
+	{
+		if(m_RegisterFirst)
+			dbg_msg("register", "no firewall/nat problems detected");
+		RegisterNewState(REGISTERSTATE_REGISTERED);
+		return 1;
+	}
+	else if(pPacket->m_DataSize == sizeof(SERVERBROWSE_FWERROR) &&
+		mem_comp(pPacket->m_pData, SERVERBROWSE_FWERROR, sizeof(SERVERBROWSE_FWERROR)) == 0)
+	{
+		dbg_msg("register", "ERROR: the master server reports that clients can not connect to this server.");
+		dbg_msg("register", "ERROR: configure your firewall/nat to let through udp on port %d.", g_Config.m_SvPort);
+		RegisterNewState(REGISTERSTATE_ERROR);
+		return 1;
+	}
+	else if(pPacket->m_DataSize == sizeof(SERVERBROWSE_COUNT)+2 &&
+		mem_comp(pPacket->m_pData, SERVERBROWSE_COUNT, sizeof(SERVERBROWSE_COUNT)) == 0)
+	{
+		RegisterGotCount(pPacket);
+		return 1;
+	}
+
+	return 0;
+}
diff --git a/src/engine/server/register.h b/src/engine/server/register.h
new file mode 100644
index 00000000..a800ec1e
--- /dev/null
+++ b/src/engine/server/register.h
@@ -0,0 +1,48 @@
+#ifndef ENGINE_SERVER_REGISTER_H
+#define ENGINE_SERVER_REGISTER_H
+

+class CRegister

+{

+	enum

+	{

+		REGISTERSTATE_START=0,

+		REGISTERSTATE_UPDATE_ADDRS,

+		REGISTERSTATE_QUERY_COUNT,

+		REGISTERSTATE_HEARTBEAT,

+		REGISTERSTATE_REGISTERED,

+		REGISTERSTATE_ERROR

+	};

+

+	struct CMasterserverInfo

+	{

+		NETADDR m_Addr;

+		int m_Count;

+		int m_Valid;

+		int64 m_LastSend;

+	};

+

+	class CNetServer *m_pNetServer;

+	class IEngineMasterServer *m_pMasterServer;

+

+	int m_RegisterState;

+	int64 m_RegisterStateStart;

+	int m_RegisterFirst;

+	int m_RegisterCount;

+

+	class CMasterserverInfo m_aMasterserverInfo[IMasterServer::MAX_MASTERSERVERS];

+	int m_RegisterRegisteredServer;

+

+	void RegisterNewState(int State);

+	void RegisterSendFwcheckresponse(NETADDR *pAddr);

+	void RegisterSendHeartbeat(NETADDR Addr);

+	void RegisterSendCountRequest(NETADDR Addr);

+	void RegisterGotCount(class CNetChunk *pChunk);

+

+public:

+	CRegister();

+	void Init(class CNetServer *pNetServer, class IEngineMasterServer *pMasterServer);

+	void RegisterUpdate();

+	int RegisterProcessPacket(class CNetChunk *pPacket);

+};

+

+#endif

diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp
new file mode 100644
index 00000000..45cec1e4
--- /dev/null
+++ b/src/engine/server/server.cpp
@@ -0,0 +1,1400 @@
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+
+#include <base/system.h>
+
+#include <engine/shared/config.h>
+#include <engine/shared/engine.h>
+
+#include <engine/shared/protocol.h>
+#include <engine/shared/snapshot.h>
+
+#include <engine/shared/compression.h>
+
+#include <engine/shared/network.h>
+#include <engine/shared/config.h>
+#include <engine/shared/packer.h>
+#include <engine/shared/datafile.h>
+#include <engine/shared/demorec.h>
+
+#include <engine/server.h>
+#include <engine/map.h>
+#include <engine/console.h>
+#include <engine/storage.h>
+#include <engine/masterserver.h>
+#include <engine/config.h>
+
+#include <mastersrv/mastersrv.h>
+
+#include "register.h"
+#include "server.h"
+
+#if defined(CONF_FAMILY_WINDOWS) 
+	#define _WIN32_WINNT 0x0500
+	#define NOGDI
+	#include <windows.h>
+#endif
+
+static const char *StrLtrim(const char *pStr)
+{
+	while(*pStr && *pStr <= 32)
+		pStr++;
+	return pStr;
+}
+
+static void StrRtrim(char *pStr)
+{
+	int i = str_length(pStr);
+	while(i >= 0)
+	{
+		if(pStr[i] > 32)
+			break;
+		pStr[i] = 0;
+		i--;
+	}
+}
+
+
+static int StrAllnum(const char *pStr)
+{
+	while(*pStr)
+	{
+		if(!(*pStr >= '0' && *pStr <= '9'))
+			return 0;
+		pStr++;
+	}
+	return 1;
+}
+
+CSnapIDPool::CSnapIDPool()
+{
+	Reset();
+}
+
+void CSnapIDPool::Reset()
+{
+	for(int i = 0; i < MAX_IDS; i++)
+	{
+		m_aIDs[i].m_Next = i+1;
+		m_aIDs[i].m_State = 0;
+	}
+		
+	m_aIDs[MAX_IDS-1].m_Next = -1;
+	m_FirstFree = 0;
+	m_FirstTimed = -1;
+	m_LastTimed = -1;
+	m_Usage = 0;
+	m_InUsage = 0;
+}
+
+
+void CSnapIDPool::RemoveFirstTimeout()
+{
+	int NextTimed = m_aIDs[m_FirstTimed].m_Next;
+	
+	// add it to the free list
+	m_aIDs[m_FirstTimed].m_Next = m_FirstFree;
+	m_aIDs[m_FirstTimed].m_State = 0;
+	m_FirstFree = m_FirstTimed;
+	
+	// remove it from the timed list
+	m_FirstTimed = NextTimed;
+	if(m_FirstTimed == -1)
+		m_LastTimed = -1;
+		
+	m_Usage--;
+}
+
+int CSnapIDPool::NewID()
+{
+	int64 Now = time_get();
+
+	// process timed ids
+	while(m_FirstTimed != -1 && m_aIDs[m_FirstTimed].m_Timeout < Now)
+		RemoveFirstTimeout();
+	
+	int Id = m_FirstFree;
+	dbg_assert(Id != -1, "id error");
+	m_FirstFree = m_aIDs[m_FirstFree].m_Next;
+	m_aIDs[Id].m_State = 1;
+	m_Usage++;
+	m_InUsage++;
+	return Id;
+}
+
+void CSnapIDPool::TimeoutIDs()
+{
+	// process timed ids
+	while(m_FirstTimed != -1)
+		RemoveFirstTimeout();
+}
+
+void CSnapIDPool::FreeID(int Id)
+{
+	dbg_assert(m_aIDs[Id].m_State == 1, "id is not alloced");
+
+	m_InUsage--;
+	m_aIDs[Id].m_State = 2;
+	m_aIDs[Id].m_Timeout = time_get()+time_freq()*5;
+	m_aIDs[Id].m_Next = -1;
+	
+	if(m_LastTimed != -1)
+	{
+		m_aIDs[m_LastTimed].m_Next = Id;
+		m_LastTimed = Id;
+	}
+	else
+	{
+		m_FirstTimed = Id;
+		m_LastTimed = Id;
+	}
+}
+	
+void CServer::CClient::Reset()
+{
+	// reset input
+	for(int i = 0; i < 200; i++)
+		m_aInputs[i].m_GameTick = -1;
+	m_CurrentInput = 0;
+	mem_zero(&m_LatestInput, sizeof(m_LatestInput));
+
+	m_Snapshots.PurgeAll();
+	m_LastAckedSnapshot = -1;
+	m_LastInputTick = -1;
+	m_SnapRate = CClient::SNAPRATE_INIT;
+	m_Score = 0;
+}
+
+CServer::CServer() : m_DemoRecorder(&m_SnapshotDelta)
+{
+	m_TickSpeed = SERVER_TICK_SPEED;
+	
+	m_pGameServer = 0;
+	
+	m_CurrentGameTick = 0;
+	m_RunServer = 1;
+
+	mem_zero(m_aBrowseinfoGametype, sizeof(m_aBrowseinfoGametype));
+	m_BrowseinfoProgression = -1;
+
+	m_pCurrentMapData = 0;
+	m_CurrentMapSize = 0;
+
+	Init();
+}
+
+
+int CServer::TrySetClientName(int ClientID, const char *pName)
+{
+	char aTrimmedName[64];
+
+	// trim the name
+	str_copy(aTrimmedName, StrLtrim(pName), sizeof(aTrimmedName));
+	StrRtrim(aTrimmedName);
+	dbg_msg("", "'%s' -> '%s'", pName, aTrimmedName);
+	pName = aTrimmedName;
+	
+	
+	// check for empty names
+	if(!pName[0])
+		return -1;
+	
+	// make sure that two clients doesn't have the same name
+	for(int i = 0; i < MAX_CLIENTS; i++)
+		if(i != ClientID && m_aClients[i].m_State >= CClient::STATE_READY)
+		{
+			if(str_comp(pName, m_aClients[i].m_aName) == 0)
+				return -1;
+		}
+
+	// set the client name
+	str_copy(m_aClients[ClientID].m_aName, pName, MAX_NAME_LENGTH);
+	return 0;
+}
+
+
+
+void CServer::SetClientName(int ClientID, const char *pName)
+{
+	if(ClientID < 0 || ClientID >= MAX_CLIENTS || m_aClients[ClientID].m_State < CClient::STATE_READY)
+		return;
+		
+	if(!pName)
+		return;
+		
+	char aNameTry[MAX_NAME_LENGTH];
+	str_copy(aNameTry, pName, MAX_NAME_LENGTH);
+	if(TrySetClientName(ClientID, aNameTry))
+	{
+		// auto rename
+		for(int i = 1;; i++)
+		{
+			str_format(aNameTry, MAX_NAME_LENGTH, "(%d)%s", i, pName);
+			if(TrySetClientName(ClientID, aNameTry) == 0)
+				break;
+		}
+	}
+}
+
+void CServer::SetClientScore(int ClientID, int Score)
+{
+	if(ClientID < 0 || ClientID >= MAX_CLIENTS || m_aClients[ClientID].m_State < CClient::STATE_READY)
+		return;
+	m_aClients[ClientID].m_Score = Score;
+}
+
+void CServer::SetBrowseInfo(const char *pGameType, int Progression)
+{
+	str_copy(m_aBrowseinfoGametype, pGameType, sizeof(m_aBrowseinfoGametype));
+	m_BrowseinfoProgression = Progression;
+	if(m_BrowseinfoProgression > 100)
+		m_BrowseinfoProgression = 100;
+	if(m_BrowseinfoProgression < -1)
+		m_BrowseinfoProgression = -1;
+}
+
+void CServer::Kick(int ClientID, const char *pReason)
+{
+	if(ClientID < 0 || ClientID >= MAX_CLIENTS)
+		return;
+		
+	if(m_aClients[ClientID].m_State != CClient::STATE_EMPTY)
+		m_NetServer.Drop(ClientID, pReason);
+}
+
+/*int CServer::Tick()
+{
+	return m_CurrentGameTick;
+}*/
+
+int64 CServer::TickStartTime(int Tick)
+{
+	return m_GameStartTime + (time_freq()*Tick)/SERVER_TICK_SPEED;
+}
+
+/*int CServer::TickSpeed()
+{
+	return SERVER_TICK_SPEED;
+}*/
+
+int CServer::Init()
+{
+	for(int i = 0; i < MAX_CLIENTS; i++)
+	{
+		m_aClients[i].m_State = CClient::STATE_EMPTY;
+		m_aClients[i].m_aName[0] = 0;
+		m_aClients[i].m_aClan[0] = 0;
+		m_aClients[i].m_Snapshots.Init();
+	}
+
+	m_CurrentGameTick = 0;
+
+	return 0;
+}
+
+int CServer::GetClientInfo(int ClientID, CClientInfo *pInfo)
+{
+	dbg_assert(ClientID >= 0 && ClientID < MAX_CLIENTS, "client_id is not valid");
+	dbg_assert(pInfo != 0, "info can not be null");
+
+	if(m_aClients[ClientID].m_State == CClient::STATE_INGAME)
+	{
+		pInfo->m_pName = m_aClients[ClientID].m_aName;
+		pInfo->m_Latency = m_aClients[ClientID].m_Latency;
+		return 1;
+	}
+	return 0;
+}
+
+void CServer::GetClientIP(int ClientID, char *pIPString, int Size)
+{
+	if(ClientID >= 0 && ClientID < MAX_CLIENTS && m_aClients[ClientID].m_State == CClient::STATE_INGAME)
+	{
+		NETADDR Addr = m_NetServer.ClientAddr(ClientID);
+		str_format(pIPString, Size, "%d.%d.%d.%d", Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3]);
+	}
+}
+	
+
+int *CServer::LatestInput(int ClientId, int *size)
+{
+	if(ClientId < 0 || ClientId >= MAX_CLIENTS || m_aClients[ClientId].m_State < CServer::CClient::STATE_READY)
+		return 0;
+	return m_aClients[ClientId].m_LatestInput.m_aData;
+}
+
+const char *CServer::ClientName(int ClientId)
+{
+	if(ClientId < 0 || ClientId >= MAX_CLIENTS || m_aClients[ClientId].m_State < CServer::CClient::STATE_READY)
+		return "(invalid client)";
+	return m_aClients[ClientId].m_aName;
+}	
+
+bool CServer::ClientIngame(int ClientID)
+{
+	return ClientID >= 0 && ClientID < MAX_CLIENTS && m_aClients[ClientID].m_State == CServer::CClient::STATE_INGAME;
+}
+
+int CServer::SendMsg(CMsgPacker *pMsg, int Flags, int ClientId)
+{
+	return SendMsgEx(pMsg, Flags, ClientId, false);
+}
+
+int CServer::SendMsgEx(CMsgPacker *pMsg, int Flags, int ClientID, bool System)
+{
+	CNetChunk Packet;
+	if(!pMsg)
+		return -1;
+		
+	mem_zero(&Packet, sizeof(CNetChunk));
+	
+	Packet.m_ClientID = ClientID;
+	Packet.m_pData = pMsg->Data();
+	Packet.m_DataSize = pMsg->Size();
+	
+	// HACK: modify the message id in the packet and store the system flag
+	*((unsigned char*)Packet.m_pData) <<= 1;
+	if(System)
+		*((unsigned char*)Packet.m_pData) |= 1;
+
+	if(Flags&MSGFLAG_VITAL)
+		Packet.m_Flags |= NETSENDFLAG_VITAL;
+	if(Flags&MSGFLAG_FLUSH)
+		Packet.m_Flags |= NETSENDFLAG_FLUSH;
+	
+	// write message to demo recorder
+	if(!(Flags&MSGFLAG_NORECORD))
+		m_DemoRecorder.RecordMessage(pMsg->Data(), pMsg->Size());
+
+	if(!(Flags&MSGFLAG_NOSEND))
+	{
+		if(ClientID == -1)
+		{
+			// broadcast
+			int i;
+			for(i = 0; i < MAX_CLIENTS; i++)
+				if(m_aClients[i].m_State == CClient::STATE_INGAME)
+				{
+					Packet.m_ClientID = i;
+					m_NetServer.Send(&Packet);
+				}
+		}
+		else
+			m_NetServer.Send(&Packet);
+	}
+	return 0;
+}
+
+void CServer::DoSnapshot()
+{
+	GameServer()->OnPreSnap();
+	
+	// create snapshot for demo recording
+	if(m_DemoRecorder.IsRecording())
+	{
+		char aData[CSnapshot::MAX_SIZE];
+		int SnapshotSize;
+
+		// build snap and possibly add some messages
+		m_SnapshotBuilder.Init();
+		GameServer()->OnSnap(-1);
+		SnapshotSize = m_SnapshotBuilder.Finish(aData);
+		
+		// write snapshot
+		m_DemoRecorder.RecordSnapshot(Tick(), aData, SnapshotSize);
+	}
+
+	// create snapshots for all clients
+	for(int i = 0; i < MAX_CLIENTS; i++)
+	{
+		// client must be ingame to recive snapshots
+		if(m_aClients[i].m_State != CClient::STATE_INGAME)
+			continue;
+			
+		// this client is trying to recover, don't spam snapshots
+		if(m_aClients[i].m_SnapRate == CClient::SNAPRATE_RECOVER && (Tick()%50) != 0)
+			continue;
+			
+		// this client is trying to recover, don't spam snapshots
+		if(m_aClients[i].m_SnapRate == CClient::SNAPRATE_INIT && (Tick()%10) != 0)
+			continue;
+			
+		{
+			char aData[CSnapshot::MAX_SIZE];
+			char aDeltaData[CSnapshot::MAX_SIZE];
+			char aCompData[CSnapshot::MAX_SIZE];
+			int SnapshotSize;
+			int Crc;
+			static CSnapshot EmptySnap;
+			CSnapshot *pDeltashot = &EmptySnap;
+			int DeltashotSize;
+			int DeltaTick = -1;
+			int DeltaSize;
+
+			m_SnapshotBuilder.Init();
+
+			GameServer()->OnSnap(i);
+
+			// finish snapshot
+			SnapshotSize = m_SnapshotBuilder.Finish(aData);
+			Crc = ((CSnapshot*)aData)->Crc();
+
+			// remove old snapshos
+			// keep 3 seconds worth of snapshots
+			m_aClients[i].m_Snapshots.PurgeUntil(m_CurrentGameTick-SERVER_TICK_SPEED*3);
+			
+			// save it the snapshot
+			m_aClients[i].m_Snapshots.Add(m_CurrentGameTick, time_get(), SnapshotSize, aData, 0);
+			
+			// find snapshot that we can preform delta against
+			EmptySnap.Clear();
+			
+			{
+				DeltashotSize = m_aClients[i].m_Snapshots.Get(m_aClients[i].m_LastAckedSnapshot, 0, &pDeltashot, 0);
+				if(DeltashotSize >= 0)
+					DeltaTick = m_aClients[i].m_LastAckedSnapshot;
+				else
+				{
+					// no acked package found, force client to recover rate
+					if(m_aClients[i].m_SnapRate == CClient::SNAPRATE_FULL)
+						m_aClients[i].m_SnapRate = CClient::SNAPRATE_RECOVER;
+				}
+			}
+			
+			// create delta
+			DeltaSize = m_SnapshotDelta.CreateDelta(pDeltashot, (CSnapshot*)aData, aDeltaData);
+			
+			if(DeltaSize)
+			{
+				// compress it
+				int SnapshotSize;
+				const int MaxSize = MAX_SNAPSHOT_PACKSIZE;
+				int NumPackets;
+
+				SnapshotSize = CVariableInt::Compress(aDeltaData, DeltaSize, aCompData);
+				NumPackets = (SnapshotSize+MaxSize-1)/MaxSize;
+				
+				for(int n = 0, Left = SnapshotSize; Left; n++)
+				{
+					int Chunk = Left < MaxSize ? Left : MaxSize;
+					Left -= Chunk;
+
+					if(NumPackets == 1)
+					{
+						CMsgPacker Msg(NETMSG_SNAPSINGLE);
+						Msg.AddInt(m_CurrentGameTick);
+						Msg.AddInt(m_CurrentGameTick-DeltaTick);
+						Msg.AddInt(Crc);
+						Msg.AddInt(Chunk);
+						Msg.AddRaw(&aCompData[n*MaxSize], Chunk);
+						SendMsgEx(&Msg, MSGFLAG_FLUSH, i, true);
+					}
+					else
+					{
+						CMsgPacker Msg(NETMSG_SNAP);
+						Msg.AddInt(m_CurrentGameTick);
+						Msg.AddInt(m_CurrentGameTick-DeltaTick);
+						Msg.AddInt(NumPackets);
+						Msg.AddInt(n);							
+						Msg.AddInt(Crc);
+						Msg.AddInt(Chunk);
+						Msg.AddRaw(&aCompData[n*MaxSize], Chunk);
+						SendMsgEx(&Msg, MSGFLAG_FLUSH, i, true);
+					}
+				}
+			}
+			else
+			{
+				CMsgPacker Msg(NETMSG_SNAPEMPTY);
+				Msg.AddInt(m_CurrentGameTick);
+				Msg.AddInt(m_CurrentGameTick-DeltaTick);
+				SendMsgEx(&Msg, MSGFLAG_FLUSH, i, true);
+			}
+		}
+	}
+
+	GameServer()->OnPostSnap();
+}
+
+
+int CServer::NewClientCallback(int ClientId, void *pUser)
+{
+	CServer *pThis = (CServer *)pUser;
+	pThis->m_aClients[ClientId].m_State = CClient::STATE_AUTH;
+	pThis->m_aClients[ClientId].m_aName[0] = 0;
+	pThis->m_aClients[ClientId].m_aClan[0] = 0;
+	pThis->m_aClients[ClientId].m_Authed = 0;
+	pThis->m_aClients[ClientId].Reset();
+	return 0;
+}
+
+int CServer::DelClientCallback(int ClientId, void *pUser)
+{
+	CServer *pThis = (CServer *)pUser;
+	
+	// notify the mod about the drop
+	if(pThis->m_aClients[ClientId].m_State >= CClient::STATE_READY)
+		pThis->GameServer()->OnClientDrop(ClientId);
+	
+	pThis->m_aClients[ClientId].m_State = CClient::STATE_EMPTY;
+	pThis->m_aClients[ClientId].m_aName[0] = 0;
+	pThis->m_aClients[ClientId].m_aClan[0] = 0;
+	pThis->m_aClients[ClientId].m_Authed = 0;
+	pThis->m_aClients[ClientId].m_Snapshots.PurgeAll();
+	return 0;
+}
+
+void CServer::SendMap(int ClientId)
+{
+	CMsgPacker Msg(NETMSG_MAP_CHANGE);
+	Msg.AddString(g_Config.m_SvMap, 0);
+	Msg.AddInt(m_CurrentMapCrc);
+	SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientId, true);
+}
+
+void CServer::SendRconLine(int ClientId, const char *pLine)
+{
+	CMsgPacker Msg(NETMSG_RCON_LINE);
+	Msg.AddString(pLine, 512);
+	SendMsgEx(&Msg, MSGFLAG_VITAL, ClientId, true);
+}
+
+void CServer::SendRconLineAuthed(const char *pLine, void *pUser)
+{
+	CServer *pThis = (CServer *)pUser;
+	static volatile int ReentryGuard = 0;
+	int i;
+	
+	if(ReentryGuard) return;
+	ReentryGuard++;
+	
+	for(i = 0; i < MAX_CLIENTS; i++)
+	{
+		if(pThis->m_aClients[i].m_State != CClient::STATE_EMPTY && pThis->m_aClients[i].m_Authed)
+			pThis->SendRconLine(i, pLine);
+	}
+	
+	ReentryGuard--;
+}
+
+void CServer::ProcessClientPacket(CNetChunk *pPacket)
+{
+	int ClientId = pPacket->m_ClientID;
+	NETADDR Addr;
+	CUnpacker Unpacker;
+	Unpacker.Reset(pPacket->m_pData, pPacket->m_DataSize);
+	
+	// unpack msgid and system flag
+	int Msg = Unpacker.GetInt();
+	int Sys = Msg&1;
+	Msg >>= 1;
+	
+	if(Unpacker.Error())
+		return;
+	
+	if(m_aClients[ClientId].m_State == CClient::STATE_AUTH)
+	{
+		if(Sys && Msg == NETMSG_INFO)
+		{
+			char aVersion[64];
+			const char *pPassword;
+			str_copy(aVersion, Unpacker.GetString(), 64);
+			if(str_comp(aVersion, GameServer()->NetVersion()) != 0)
+			{
+				// OH FUCK! wrong version, drop him
+				char aReason[256];
+				str_format(aReason, sizeof(aReason), "wrong version. server is running '%s' and client '%s'.", GameServer()->NetVersion(), aVersion);
+				m_NetServer.Drop(ClientId, aReason);
+				return;
+			}
+			
+			str_copy(m_aClients[ClientId].m_aName, Unpacker.GetString(), MAX_NAME_LENGTH);
+			str_copy(m_aClients[ClientId].m_aClan, Unpacker.GetString(), MAX_CLANNAME_LENGTH);
+			pPassword = Unpacker.GetString();
+			
+			if(g_Config.m_Password[0] != 0 && str_comp(g_Config.m_Password, pPassword) != 0)
+			{
+				// wrong password
+				m_NetServer.Drop(ClientId, "wrong password");
+				return;
+			}
+			
+			m_aClients[ClientId].m_State = CClient::STATE_CONNECTING;
+			SendMap(ClientId);
+		}
+	}
+	else
+	{
+		if(Sys)
+		{
+			// system message
+			if(Msg == NETMSG_REQUEST_MAP_DATA)
+			{
+				int Chunk = Unpacker.GetInt();
+				int ChunkSize = 1024-128;
+				int Offset = Chunk * ChunkSize;
+				int Last = 0;
+				
+				// drop faulty map data requests
+				if(Chunk < 0 || Offset > m_CurrentMapSize)
+					return;
+				
+				if(Offset+ChunkSize >= m_CurrentMapSize)
+				{
+					ChunkSize = m_CurrentMapSize-Offset;
+					if(ChunkSize < 0)
+						ChunkSize = 0;
+					Last = 1;
+				}
+				
+				CMsgPacker Msg(NETMSG_MAP_DATA);
+				Msg.AddInt(Last);
+				Msg.AddInt(m_CurrentMapSize);
+				Msg.AddInt(ChunkSize);
+				Msg.AddRaw(&m_pCurrentMapData[Offset], ChunkSize);
+				SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientId, true);
+				
+				if(g_Config.m_Debug)
+					dbg_msg("server", "sending chunk %d with size %d", Chunk, ChunkSize);
+			}
+			else if(Msg == NETMSG_READY)
+			{
+				if(m_aClients[ClientId].m_State == CClient::STATE_CONNECTING)
+				{
+					Addr = m_NetServer.ClientAddr(ClientId);
+					
+					dbg_msg("server", "player is ready. ClientId=%x ip=%d.%d.%d.%d",
+						ClientId, Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3]);
+					m_aClients[ClientId].m_State = CClient::STATE_READY;
+					GameServer()->OnClientConnected(ClientId);
+				}
+			}
+			else if(Msg == NETMSG_ENTERGAME)
+			{
+				if(m_aClients[ClientId].m_State == CClient::STATE_READY)
+				{
+					Addr = m_NetServer.ClientAddr(ClientId);
+					
+					dbg_msg("server", "player has entered the game. ClientId=%x ip=%d.%d.%d.%d",
+						ClientId, Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3]);
+					m_aClients[ClientId].m_State = CClient::STATE_INGAME;
+					GameServer()->OnClientEnter(ClientId);
+				}
+			}
+			else if(Msg == NETMSG_INPUT)
+			{
+				CClient::CInput *pInput;
+				int64 TagTime;
+				
+				m_aClients[ClientId].m_LastAckedSnapshot = Unpacker.GetInt();
+				int IntendedTick = Unpacker.GetInt();
+				int Size = Unpacker.GetInt();
+				
+				// check for errors
+				if(Unpacker.Error() || Size/4 > MAX_INPUT_SIZE)
+					return;
+
+				if(m_aClients[ClientId].m_LastAckedSnapshot > 0)
+					m_aClients[ClientId].m_SnapRate = CClient::SNAPRATE_FULL;
+					
+				if(m_aClients[ClientId].m_Snapshots.Get(m_aClients[ClientId].m_LastAckedSnapshot, &TagTime, 0, 0) >= 0)
+					m_aClients[ClientId].m_Latency = (int)(((time_get()-TagTime)*1000)/time_freq());
+
+				// add message to report the input timing
+				// skip packets that are old
+				if(IntendedTick > m_aClients[ClientId].m_LastInputTick)
+				{
+					int TimeLeft = ((TickStartTime(IntendedTick)-time_get())*1000) / time_freq();
+					
+					CMsgPacker Msg(NETMSG_INPUTTIMING);
+					Msg.AddInt(IntendedTick);
+					Msg.AddInt(TimeLeft);
+					SendMsgEx(&Msg, 0, ClientId, true);
+				}
+
+				m_aClients[ClientId].m_LastInputTick = IntendedTick;
+
+				pInput = &m_aClients[ClientId].m_aInputs[m_aClients[ClientId].m_CurrentInput];
+				
+				if(IntendedTick <= Tick())
+					IntendedTick = Tick()+1;
+
+				pInput->m_GameTick = IntendedTick;
+				
+				for(int i = 0; i < Size/4; i++)
+					pInput->m_aData[i] = Unpacker.GetInt();
+				
+				mem_copy(m_aClients[ClientId].m_LatestInput.m_aData, pInput->m_aData, MAX_INPUT_SIZE*sizeof(int));
+				
+				m_aClients[ClientId].m_CurrentInput++;
+				m_aClients[ClientId].m_CurrentInput %= 200;
+			
+				// call the mod with the fresh input data
+				if(m_aClients[ClientId].m_State == CClient::STATE_INGAME)
+					GameServer()->OnClientDirectInput(ClientId, m_aClients[ClientId].m_LatestInput.m_aData);
+			}
+			else if(Msg == NETMSG_RCON_CMD)
+			{
+				const char *pCmd = Unpacker.GetString();
+				
+				if(Unpacker.Error() == 0 && m_aClients[ClientId].m_Authed)
+				{
+					dbg_msg("server", "ClientId=%d rcon='%s'", ClientId, pCmd);
+					Console()->ExecuteLine(pCmd);
+				}
+			}
+			else if(Msg == NETMSG_RCON_AUTH)
+			{
+				const char *pPw;
+				Unpacker.GetString(); // login name, not used
+				pPw = Unpacker.GetString();
+				
+				if(Unpacker.Error() == 0)
+				{
+					if(g_Config.m_SvRconPassword[0] == 0)
+					{
+						SendRconLine(ClientId, "No rcon password set on server. Set sv_rcon_password to enable the remote console.");
+					}
+					else if(str_comp(pPw, g_Config.m_SvRconPassword) == 0)
+					{
+						CMsgPacker Msg(NETMSG_RCON_AUTH_STATUS);
+						Msg.AddInt(1);
+						SendMsgEx(&Msg, MSGFLAG_VITAL, ClientId, true);
+						
+						m_aClients[ClientId].m_Authed = 1;
+						SendRconLine(ClientId, "Authentication successful. Remote console access granted.");
+						dbg_msg("server", "ClientId=%d authed", ClientId);
+					}
+					else
+					{
+						SendRconLine(ClientId, "Wrong password.");
+					}
+				}
+			}
+			else if(Msg == NETMSG_PING)
+			{
+				CMsgPacker Msg(NETMSG_PING_REPLY);
+				SendMsgEx(&Msg, 0, ClientId, true);
+			}
+			else
+			{
+				char aHex[] = "0123456789ABCDEF";
+				char aBuf[512];
+
+				for(int b = 0; b < pPacket->m_DataSize && b < 32; b++)
+				{
+					aBuf[b*3] = aHex[((const unsigned char *)pPacket->m_pData)[b]>>4];
+					aBuf[b*3+1] = aHex[((const unsigned char *)pPacket->m_pData)[b]&0xf];
+					aBuf[b*3+2] = ' ';
+					aBuf[b*3+3] = 0;
+				}
+
+				dbg_msg("server", "strange message ClientId=%d msg=%d data_size=%d", ClientId, Msg, pPacket->m_DataSize);
+				dbg_msg("server", "%s", aBuf);
+				
+			}
+		}
+		else
+		{
+			// game message
+			if(m_aClients[ClientId].m_State >= CClient::STATE_READY)
+				GameServer()->OnMessage(Msg, &Unpacker, ClientId);
+		}
+	}
+}
+	
+void CServer::SendServerInfo(NETADDR *pAddr, int Token)
+{
+	CNetChunk Packet;
+	CPacker p;
+	char aBuf[128];
+
+	// count the players
+	int PlayerCount = 0;
+	for(int i = 0; i < MAX_CLIENTS; i++)
+	{
+		if(m_aClients[i].m_State != CClient::STATE_EMPTY)
+			PlayerCount++;
+	}
+	
+	p.Reset();
+
+	if(Token >= 0)
+	{
+		// new token based format
+		p.AddRaw(SERVERBROWSE_INFO, sizeof(SERVERBROWSE_INFO));
+		str_format(aBuf, sizeof(aBuf), "%d", Token);
+		p.AddString(aBuf, 6);
+	}
+	else
+	{
+		// old format
+		p.AddRaw(SERVERBROWSE_OLD_INFO, sizeof(SERVERBROWSE_OLD_INFO));
+	}
+	
+	p.AddString(GameServer()->Version(), 32);
+	p.AddString(g_Config.m_SvName, 64);
+	p.AddString(g_Config.m_SvMap, 32);
+
+	// gametype
+	p.AddString(m_aBrowseinfoGametype, 16);
+
+	// flags
+	int i = 0;
+	if(g_Config.m_Password[0])   // password set
+		i |= SERVER_FLAG_PASSWORD;
+	str_format(aBuf, sizeof(aBuf), "%d", i);
+	p.AddString(aBuf, 2);
+
+	// progression
+	str_format(aBuf, sizeof(aBuf), "%d", m_BrowseinfoProgression);
+	p.AddString(aBuf, 4);
+	
+	str_format(aBuf, sizeof(aBuf), "%d", PlayerCount); p.AddString(aBuf, 3);  // num players
+	str_format(aBuf, sizeof(aBuf), "%d", m_NetServer.MaxClients()); p.AddString(aBuf, 3); // max players
+
+	for(i = 0; i < MAX_CLIENTS; i++)
+	{
+		if(m_aClients[i].m_State != CClient::STATE_EMPTY)
+		{
+			p.AddString(m_aClients[i].m_aName, 48);  // player name
+			str_format(aBuf, sizeof(aBuf), "%d", m_aClients[i].m_Score); p.AddString(aBuf, 6);  // player score
+		}
+	}
+	
+	
+	Packet.m_ClientID = -1;
+	Packet.m_Address = *pAddr;
+	Packet.m_Flags = NETSENDFLAG_CONNLESS;
+	Packet.m_DataSize = p.Size();
+	Packet.m_pData = p.Data();
+	m_NetServer.Send(&Packet);
+}
+
+void CServer::UpdateServerInfo()
+{
+	for(int i = 0; i < MAX_CLIENTS; ++i)
+	{
+		if(m_aClients[i].m_State != CClient::STATE_EMPTY)
+		{
+			NETADDR Addr = m_NetServer.ClientAddr(i);
+			SendServerInfo(&Addr, -1); 	// SERVERBROWSE_OLD_INFO
+		}
+	}
+}
+
+int CServer::BanAdd(NETADDR Addr, int Seconds)
+{
+	return m_NetServer.BanAdd(Addr, Seconds);	
+}
+
+int CServer::BanRemove(NETADDR Addr)
+{
+	return m_NetServer.BanRemove(Addr);
+}
+	
+
+void CServer::PumpNetwork()
+{
+	CNetChunk Packet;
+
+	m_NetServer.Update();
+	
+	// process packets
+	while(m_NetServer.Recv(&Packet))
+	{
+		if(Packet.m_ClientID == -1)
+		{
+			// stateless
+			if(!m_Register.RegisterProcessPacket(&Packet))
+			{
+				if(Packet.m_DataSize == sizeof(SERVERBROWSE_GETINFO)+1 &&
+					mem_comp(Packet.m_pData, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO)) == 0)
+				{
+					SendServerInfo(&Packet.m_Address, ((unsigned char *)Packet.m_pData)[sizeof(SERVERBROWSE_GETINFO)]);
+				}
+				
+				
+				if(Packet.m_DataSize == sizeof(SERVERBROWSE_OLD_GETINFO) &&
+					mem_comp(Packet.m_pData, SERVERBROWSE_OLD_GETINFO, sizeof(SERVERBROWSE_OLD_GETINFO)) == 0)
+				{
+					SendServerInfo(&Packet.m_Address, -1);
+				}
+			}
+		}
+		else
+			ProcessClientPacket(&Packet);
+	}
+}
+
+int CServer::LoadMap(const char *pMapName)
+{
+	//DATAFILE *df;
+	char aBuf[512];
+	str_format(aBuf, sizeof(aBuf), "maps/%s.map", pMapName);
+	
+	/*df = datafile_load(buf);
+	if(!df)
+		return 0;*/
+		
+	if(!m_pMap->Load(aBuf))
+		return 0;
+	
+	// stop recording when we change map
+	m_DemoRecorder.Stop();
+	
+	// reinit snapshot ids
+	m_IDPool.TimeoutIDs();
+	
+	// get the crc of the map
+	m_CurrentMapCrc = m_pMap->Crc();
+	dbg_msg("server", "%s crc is %08x", aBuf, m_CurrentMapCrc);
+		
+	str_copy(m_aCurrentMap, pMapName, sizeof(m_aCurrentMap));
+	//map_set(df);
+	
+	// load compelate map into memory for download
+	{
+		IOHANDLE File = Storage()->OpenFile(aBuf, IOFLAG_READ);
+		m_CurrentMapSize = (int)io_length(File);
+		if(m_pCurrentMapData)
+			mem_free(m_pCurrentMapData);
+		m_pCurrentMapData = (unsigned char *)mem_alloc(m_CurrentMapSize, 1);
+		io_read(File, m_pCurrentMapData, m_CurrentMapSize);
+		io_close(File);
+	}
+	return 1;
+}
+
+void CServer::InitEngine(const char *pAppname)
+{
+	m_Engine.Init(pAppname);
+}
+
+void CServer::InitRegister(CNetServer *pNetServer, IEngineMasterServer *pMasterServer)
+{
+	m_Register.Init(pNetServer, pMasterServer);
+}
+
+int CServer::Run()
+{
+	m_pGameServer = Kernel()->RequestInterface<IGameServer>();
+	m_pMap = Kernel()->RequestInterface<IEngineMap>();
+	m_pStorage = Kernel()->RequestInterface<IStorage>();
+
+	//snap_init_id();
+	net_init();
+	
+	//
+	Console()->RegisterPrintCallback(SendRconLineAuthed, this);
+
+	// load map
+	if(!LoadMap(g_Config.m_SvMap))
+	{
+		dbg_msg("server", "failed to load map. mapname='%s'", g_Config.m_SvMap);
+		return -1;
+	}
+	
+	// start server
+	// TODO: IPv6 support
+	NETADDR BindAddr;
+	if(g_Config.m_SvBindaddr[0] && net_host_lookup(g_Config.m_SvBindaddr, &BindAddr, NETTYPE_IPV4) == 0)
+	{
+		// sweet!
+		BindAddr.port = g_Config.m_SvPort;
+	}
+	else
+	{
+		mem_zero(&BindAddr, sizeof(BindAddr));
+		BindAddr.port = g_Config.m_SvPort;
+	}
+	
+	
+	if(!m_NetServer.Open(BindAddr, g_Config.m_SvMaxClients, 0))
+	{
+		dbg_msg("server", "couldn't open socket. port might already be in use");
+		return -1;
+	}
+
+	m_NetServer.SetCallbacks(NewClientCallback, DelClientCallback, this);
+	
+	dbg_msg("server", "server name is '%s'", g_Config.m_SvName);
+	
+	GameServer()->OnInit();
+	dbg_msg("server", "version %s", GameServer()->NetVersion());
+
+	// start game
+	{
+		int64 ReportTime = time_get();
+		int ReportInterval = 3;
+	
+		m_Lastheartbeat = 0;
+		m_GameStartTime = time_get();
+	
+		if(g_Config.m_Debug)
+			dbg_msg("server", "baseline memory usage %dk", mem_stats()->allocated/1024);
+
+		while(m_RunServer)
+		{
+			int64 t = time_get();
+			int NewTicks = 0;
+			
+			// load new map TODO: don't poll this
+			if(str_comp(g_Config.m_SvMap, m_aCurrentMap) != 0 || g_Config.m_SvMapReload)
+			{
+				g_Config.m_SvMapReload = 0;
+				
+				// load map
+				if(LoadMap(g_Config.m_SvMap))
+				{
+					// new map loaded
+					GameServer()->OnShutdown();
+					
+					for(int c = 0; c < MAX_CLIENTS; c++)
+					{
+						if(m_aClients[c].m_State == CClient::STATE_EMPTY)
+							continue;
+						
+						SendMap(c);
+						m_aClients[c].Reset();
+						m_aClients[c].m_State = CClient::STATE_CONNECTING;
+					}
+					
+					m_GameStartTime = time_get();
+					m_CurrentGameTick = 0;
+					Kernel()->ReregisterInterface(GameServer());
+					GameServer()->OnInit();
+				}
+				else
+				{
+					dbg_msg("server", "failed to load map. mapname='%s'", g_Config.m_SvMap);
+					str_copy(g_Config.m_SvMap, m_aCurrentMap, sizeof(g_Config.m_SvMap));
+				}
+			}
+			
+			while(t > TickStartTime(m_CurrentGameTick+1))
+			{
+				m_CurrentGameTick++;
+				NewTicks++;
+				
+				// apply new input
+				for(int c = 0; c < MAX_CLIENTS; c++)
+				{
+					if(m_aClients[c].m_State == CClient::STATE_EMPTY)
+						continue;
+					for(int i = 0; i < 200; i++)
+					{
+						if(m_aClients[c].m_aInputs[i].m_GameTick == Tick())
+						{
+							if(m_aClients[c].m_State == CClient::STATE_INGAME)
+								GameServer()->OnClientPredictedInput(c, m_aClients[c].m_aInputs[i].m_aData);
+							break;
+						}
+					}
+				}
+
+				GameServer()->OnTick();
+			}
+			
+			// snap game
+			if(NewTicks)
+			{
+				if(g_Config.m_SvHighBandwidth || (m_CurrentGameTick%2) == 0)
+					DoSnapshot();
+			}
+			
+			// master server stuff
+			m_Register.RegisterUpdate();
+	
+			PumpNetwork();
+	
+			if(ReportTime < time_get())
+			{
+				if(g_Config.m_Debug)
+				{
+					/*
+					static NETSTATS prev_stats;
+					NETSTATS stats;
+					netserver_stats(net, &stats);
+					
+					perf_next();
+					
+					if(config.dbg_pref)
+						perf_dump(&rootscope);
+
+					dbg_msg("server", "send=%8d recv=%8d",
+						(stats.send_bytes - prev_stats.send_bytes)/reportinterval,
+						(stats.recv_bytes - prev_stats.recv_bytes)/reportinterval);
+						
+					prev_stats = stats;
+					*/
+				}
+	
+				ReportTime += time_freq()*ReportInterval;
+			}
+			
+			// wait for incomming data
+			net_socket_read_wait(m_NetServer.Socket(), 5);
+		}
+	}
+	// disconnect all clients on shutdown
+	for(int i = 0; i < MAX_CLIENTS; ++i)
+	{
+		if(m_aClients[i].m_State != CClient::STATE_EMPTY)
+			m_NetServer.Drop(i, "server shutdown");
+	}
+
+	GameServer()->OnShutdown();
+	m_pMap->Unload();
+
+	if(m_pCurrentMapData)
+		mem_free(m_pCurrentMapData);
+	return 0;
+}
+
+void CServer::ConKick(IConsole::IResult *pResult, void *pUser)
+{
+	((CServer *)pUser)->Kick(pResult->GetInteger(0), "kicked by console");
+}
+
+void CServer::ConBan(IConsole::IResult *pResult, void *pUser)
+{
+	NETADDR Addr;
+	char aAddrStr[128];
+	const char *pStr = pResult->GetString(0);
+	int Minutes = 30;
+	
+	if(pResult->NumArguments() > 1)
+		Minutes = pResult->GetInteger(1);
+	
+	if(net_addr_from_str(&Addr, pStr) == 0)
+		((CServer *)pUser)->BanAdd(Addr, Minutes*60);
+	else if(StrAllnum(pStr))
+	{
+		int ClientId = str_toint(pStr);
+
+		if(ClientId < 0 || ClientId >= MAX_CLIENTS || ((CServer *)pUser)->m_aClients[ClientId].m_State == CClient::STATE_EMPTY)
+		{
+			dbg_msg("server", "invalid client id");
+			return;
+		}
+
+		NETADDR Addr = ((CServer *)pUser)->m_NetServer.ClientAddr(ClientId);
+		((CServer *)pUser)->BanAdd(Addr, Minutes*60);
+	}
+	
+	Addr.port = 0;
+	net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr));
+	
+	if(Minutes)
+		dbg_msg("server", "banned %s for %d minutes", aAddrStr, Minutes);
+	else
+		dbg_msg("server", "banned %s for life", aAddrStr);
+}
+
+void CServer::ConUnban(IConsole::IResult *pResult, void *pUser)
+{
+	NETADDR Addr;
+	const char *pStr = pResult->GetString(0);
+	
+	if(net_addr_from_str(&Addr, pStr) == 0)
+		((CServer *)pUser)->BanRemove(Addr);
+	else
+		dbg_msg("server", "invalid network address");
+}
+
+void CServer::ConBans(IConsole::IResult *pResult, void *pUser)
+{
+	unsigned Now = time_timestamp();
+	char aBuf[1024];
+	CServer* pServer = (CServer *)pUser;
+	
+	int Num = pServer->m_NetServer.BanNum();
+	for(int i = 0; i < Num; i++)
+	{
+		CNetServer::CBanInfo Info;
+		pServer->m_NetServer.BanGet(i, &Info);
+		NETADDR Addr = Info.m_Addr;
+		
+		if(Info.m_Expires == -1)
+		{
+			str_format(aBuf, sizeof(aBuf), "#%d %d.%d.%d.%d for life", i, Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3]);
+		}
+		else
+		{
+			unsigned t = Info.m_Expires - Now;
+			str_format(aBuf, sizeof(aBuf), "#%d %d.%d.%d.%d for %d minutes and %d seconds", i, Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3], t/60, t%60);
+		}
+		pServer->Console()->Print(aBuf);
+		dbg_msg("server", "%s", aBuf);
+	}
+	str_format(aBuf, sizeof(aBuf), "%d ban(s)", Num);
+	pServer->Console()->Print(aBuf);
+	dbg_msg("server", "%s", aBuf);
+}
+
+void CServer::ConStatus(IConsole::IResult *pResult, void *pUser)
+{
+	int i;
+	NETADDR Addr;
+	char aBuf[1024];
+	CServer* pServer = (CServer *)pUser;
+
+	for(i = 0; i < MAX_CLIENTS; i++)
+	{
+		if(pServer->m_aClients[i].m_State == CClient::STATE_INGAME)
+		{
+			Addr = pServer->m_NetServer.ClientAddr(i);
+			str_format(aBuf, sizeof(aBuf), "id=%d addr=%d.%d.%d.%d:%d name='%s' score=%d",
+				i, Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3], Addr.port,
+				pServer->m_aClients[i].m_aName, pServer->m_aClients[i].m_Score);
+			pServer->Console()->Print(aBuf);
+			dbg_msg("server", "%s", aBuf);
+		}
+	}
+}
+
+void CServer::ConShutdown(IConsole::IResult *pResult, void *pUser)
+{
+	((CServer *)pUser)->m_RunServer = 0;
+}
+
+void CServer::ConRecord(IConsole::IResult *pResult, void *pUser)
+{
+	char aFilename[512];
+	str_format(aFilename, sizeof(aFilename), "demos/%s.demo", pResult->GetString(0));
+	((CServer *)pUser)->m_DemoRecorder.Start(((CServer *)pUser)->Storage(), aFilename, ((CServer *)pUser)->GameServer()->NetVersion(), ((CServer *)pUser)->m_aCurrentMap, ((CServer *)pUser)->m_CurrentMapCrc, "server");
+}
+
+void CServer::ConStopRecord(IConsole::IResult *pResult, void *pUser)
+{
+	((CServer *)pUser)->m_DemoRecorder.Stop();
+}
+
+void CServer::ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
+{
+	pfnCallback(pResult, pCallbackUserData);
+	if(pResult->NumArguments())
+		((CServer *)pUserData)->UpdateServerInfo();
+}
+
+void CServer::RegisterCommands()
+{
+	m_pConsole = Kernel()->RequestInterface<IConsole>();
+	
+	Console()->Register("kick", "i", CFGFLAG_SERVER, ConKick, this, "");
+	Console()->Register("ban", "s?i", CFGFLAG_SERVER, ConBan, this, "");
+	Console()->Register("unban", "s", CFGFLAG_SERVER, ConUnban, this, "");
+	Console()->Register("bans", "", CFGFLAG_SERVER, ConBans, this, "");
+	Console()->Register("status", "", CFGFLAG_SERVER, ConStatus, this, "");
+	Console()->Register("shutdown", "", CFGFLAG_SERVER, ConShutdown, this, "");
+
+	Console()->Register("record", "s", CFGFLAG_SERVER, ConRecord, this, "");
+	Console()->Register("stoprecord", "", CFGFLAG_SERVER, ConStopRecord, this, "");
+
+	Console()->Chain("sv_name", ConchainSpecialInfoupdate, this);
+	Console()->Chain("password", ConchainSpecialInfoupdate, this);
+}	
+
+
+int CServer::SnapNewID()
+{
+	return m_IDPool.NewID();
+}
+
+void CServer::SnapFreeID(int ID)
+{
+	m_IDPool.FreeID(ID);
+}
+
+
+void *CServer::SnapNewItem(int Type, int Id, int Size)
+{
+	dbg_assert(Type >= 0 && Type <=0xffff, "incorrect type");
+	dbg_assert(Id >= 0 && Id <=0xffff, "incorrect id");
+	return m_SnapshotBuilder.NewItem(Type, Id, Size);		
+}
+
+void CServer::SnapSetStaticsize(int ItemType, int Size)
+{
+	m_SnapshotDelta.SetStaticsize(ItemType, Size);
+}
+
+static CServer *CreateServer() { return new CServer(); }
+
+int main(int argc, const char **argv) // ignore_convention
+{
+#if defined(CONF_FAMILY_WINDOWS)
+	for(int i = 1; i < argc; i++) // ignore_convention
+	{
+		if(str_comp("-s", argv[i]) == 0 || str_comp("--silent", argv[i]) == 0) // ignore_convention
+		{
+			ShowWindow(GetConsoleWindow(), SW_HIDE);
+			break;
+		}
+	}
+#endif
+
+	// init the engine
+	dbg_msg("server", "starting...");
+	CServer *pServer = CreateServer();
+	pServer->InitEngine("Teeworlds");
+	
+	IKernel *pKernel = IKernel::Create();
+
+	// create the components
+	IEngineMap *pEngineMap = CreateEngineMap();
+	IGameServer *pGameServer = CreateGameServer();
+	IConsole *pConsole = CreateConsole();
+	IEngineMasterServer *pEngineMasterServer = CreateEngineMasterServer();
+	IStorage *pStorage = CreateStorage("Teeworlds", argv[0]); // ignore_convention
+	IConfig *pConfig = CreateConfig();
+	
+	pServer->InitRegister(&pServer->m_NetServer, pEngineMasterServer);
+
+	{
+		bool RegisterFail = false;
+
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(pServer); // register as both
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IEngineMap*>(pEngineMap)); // register as both
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IMap*>(pEngineMap));
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(pGameServer);
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(pConsole);
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(pStorage);
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(pConfig);
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IEngineMasterServer*>(pEngineMasterServer)); // register as both
+		RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IMasterServer*>(pEngineMasterServer));
+		
+		if(RegisterFail)
+			return -1;
+	}
+	
+	pConfig->Init();
+	pEngineMasterServer->Init(pServer->Engine());
+	pEngineMasterServer->Load();
+		
+	// register all console commands
+	pServer->RegisterCommands();
+	pGameServer->OnConsoleInit();
+	
+	// execute autoexec file
+	pConsole->ExecuteFile("autoexec.cfg");
+
+	// parse the command line arguments
+	if(argc > 1) // ignore_convention
+		pConsole->ParseArguments(argc-1, &argv[1]); // ignore_convention
+	
+	// run the server
+	pServer->Run();
+	
+	// free
+	delete pServer;
+	delete pKernel;
+	delete pEngineMap;
+	delete pGameServer;
+	delete pConsole;
+	delete pEngineMasterServer;
+	delete pStorage;
+	delete pConfig;
+	return 0;
+}
+
diff --git a/src/engine/server/server.h b/src/engine/server/server.h
new file mode 100644
index 00000000..6904085a
--- /dev/null
+++ b/src/engine/server/server.h
@@ -0,0 +1,195 @@
+#ifndef ENGINE_SERVER_SERVER_H
+#define ENGINE_SERVER_SERVER_H
+
+#include <engine/server.h>
+
+class CSnapIDPool
+{
+	enum
+	{
+		MAX_IDS = 16*1024,
+	};
+
+	class CID
+	{
+	public:
+		short m_Next;
+		short m_State; // 0 = free, 1 = alloced, 2 = timed
+		int m_Timeout;
+	};
+
+	CID m_aIDs[MAX_IDS];
+		
+	int m_FirstFree;
+	int m_FirstTimed;
+	int m_LastTimed;
+	int m_Usage;
+	int m_InUsage;
+
+public:	
+
+	CSnapIDPool();
+	
+	void Reset();
+	void RemoveFirstTimeout();
+	int NewID();
+	void TimeoutIDs();
+	void FreeID(int Id);
+};
+
+class CServer : public IServer
+{
+	class IGameServer *m_pGameServer;
+	class IConsole *m_pConsole;
+	class IStorage *m_pStorage;
+public:
+	class IGameServer *GameServer() { return m_pGameServer; }
+	class IConsole *Console() { return m_pConsole; }
+	class IStorage *Storage() { return m_pStorage; }
+	class CEngine *Engine() { return &m_Engine; }
+
+	class CClient
+	{
+	public:
+	
+		enum
+		{
+			STATE_EMPTY = 0,
+			STATE_AUTH,
+			STATE_CONNECTING,
+			STATE_READY,
+			STATE_INGAME,
+			
+			SNAPRATE_INIT=0,
+			SNAPRATE_FULL,
+			SNAPRATE_RECOVER
+		};
+	
+		class CInput
+		{
+		public:
+			int m_aData[MAX_INPUT_SIZE];
+			int m_GameTick; // the tick that was chosen for the input
+		};
+	
+		// connection state info
+		int m_State;
+		int m_Latency;
+		int m_SnapRate;
+		
+		int m_LastAckedSnapshot;
+		int m_LastInputTick;
+		CSnapshotStorage m_Snapshots;
+		
+		CInput m_LatestInput;
+		CInput m_aInputs[200]; // TODO: handle input better
+		int m_CurrentInput;
+		
+		char m_aName[MAX_NAME_LENGTH];
+		char m_aClan[MAX_CLANNAME_LENGTH];
+		int m_Score;
+		int m_Authed;
+		
+		void Reset();
+	};
+	
+	CClient m_aClients[MAX_CLIENTS];
+
+	CSnapshotDelta m_SnapshotDelta;
+	CSnapshotBuilder m_SnapshotBuilder;
+	CSnapIDPool m_IDPool;
+	CNetServer m_NetServer;
+	
+	IEngineMap *m_pMap;
+
+	int64 m_GameStartTime;
+	//int m_CurrentGameTick;
+	int m_RunServer;
+
+	char m_aBrowseinfoGametype[16];
+	int m_BrowseinfoProgression;
+
+	int64 m_Lastheartbeat;
+	//static NETADDR4 master_server;
+
+	char m_aCurrentMap[64];
+	int m_CurrentMapCrc;
+	unsigned char *m_pCurrentMapData;
+	int m_CurrentMapSize;	
+	
+	CDemoRecorder m_DemoRecorder;
+	CEngine m_Engine;
+	CRegister m_Register;
+	
+	CServer();
+	
+	int TrySetClientName(int ClientID, const char *pName);
+
+	virtual void SetClientName(int ClientID, const char *pName);
+	virtual void SetClientScore(int ClientID, int Score);
+	virtual void SetBrowseInfo(const char *pGameType, int Progression);
+
+	void Kick(int ClientID, const char *pReason);
+
+	//int Tick()
+	int64 TickStartTime(int Tick);
+	//int TickSpeed()
+
+	int Init();
+
+	int GetClientInfo(int ClientID, CClientInfo *pInfo);
+	void GetClientIP(int ClientID, char *pIPString, int Size);
+	const char *ClientName(int ClientId);
+	bool ClientIngame(int ClientID);
+
+	int *LatestInput(int ClientId, int *size);
+
+	virtual int SendMsg(CMsgPacker *pMsg, int Flags, int ClientId);
+	int SendMsgEx(CMsgPacker *pMsg, int Flags, int ClientID, bool System);
+
+	void DoSnapshot();
+
+	static int NewClientCallback(int ClientId, void *pUser);
+	static int DelClientCallback(int ClientId, void *pUser);
+
+	void SendMap(int ClientId);
+	void SendRconLine(int ClientId, const char *pLine);
+	static void SendRconLineAuthed(const char *pLine, void *pUser);
+	
+	void ProcessClientPacket(CNetChunk *pPacket);
+		
+	void SendServerInfo(NETADDR *pAddr, int Token);
+	void UpdateServerInfo();
+
+	int BanAdd(NETADDR Addr, int Seconds);
+	int BanRemove(NETADDR Addr);
+		
+
+	void PumpNetwork();
+
+	int LoadMap(const char *pMapName);
+
+	void InitEngine(const char *pAppname);
+	void InitRegister(CNetServer *pNetServer, IEngineMasterServer *pMasterServer);
+	int Run();
+
+	static void ConKick(IConsole::IResult *pResult, void *pUser);
+	static void ConBan(IConsole::IResult *pResult, void *pUser);
+	static void ConUnban(IConsole::IResult *pResult, void *pUser);
+	static void ConBans(IConsole::IResult *pResult, void *pUser);
+ 	static void ConStatus(IConsole::IResult *pResult, void *pUser);
+	static void ConShutdown(IConsole::IResult *pResult, void *pUser);
+	static void ConRecord(IConsole::IResult *pResult, void *pUser);
+	static void ConStopRecord(IConsole::IResult *pResult, void *pUser);
+	static void ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
+
+	void RegisterCommands();
+	
+	
+	virtual int SnapNewID();
+	virtual void SnapFreeID(int ID);
+	virtual void *SnapNewItem(int Type, int Id, int Size);
+	void SnapSetStaticsize(int ItemType, int Size);
+};
+
+#endif
diff --git a/src/engine/serverbrowser.h b/src/engine/serverbrowser.h
new file mode 100644
index 00000000..43732f13
--- /dev/null
+++ b/src/engine/serverbrowser.h
@@ -0,0 +1,93 @@
+#ifndef ENGINE_SERVERBROWSER_H
+#define ENGINE_SERVERBROWSER_H
+
+#include "kernel.h"
+
+/*
+	Structure: CServerInfo
+*/
+class CServerInfo
+{
+public:
+	/*
+		Structure: CInfoPlayer
+	*/
+	class CPlayer
+	{
+	public:
+		char m_aName[48];
+		int m_Score;
+	} ;
+
+	int m_SortedIndex;
+	int m_ServerIndex;
+	
+	NETADDR m_NetAddr;
+	
+	int m_QuickSearchHit;
+	
+	int m_Progression;
+	int m_MaxPlayers;
+	int m_NumPlayers;
+	int m_Flags;
+	int m_Favorite;
+	int m_Latency; // in ms
+	char m_aGameType[16];
+	char m_aName[64];
+	char m_aMap[32];
+	char m_aVersion[32];
+	char m_aAddress[24];
+	CPlayer m_aPlayers[16];
+};
+
+class IServerBrowser : public IInterface
+{
+	MACRO_INTERFACE("serverbrowser", 0)
+public:
+
+	/* Constants: Server Browser Sorting
+		SORT_NAME - Sort by name.
+		SORT_PING - Sort by ping.
+		SORT_MAP - Sort by map
+		SORT_GAMETYPE - Sort by game type. DM, TDM etc.
+		SORT_PROGRESSION - Sort by progression.
+		SORT_NUMPLAYERS - Sort after how many players there are on the server.
+	*/
+	enum{
+		SORT_NAME = 0,
+		SORT_PING,
+		SORT_MAP,
+		SORT_GAMETYPE,
+		SORT_PROGRESSION,
+		SORT_NUMPLAYERS,
+		
+		QUICK_SERVERNAME=1,
+		QUICK_PLAYERNAME=2,
+		QUICK_MAPNAME=4,
+		
+		TYPE_INTERNET = 0,
+		TYPE_LAN = 1,
+		TYPE_FAVORITES = 2,
+
+		// TODO: clean this up
+		SET_MASTER_ADD=1,
+		SET_FAV_ADD,
+		SET_TOKEN,
+		SET_OLD_INTERNET,
+		SET_OLD_LAN
+	};
+
+	virtual void Refresh(int Type) = 0;
+	virtual bool IsRefreshingMasters() const = 0;
+	
+	virtual int NumServers() const = 0;
+	
+	virtual int NumSortedServers() const = 0;
+	virtual const CServerInfo *SortedGet(int Index) const = 0;
+	
+	virtual bool IsFavorite(const NETADDR &Addr) const = 0;
+	virtual void AddFavorite(const NETADDR &Addr) = 0;
+	virtual void RemoveFavorite(const NETADDR &Addr) = 0;
+};
+
+#endif
diff --git a/src/engine/shared/compression.cpp b/src/engine/shared/compression.cpp
new file mode 100644
index 00000000..63e44699
--- /dev/null
+++ b/src/engine/shared/compression.cpp
@@ -0,0 +1,88 @@
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+#include <base/system.h>
+
+#include "compression.h"
+
+// Format: ESDDDDDD EDDDDDDD EDD...  Extended, Data, Sign
+unsigned char *CVariableInt::Pack(unsigned char *pDst, int i) 
+{ 
+	*pDst = (i>>25)&0x40; // set sign bit if i<0
+	i = i^(i>>31); // if(i<0) i = ~i
+
+	*pDst |= i&0x3F; // pack 6bit into dst
+	i >>= 6; // discard 6 bits
+	if(i)
+	{
+		*pDst |= 0x80; // set extend bit
+		while(1)
+		{
+			pDst++;
+			*pDst = i&(0x7F); // pack 7bit
+			i >>= 7; // discard 7 bits
+			*pDst |= (i!=0)<<7; // set extend bit (may branch)
+			if(!i)
+				break;
+		}
+	}
+
+	pDst++;
+	return pDst; 
+} 
+ 
+const unsigned char *CVariableInt::Unpack(const unsigned char *pSrc, int *pInOut)
+{ 
+	int Sign = (*pSrc>>6)&1; 
+	*pInOut = *pSrc&0x3F; 
+
+	do
+	{ 
+		if(!(*pSrc&0x80)) break;
+		pSrc++;
+		*pInOut |= (*pSrc&(0x7F))<<(6);
+
+		if(!(*pSrc&0x80)) break;
+		pSrc++;
+		*pInOut |= (*pSrc&(0x7F))<<(6+7);
+
+		if(!(*pSrc&0x80)) break;
+		pSrc++;
+		*pInOut |= (*pSrc&(0x7F))<<(6+7+7);
+
+		if(!(*pSrc&0x80)) break;
+		pSrc++;
+		*pInOut |= (*pSrc&(0x7F))<<(6+7+7+7);
+	} while(0);
+
+	pSrc++;
+	*pInOut ^= -Sign; // if(sign) *i = ~(*i)
+	return pSrc; 
+} 
+
+
+long CVariableInt::Decompress(const void *pSrc_, int Size, void *pDst_)
+{
+	const unsigned char *pSrc = (unsigned char *)pSrc_;
+	const unsigned char *pEnd = pSrc + Size;
+	int *pDst = (int *)pDst_;
+	while(pSrc < pEnd)
+	{
+		pSrc = CVariableInt::Unpack(pSrc, pDst);
+		pDst++;
+	}
+	return (long)((unsigned char *)pDst-(unsigned char *)pDst_);
+}
+
+long CVariableInt::Compress(const void *pSrc_, int Size, void *pDst_)
+{
+	int *pSrc = (int *)pSrc_;
+	unsigned char *pDst = (unsigned char *)pDst_;
+	Size /= 4;
+	while(Size)
+	{
+		pDst = CVariableInt::Pack(pDst, *pSrc);
+		Size--;
+		pSrc++;
+	}
+	return (long)(pDst-(unsigned char *)pDst_);
+}
+
diff --git a/src/engine/shared/compression.h b/src/engine/shared/compression.h
new file mode 100644
index 00000000..9bd9e61a
--- /dev/null
+++ b/src/engine/shared/compression.h
@@ -0,0 +1,12 @@
+#ifndef ENGINE_SHARED_COMPRESSION_H
+#define ENGINE_SHARED_COMPRESSION_H
+// variable int packing
+class CVariableInt
+{
+public:
+	static unsigned char *Pack(unsigned char *pDst, int i);
+	static const unsigned char *Unpack(const unsigned char *pSrc, int *pInOut);
+	static long Compress(const void *pSrc, int Size, void *pDst);
+	static long Decompress(const void *pSrc, int Size, void *pDst);
+};
+#endif
diff --git a/src/engine/shared/config.cpp b/src/engine/shared/config.cpp
new file mode 100644
index 00000000..ca12e8b7
--- /dev/null
+++ b/src/engine/shared/config.cpp
@@ -0,0 +1,111 @@
+#include <engine/config.h>
+#include <engine/storage.h>
+#include <engine/shared/config.h>
+
+CConfiguration g_Config;
+
+class CConfig : public IConfig
+{
+	IStorage *m_pStorage;
+	IOHANDLE m_ConfigFile;
+	
+	struct CCallback
+	{
+		SAVECALLBACKFUNC m_pfnFunc;
+		void *m_pUserData;
+	};
+	
+	enum
+	{
+		MAX_CALLBACKS = 16
+	};
+	
+	CCallback m_aCallbacks[MAX_CALLBACKS];
+	int m_NumCallbacks;
+	
+	void EscapeParam(char *pDst, const char *pSrc, int size)
+	{
+		for(int i = 0; *pSrc && i < size - 1; ++i)
+		{
+			if(*pSrc == '"' || *pSrc == '\\') // escape \ and "
+				*pDst++ = '\\';
+			*pDst++ = *pSrc++;
+		}
+		*pDst = 0;
+	}
+
+public:
+
+	CConfig()
+	{
+		m_ConfigFile = 0;
+		m_NumCallbacks = 0;
+	}
+	
+	virtual void Init()
+	{
+		m_pStorage = Kernel()->RequestInterface<IStorage>();
+		Reset();
+	}
+	
+	virtual void Reset()
+	{
+		#define MACRO_CONFIG_INT(Name,ScriptName,def,min,max,flags,desc) g_Config.m_##Name = def;
+		#define MACRO_CONFIG_STR(Name,ScriptName,len,def,flags,desc) str_copy(g_Config.m_##Name, def, len);
+
+		#include "config_variables.h" 
+
+		#undef MACRO_CONFIG_INT 
+		#undef MACRO_CONFIG_STR 		
+	}
+	
+	virtual void Save()
+	{
+		if(!m_pStorage)
+			return;
+		m_ConfigFile = m_pStorage->OpenFile("settings.cfg", IOFLAG_WRITE);
+		
+		if(!m_ConfigFile)
+			return;
+		
+		char aLineBuf[1024*2];
+		char aEscapeBuf[1024*2];
+
+		#define MACRO_CONFIG_INT(Name,ScriptName,def,min,max,flags,desc) if((flags)&CFGFLAG_SAVE){ str_format(aLineBuf, sizeof(aLineBuf), "%s %i", #ScriptName, g_Config.m_##Name); WriteLine(aLineBuf); }
+		#define MACRO_CONFIG_STR(Name,ScriptName,len,def,flags,desc) if((flags)&CFGFLAG_SAVE){ EscapeParam(aEscapeBuf, g_Config.m_##Name, sizeof(aEscapeBuf)); str_format(aLineBuf, sizeof(aLineBuf), "%s \"%s\"", #ScriptName, aEscapeBuf); WriteLine(aLineBuf); }
+
+		#include "config_variables.h" 
+
+		#undef MACRO_CONFIG_INT 
+		#undef MACRO_CONFIG_STR 				
+		
+		for(int i = 0; i < m_NumCallbacks; i++)
+			m_aCallbacks[i].m_pfnFunc(this, m_aCallbacks[i].m_pUserData);
+		
+		io_close(m_ConfigFile);
+		m_ConfigFile = 0;
+	}
+	
+	virtual void RegisterCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData)
+	{
+		dbg_assert(m_NumCallbacks < MAX_CALLBACKS, "too many config callbacks");
+		m_aCallbacks[m_NumCallbacks].m_pfnFunc = pfnFunc;
+		m_aCallbacks[m_NumCallbacks].m_pUserData = pUserData;
+		m_NumCallbacks++;
+	}
+	
+	virtual void WriteLine(const char *pLine)
+	{
+		if(!m_ConfigFile)
+			return;
+#if defined(CONF_FAMILY_WINDOWS)
+		static const char Newline[] = "\r\n";
+#else
+		static const char Newline[] = "\n";
+#endif
+		io_write(m_ConfigFile, pLine, str_length(pLine));
+		io_write(m_ConfigFile, Newline, sizeof(Newline)-1);			
+	}
+};
+
+IConfig *CreateConfig() { return new CConfig; }
diff --git a/src/engine/shared/config.h b/src/engine/shared/config.h
new file mode 100644
index 00000000..10a54004
--- /dev/null
+++ b/src/engine/shared/config.h
@@ -0,0 +1,22 @@
+#ifndef ENGINE_SHARED_E_CONFIG_H
+#define ENGINE_SHARED_E_CONFIG_H
+
+struct CConfiguration
+{ 
+    #define MACRO_CONFIG_INT(Name,ScriptName,Def,Min,Max,Save,Desc) int m_##Name;
+    #define MACRO_CONFIG_STR(Name,ScriptName,Len,Def,Save,Desc) char m_##Name[Len]; // Flawfinder: ignore
+    #include "config_variables.h" 
+    #undef MACRO_CONFIG_INT 
+    #undef MACRO_CONFIG_STR 
+};
+
+extern CConfiguration g_Config;
+
+enum
+{
+	CFGFLAG_SAVE=1,
+	CFGFLAG_CLIENT=2,
+	CFGFLAG_SERVER=4
+};
+
+#endif
diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h
new file mode 100644
index 00000000..e5541911
--- /dev/null
+++ b/src/engine/shared/config_variables.h
@@ -0,0 +1,80 @@
+#ifndef ENGINE_SHARED_E_CONFIG_VARIABLES_H
+#define ENGINE_SHARED_E_CONFIG_VARIABLES_H
+#undef ENGINE_SHARED_E_CONFIG_VARIABLES_H // this file will be included several times
+
+// TODO: remove this
+#include "././game/variables.h"
+
+
+MACRO_CONFIG_STR(PlayerName, player_name, 24, "nameless tee", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Name of the player")
+MACRO_CONFIG_STR(ClanName, clan_name, 32, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "(not used)")
+MACRO_CONFIG_STR(Password, password, 32, "", CFGFLAG_CLIENT|CFGFLAG_SERVER, "Password to the server")
+MACRO_CONFIG_STR(Logfile, logfile, 128, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filename to log all output to")
+
+MACRO_CONFIG_INT(ClCpuThrottle, cl_cpu_throttle, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
+MACRO_CONFIG_INT(ClEditor, cl_editor, 0, 0, 1, CFGFLAG_CLIENT, "")
+
+MACRO_CONFIG_INT(ClEventthread, cl_eventthread, 0, 0, 1, CFGFLAG_CLIENT, "Enables the usage of a thread to pump the events")
+
+MACRO_CONFIG_INT(InpGrab, inp_grab, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Use forceful input grabbing method")
+
+MACRO_CONFIG_STR(BrFilterString, br_filter_string, 25, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Server browser filtering string")
+
+MACRO_CONFIG_INT(BrFilterFull, br_filter_full, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out full server in browser")
+MACRO_CONFIG_INT(BrFilterEmpty, br_filter_empty, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out empty server in browser")
+MACRO_CONFIG_INT(BrFilterPw, br_filter_pw, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out password protected servers in browser")
+MACRO_CONFIG_INT(BrFilterPing, br_filter_ping, 999, 0, 999, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Ping to filter by in the server browser")
+MACRO_CONFIG_STR(BrFilterGametype, br_filter_gametype, 128, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Game types to filter")
+MACRO_CONFIG_INT(BrFilterPure, br_filter_pure, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out non-standard servers in browser")
+MACRO_CONFIG_INT(BrFilterPureMap, br_filter_pure_map, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out non-standard maps in browser")
+MACRO_CONFIG_INT(BrFilterCompatversion, br_filter_compatversion, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out non-compatible servers in browser")
+
+MACRO_CONFIG_INT(BrSort, br_sort, 0, 0, 256, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
+MACRO_CONFIG_INT(BrSortOrder, br_sort_order, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
+MACRO_CONFIG_INT(BrMaxRequests, br_max_requests, 10, 0, 1000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Number of requests to use when refreshing server browser")
+
+MACRO_CONFIG_INT(SndBufferSize, snd_buffer_size, 512, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sound buffer size")
+MACRO_CONFIG_INT(SndRate, snd_rate, 48000, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sound mixing rate")
+MACRO_CONFIG_INT(SndEnable, snd_enable, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sound enable")
+MACRO_CONFIG_INT(SndVolume, snd_volume, 100, 0, 100, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sound volume")
+MACRO_CONFIG_INT(SndDevice, snd_device, -1, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "(deprecated) Sound device to use")
+
+MACRO_CONFIG_INT(SndNonactiveMute, snd_nonactive_mute, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
+
+MACRO_CONFIG_INT(GfxScreenWidth, gfx_screen_width, 800, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen resolution width")
+MACRO_CONFIG_INT(GfxScreenHeight, gfx_screen_height, 600, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen resolution height")
+MACRO_CONFIG_INT(GfxFullscreen, gfx_fullscreen, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Fullscreen")
+MACRO_CONFIG_INT(GfxAlphabits, gfx_alphabits, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Alpha bits for framebuffer  (fullscreen only)")
+MACRO_CONFIG_INT(GfxColorDepth, gfx_color_depth, 24, 16, 24, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Colors bits for framebuffer (fullscreen only)")
+MACRO_CONFIG_INT(GfxClear, gfx_clear, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Clear screen before rendering")
+MACRO_CONFIG_INT(GfxVsync, gfx_vsync, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Vertical sync")
+MACRO_CONFIG_INT(GfxDisplayAllModes, gfx_display_all_modes, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
+MACRO_CONFIG_INT(GfxTextureCompression, gfx_texture_compression, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Use texture compression")
+MACRO_CONFIG_INT(GfxHighDetail, gfx_high_detail, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "High detail")
+MACRO_CONFIG_INT(GfxTextureQuality, gfx_texture_quality, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
+MACRO_CONFIG_INT(GfxFsaaSamples, gfx_fsaa_samples, 0, 0, 16, CFGFLAG_SAVE|CFGFLAG_CLIENT, "FSAA Samples")
+MACRO_CONFIG_INT(GfxRefreshRate, gfx_refresh_rate, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen refresh rate")
+MACRO_CONFIG_INT(GfxFinish, gfx_finish, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
+
+MACRO_CONFIG_INT(InpMousesens, inp_mousesens, 100, 5, 100000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Mouse sensitivity")
+
+MACRO_CONFIG_STR(SvName, sv_name, 128, "unnamed server", CFGFLAG_SERVER, "Server name")
+MACRO_CONFIG_STR(SvBindaddr, sv_bindaddr, 128, "", CFGFLAG_SERVER, "Address to bind the server to")
+MACRO_CONFIG_INT(SvPort, sv_port, 8303, 0, 0, CFGFLAG_SERVER, "Port to use for the server")
+MACRO_CONFIG_INT(SvExternalPort, sv_external_port, 0, 0, 0, CFGFLAG_SERVER, "External port to report to the master servers")
+MACRO_CONFIG_STR(SvMap, sv_map, 128, "dm1", CFGFLAG_SERVER, "Map to use on the server")
+MACRO_CONFIG_INT(SvMaxClients, sv_max_clients, 8, 1, MAX_CLIENTS, CFGFLAG_SERVER, "Maximum number of clients that are allowed on a server")
+MACRO_CONFIG_INT(SvHighBandwidth, 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(SvRegister, sv_register, 1, 0, 1, CFGFLAG_SERVER, "Register server with master server for public listing")
+MACRO_CONFIG_STR(SvRconPassword, sv_rcon_password, 32, "", CFGFLAG_SERVER, "Remote console password")
+MACRO_CONFIG_INT(SvMapReload, sv_map_reload, 0, 0, 1, CFGFLAG_SERVER, "Reload the current map")
+
+MACRO_CONFIG_INT(Debug, debug, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SERVER, "Debug mode")
+MACRO_CONFIG_INT(DbgStress, dbg_stress, 0, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SERVER, "Stress systems")
+MACRO_CONFIG_INT(DbgStressNetwork, dbg_stress_network, 0, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SERVER, "Stress network")
+MACRO_CONFIG_INT(DbgPref, dbg_pref, 0, 0, 1, CFGFLAG_SERVER, "Performance outputs")
+MACRO_CONFIG_INT(DbgGraphs, dbg_graphs, 0, 0, 1, CFGFLAG_CLIENT, "Performance graphs")
+MACRO_CONFIG_INT(DbgHitch, dbg_hitch, 0, 0, 0, CFGFLAG_SERVER, "Hitch warnings")
+MACRO_CONFIG_STR(DbgStressServer, dbg_stress_server, 32, "localhost", CFGFLAG_CLIENT, "Server to stress")
+MACRO_CONFIG_INT(DbgResizable, dbg_resizable, 0, 0, 0, CFGFLAG_CLIENT, "Enables window resizing")
+#endif
diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp
new file mode 100644
index 00000000..c545b7db
--- /dev/null
+++ b/src/engine/shared/console.cpp
@@ -0,0 +1,489 @@
+#include <base/system.h>
+#include <engine/shared/protocol.h>
+#include <engine/storage.h>
+#include "console.h"
+#include "config.h"
+#include "engine.h"
+#include "linereader.h"
+
+const char *CConsole::CResult::GetString(unsigned Index)
+{
+	if (Index < 0 || Index >= m_NumArgs)
+		return "";
+	return m_apArgs[Index];
+}
+
+int CConsole::CResult::GetInteger(unsigned Index)
+{
+	if (Index < 0 || Index >= m_NumArgs)
+		return 0;
+	return str_toint(m_apArgs[Index]);
+}
+
+float CConsole::CResult::GetFloat(unsigned Index)
+{
+	if (Index < 0 || Index >= m_NumArgs)
+		return 0.0f;
+	return str_tofloat(m_apArgs[Index]);
+}
+
+// the maximum number of tokens occurs in a string of length CONSOLE_MAX_STR_LENGTH with tokens size 1 separated by single spaces
+static char *SkipBlanks(char *pStr)
+{
+	while(*pStr && (*pStr == ' ' || *pStr == '\t' || *pStr == '\n'))
+		pStr++;
+	return pStr;
+}
+
+static char *SkipToBlank(char *pStr)
+{
+	while(*pStr && (*pStr != ' ' && *pStr != '\t' && *pStr != '\n'))
+		pStr++;
+	return pStr;
+}
+
+
+int CConsole::ParseStart(CResult *pResult, const char *pString, int Length)
+{
+	char *pStr;
+	int Len = sizeof(pResult->m_aStringStorage);
+	if(Length < Len)
+		Len = Length;
+		
+	str_copy(pResult->m_aStringStorage, pString, Length);
+	pStr = pResult->m_aStringStorage;
+	
+	// get command
+	pStr = SkipBlanks(pStr);
+	pResult->m_pCommand = pStr;
+	pStr = SkipToBlank(pStr);
+	
+	if(*pStr)
+	{
+		pStr[0] = 0;
+		pStr++;
+	}
+	
+	pResult->m_pArgsStart = pStr;
+	return 0;
+}
+
+int CConsole::ParseArgs(CResult *pResult, const char *pFormat)
+{
+	char Command;
+	char *pStr;
+	int Optional = 0;
+	int Error = 0;
+	
+	pStr = pResult->m_pArgsStart;
+
+	while(1)	
+	{
+		// fetch command
+		Command = *pFormat;
+		pFormat++;
+		
+		if(!Command)
+			break;
+		
+		if(Command == '?')
+			Optional = 1;
+		else
+		{
+			pStr = SkipBlanks(pStr);
+		
+			if(!(*pStr)) // error, non optional command needs value
+			{
+				if(!Optional)
+					Error = 1;
+				break;
+			}
+			
+			// add token
+			if(*pStr == '"')
+			{
+				char *pDst;
+				pStr++;
+				pResult->AddArgument(pStr);
+				
+				pDst = pStr; // we might have to process escape data
+				while(1)
+				{
+					if(pStr[0] == '"')
+						break;
+					else if(pStr[0] == '\\')
+					{
+						if(pStr[1] == '\\')
+							pStr++; // skip due to escape
+						else if(pStr[1] == '"')
+							pStr++; // skip due to escape
+					}
+					else if(pStr[0] == 0)
+						return 1; // return error
+						
+					*pDst = *pStr;
+					pDst++;
+					pStr++;
+				}
+				
+				// write null termination
+				*pDst = 0;
+
+				
+				pStr++;
+			}
+			else
+			{
+				pResult->AddArgument(pStr);
+				
+				if(Command == 'r') // rest of the string
+					break;
+				else if(Command == 'i') // validate int
+					pStr = SkipToBlank(pStr);
+				else if(Command == 'f') // validate float
+					pStr = SkipToBlank(pStr);
+				else if(Command == 's') // validate string
+					pStr = SkipToBlank(pStr);
+
+				if(pStr[0] != 0) // check for end of string
+				{
+					pStr[0] = 0;
+					pStr++;
+				}
+			}
+		}
+	}
+
+	return Error;
+}
+
+void CConsole::RegisterPrintCallback(FPrintCallback pfnPrintCallback, void *pUserData)
+{
+	m_pfnPrintCallback = pfnPrintCallback;
+	m_pPrintCallbackUserdata = pUserData;
+}
+
+void CConsole::Print(const char *pStr)
+{
+	dbg_msg("console" ,"%s", pStr);
+	if (m_pfnPrintCallback)
+		m_pfnPrintCallback(pStr, m_pPrintCallbackUserdata);
+}
+
+void CConsole::ExecuteLineStroked(int Stroke, const char *pStr)
+{
+	CResult Result;
+	
+	char aStrokeStr[2] = {'0', 0};
+	if(Stroke)
+		aStrokeStr[0] = '1';
+
+	while(pStr && *pStr)
+	{
+		const char *pEnd = pStr;
+		const char *pNextPart = 0;
+		int InString = 0;
+		
+		while(*pEnd)
+		{
+			if(*pEnd == '"')
+				InString ^= 1;
+			else if(*pEnd == '\\') // escape sequences
+			{
+				if(pEnd[1] == '"')
+					pEnd++;
+			}
+			else if(!InString)
+			{
+				if(*pEnd == ';')  // command separator
+				{
+					pNextPart = pEnd+1;
+					break;
+				}
+				else if(*pEnd == '#')  // comment, no need to do anything more
+					break;
+			}
+			
+			pEnd++;
+		}
+		
+		if(ParseStart(&Result, pStr, (pEnd-pStr) + 1) != 0)
+			return;
+
+		CCommand *pCommand = FindCommand(Result.m_pCommand);
+
+		if(pCommand)
+		{
+			int IsStrokeCommand = 0;
+			if(Result.m_pCommand[0] == '+')
+			{
+				// insert the stroke direction token
+				Result.AddArgument(aStrokeStr);
+				IsStrokeCommand = 1;
+			}
+			
+			if(Stroke || IsStrokeCommand)
+			{
+				if(ParseArgs(&Result, pCommand->m_pParams))
+				{
+					char aBuf[256];
+					str_format(aBuf, sizeof(aBuf), "Invalid arguments... Usage: %s %s", pCommand->m_pName, pCommand->m_pParams);
+					Print(aBuf);
+				}
+				else
+					pCommand->m_pfnCallback(&Result, pCommand->m_pUserData);
+			}
+		}
+		else
+		{
+			char aBuf[256];
+			str_format(aBuf, sizeof(aBuf), "No such command: %s.", Result.m_pCommand);
+			Print(aBuf);
+		}
+		
+		pStr = pNextPart;
+	}
+}
+
+void CConsole::PossibleCommands(const char *pStr, int FlagMask, FPossibleCallback pfnCallback, void *pUser)
+{
+	CCommand *pCommand;
+	for(pCommand = m_pFirstCommand; pCommand; pCommand = pCommand->m_pNext)
+	{
+		if(pCommand->m_Flags&FlagMask)
+		{
+			if(str_find_nocase(pCommand->m_pName, pStr))
+				pfnCallback(pCommand->m_pName, pUser);
+		}
+	}	
+}
+
+// TODO: this should regard the commands flag
+CConsole::CCommand *CConsole::FindCommand(const char *pName)
+{
+	CCommand *pCommand;
+	for (pCommand = m_pFirstCommand; pCommand; pCommand = pCommand->m_pNext)
+	{
+		if(str_comp_nocase(pCommand->m_pName, pName) == 0)
+			return pCommand;
+	}	
+	
+	return 0x0;
+}
+
+void CConsole::ExecuteLine(const char *pStr)
+{
+	CConsole::ExecuteLineStroked(1, pStr);
+}
+
+
+void CConsole::ExecuteFile(const char *pFilename)
+{
+	// make sure that this isn't being executed already
+	for(CExecFile *pCur = m_pFirstExec; pCur; pCur = pCur->m_pPrev)
+		if(str_comp(pFilename, pCur->m_pFilename) == 0)
+			return;
+
+	if(!m_pStorage)
+		m_pStorage = Kernel()->RequestInterface<IStorage>();
+	if(!m_pStorage)
+		return;
+		
+	// push this one to the stack
+	CExecFile ThisFile;
+	CExecFile *pPrev = m_pFirstExec;
+	ThisFile.m_pFilename = pFilename;
+	ThisFile.m_pPrev = m_pFirstExec;
+	m_pFirstExec = &ThisFile;
+
+	// exec the file
+	IOHANDLE File = m_pStorage->OpenFile(pFilename, IOFLAG_READ);
+	
+	if(File)
+	{
+		char *pLine;
+		CLineReader lr;
+		
+		dbg_msg("console", "executing '%s'", pFilename);
+		lr.Init(File);
+
+		while((pLine = lr.Get()))
+			ExecuteLine(pLine);
+
+		io_close(File);
+	}
+	else
+		dbg_msg("console", "failed to open '%s'", pFilename);
+	
+	m_pFirstExec = pPrev;
+}
+
+void CConsole::Con_Echo(IResult *pResult, void *pUserData)
+{
+	((CConsole*)pUserData)->Print(pResult->GetString(0));
+}
+
+void CConsole::Con_Exec(IResult *pResult, void *pUserData)
+{
+	((CConsole*)pUserData)->ExecuteFile(pResult->GetString(0));
+}
+
+struct CIntVariableData
+{
+	IConsole *m_pConsole;
+	int *m_pVariable;
+	int m_Min;
+	int m_Max;
+};
+
+struct CStrVariableData
+{
+	IConsole *m_pConsole;
+	char *m_pStr;
+	int m_MaxSize;
+};
+
+static void IntVariableCommand(IConsole::IResult *pResult, void *pUserData)
+{
+	CIntVariableData *pData = (CIntVariableData *)pUserData;
+
+	if(pResult->NumArguments())
+	{
+		int Val = pResult->GetInteger(0);
+		
+		// do clamping
+		if(pData->m_Min != pData->m_Max)
+		{
+			if (Val < pData->m_Min)
+				Val = pData->m_Min;
+			if (pData->m_Max != 0 && Val > pData->m_Max)
+				Val = pData->m_Max;
+		}
+
+		*(pData->m_pVariable) = Val;
+	}
+	else
+	{
+		char aBuf[1024];
+		str_format(aBuf, sizeof(aBuf), "Value: %d", *(pData->m_pVariable));
+		pData->m_pConsole->Print(aBuf);
+	}
+}
+
+static void StrVariableCommand(IConsole::IResult *pResult, void *pUserData)
+{
+	CStrVariableData *pData = (CStrVariableData *)pUserData;
+
+	if(pResult->NumArguments())
+		str_copy(pData->m_pStr, pResult->GetString(0), pData->m_MaxSize);
+	else
+	{
+		char aBuf[1024];
+		str_format(aBuf, sizeof(aBuf), "Value: %s", pData->m_pStr);
+		pData->m_pConsole->Print(aBuf);
+	}
+}
+
+CConsole::CConsole()
+{
+	m_pFirstCommand = 0;
+	m_pFirstExec = 0;
+	m_pPrintCallbackUserdata = 0;
+	m_pfnPrintCallback = 0;
+	
+	m_pStorage = 0;
+	
+	// register some basic commands
+	Register("echo", "r", CFGFLAG_SERVER|CFGFLAG_CLIENT, Con_Echo, this, "Echo the text");
+	Register("exec", "r", CFGFLAG_SERVER|CFGFLAG_CLIENT, Con_Exec, this, "Execute the specified file");
+	
+	// TODO: this should disappear
+	#define MACRO_CONFIG_INT(Name,ScriptName,Def,Min,Max,Flags,Desc) \
+	{ \
+		static CIntVariableData Data = { this, &g_Config.m_##Name, Min, Max }; \
+		Register(#ScriptName, "?i", Flags, IntVariableCommand, &Data, Desc); \
+	}
+	
+	#define MACRO_CONFIG_STR(Name,ScriptName,Len,Def,Flags,Desc) \
+	{ \
+		static CStrVariableData Data = { this, g_Config.m_##Name, Len }; \
+		Register(#ScriptName, "?r", Flags, StrVariableCommand, &Data, Desc); \
+	}
+
+	#include "config_variables.h" 
+
+	#undef MACRO_CONFIG_INT 
+	#undef MACRO_CONFIG_STR 	
+}
+
+void CConsole::ParseArguments(int NumArgs, const char **ppArguments)
+{
+	for(int i = 0; i < NumArgs; i++)
+	{
+		// check for scripts to execute
+		if(ppArguments[i][0] == '-' && ppArguments[i][1] == 'f' && ppArguments[i][2] == 0 && NumArgs - i > 1)
+		{
+			ExecuteFile(ppArguments[i+1]);
+			i++;
+		}
+		else
+		{
+			// search arguments for overrides
+			ExecuteLine(ppArguments[i]);
+		}
+	}
+}
+
+void CConsole::Register(const char *pName, const char *pParams, 
+	int Flags, FCommandCallback pfnFunc, void *pUser, const char *pHelp)
+{
+	CCommand *pCommand = (CCommand *)mem_alloc(sizeof(CCommand), sizeof(void*));
+	pCommand->m_pfnCallback = pfnFunc;
+	pCommand->m_pUserData = pUser;
+	pCommand->m_pHelp = pHelp;
+	pCommand->m_pName = pName;
+	pCommand->m_pParams = pParams;
+	pCommand->m_Flags = Flags;
+	
+	
+	pCommand->m_pNext = m_pFirstCommand;
+	m_pFirstCommand = pCommand;
+}
+
+void CConsole::Con_Chain(IResult *pResult, void *pUserData)
+{
+	CChain *pInfo = (CChain *)pUserData;
+	pInfo->m_pfnChainCallback(pResult, pInfo->m_pUserData, pInfo->m_pfnCallback, pInfo->m_pCallbackUserData);
+}
+
+void CConsole::Chain(const char *pName, FChainCommandCallback pfnChainFunc, void *pUser)
+{
+	CCommand *pCommand = FindCommand(pName);
+	
+	if(!pCommand)
+	{
+		dbg_msg("console", "failed to chain '%s'", pName);
+		return;
+	}
+	
+	CChain *pChainInfo = (CChain *)mem_alloc(sizeof(CChain), sizeof(void*));
+
+	// store info
+	pChainInfo->m_pfnChainCallback = pfnChainFunc;
+	pChainInfo->m_pUserData = pUser;
+	pChainInfo->m_pfnCallback = pCommand->m_pfnCallback;
+	pChainInfo->m_pCallbackUserData = pCommand->m_pUserData;
+	
+	// chain
+	pCommand->m_pfnCallback = Con_Chain;
+	pCommand->m_pUserData = pChainInfo;
+}
+
+
+IConsole::CCommandInfo *CConsole::GetCommandInfo(const char *pName)
+{
+	return FindCommand(pName);
+}
+
+
+extern IConsole *CreateConsole() { return new CConsole(); }
diff --git a/src/engine/shared/console.h b/src/engine/shared/console.h
new file mode 100644
index 00000000..93d23547
--- /dev/null
+++ b/src/engine/shared/console.h
@@ -0,0 +1,96 @@
+#ifndef ENGINE_SHARED_CONSOLE_H
+#define ENGINE_SHARED_CONSOLE_H
+
+#include <engine/console.h>
+
+class CConsole : public IConsole
+{
+	class CCommand : public CCommandInfo
+	{
+	public:
+		CCommand *m_pNext;
+		int m_Flags;
+		FCommandCallback m_pfnCallback;
+		void *m_pUserData;
+	};
+		
+
+	class CChain
+	{
+	public:
+		FChainCommandCallback m_pfnChainCallback;
+		FCommandCallback m_pfnCallback;
+		void *m_pCallbackUserData;
+		void *m_pUserData;
+	};	
+	
+	CCommand *m_pFirstCommand;
+
+	class CExecFile
+	{
+	public:
+		const char *m_pFilename;
+		struct CExecFile *m_pPrev;
+	};
+	
+	CExecFile *m_pFirstExec;
+	class IStorage *m_pStorage;
+
+	static void Con_Chain(IResult *pResult, void *pUserData);
+	static void Con_Echo(IResult *pResult, void *pUserData);
+	static void Con_Exec(IResult *pResult, void *pUserData);
+
+	void ExecuteFileRecurse(const char *pFilename);
+	void ExecuteLineStroked(int Stroke, const char *pStr);
+	
+	FPrintCallback m_pfnPrintCallback;
+	void *m_pPrintCallbackUserdata;
+
+	enum
+	{
+		CONSOLE_MAX_STR_LENGTH  = 1024,
+		MAX_PARTS = (CONSOLE_MAX_STR_LENGTH+1)/2
+	};
+	
+	class CResult : public IResult
+	{
+	public:
+		char m_aStringStorage[CONSOLE_MAX_STR_LENGTH+1];
+		char *m_pArgsStart;
+		
+		const char *m_pCommand;
+		const char *m_apArgs[MAX_PARTS];
+		
+		void AddArgument(const char *pArg)
+		{
+			m_apArgs[m_NumArgs++] = pArg;
+		}
+
+		virtual const char *GetString(unsigned Index);
+		virtual int GetInteger(unsigned Index);
+		virtual float GetFloat(unsigned Index);
+	};
+	
+	int ParseStart(CResult *pResult, const char *pString, int Length);
+	int ParseArgs(CResult *pResult, const char *pFormat);
+
+	CCommand *FindCommand(const char *pName);
+
+public:
+	CConsole();
+
+	virtual CCommandInfo *GetCommandInfo(const char *pName);
+	virtual void PossibleCommands(const char *pStr, int FlagMask, FPossibleCallback pfnCallback, void *pUser) ;
+
+	virtual void ParseArguments(int NumArgs, const char **ppArguments);
+	virtual void Register(const char *pName, const char *pParams, int Flags, FCommandCallback pfnFunc, void *pUser, const char *pHelp);
+	virtual void Chain(const char *pName, FChainCommandCallback pfnChainFunc, void *pUser);
+	
+	virtual void ExecuteLine(const char *pStr);
+	virtual void ExecuteFile(const char *pFilename);
+
+	virtual void RegisterPrintCallback(FPrintCallback pfnPrintCallback, void *pUserData);
+	virtual void Print(const char *pStr);
+};
+
+#endif
diff --git a/src/engine/shared/datafile.cpp b/src/engine/shared/datafile.cpp
new file mode 100644
index 00000000..dcc32ef2
--- /dev/null
+++ b/src/engine/shared/datafile.cpp
@@ -0,0 +1,643 @@
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+#include <base/system.h>
+#include <engine/storage.h>
+#include "datafile.h"
+#include "engine.h"
+#include <zlib.h>
+
+static const int DEBUG=0;
+
+struct CDatafileItemType
+{
+	int m_Type;
+	int m_Start;
+	int m_Num;
+} ;
+
+struct CDatafileItem
+{
+	int m_TypeAndId;
+	int m_Size;
+};
+
+struct CDatafileHeader
+{
+	char m_aId[4];
+	int m_Version;
+	int m_Size;
+	int m_Swaplen;
+	int m_NumItemTypes;
+	int m_NumItems;
+	int m_NumRawData;
+	int m_ItemSize;
+	int m_DataSize;
+};
+
+struct CDatafileData
+{
+	int m_NumItemTypes;
+	int m_NumItems;
+	int m_NumRawData;
+	int m_ItemSize;
+	int m_DataSize;
+	char m_aStart[4];
+};
+
+struct CDatafileInfo
+{
+	CDatafileItemType *m_pItemTypes;
+	int *m_pItemOffsets;
+	int *m_pDataOffsets;
+	int *m_pDataSizes;
+
+	char *m_pItemStart;
+	char *m_pDataStart;
+};
+
+struct CDatafile
+{
+	IOHANDLE m_File;
+	unsigned m_Crc;
+	CDatafileInfo m_Info;
+	CDatafileHeader m_Header;
+	int m_DataStartOffset;
+	char **m_ppDataPtrs;
+	char *m_pData;
+};
+
+bool CDataFileReader::Open(class IStorage *pStorage, const char *pFilename)
+{
+	dbg_msg("datafile", "loading. filename='%s'", pFilename);
+
+	IOHANDLE File = pStorage->OpenFile(pFilename, IOFLAG_READ);
+	if(!File)
+	{
+		dbg_msg("datafile", "could not open '%s'", pFilename);
+		return false;
+	}	
+	
+	
+	// take the CRC of the file and store it
+	unsigned Crc = 0;
+	{
+		enum
+		{
+			BUFFER_SIZE = 64*1024
+		};
+		
+		unsigned char aBuffer[BUFFER_SIZE];
+		
+		while(1)
+		{
+			unsigned Bytes = io_read(File, aBuffer, BUFFER_SIZE);
+			if(Bytes <= 0)
+				break;
+			Crc = crc32(Crc, aBuffer, Bytes); // ignore_convention
+		}
+		
+		io_seek(File, 0, IOSEEK_START);
+	}
+	
+	
+	// TODO: change this header
+	CDatafileHeader Header;
+	io_read(File, &Header, sizeof(Header));
+	if(Header.m_aId[0] != 'A' || Header.m_aId[1] != 'T' || Header.m_aId[2] != 'A' || Header.m_aId[3] != 'D')
+	{
+		if(Header.m_aId[0] != 'D' || Header.m_aId[1] != 'A' || Header.m_aId[2] != 'T' || Header.m_aId[3] != 'A')
+		{
+			dbg_msg("datafile", "wrong signature. %x %x %x %x", Header.m_aId[0], Header.m_aId[1], Header.m_aId[2], Header.m_aId[3]);
+			return 0;
+		}
+	}
+
+#if defined(CONF_ARCH_ENDIAN_BIG)
+	swap_endian(&Header, sizeof(int), sizeof(Header)/sizeof(int));	
+#endif
+	if(Header.m_Version != 3 && Header.m_Version != 4)
+	{
+		dbg_msg("datafile", "wrong version. version=%x", Header.m_Version);
+		return 0;
+	}
+	
+	// read in the rest except the data
+	unsigned Size = 0;
+	Size += Header.m_NumItemTypes*sizeof(CDatafileItemType);
+	Size += (Header.m_NumItems+Header.m_NumRawData)*sizeof(int);
+	if(Header.m_Version == 4)
+		Size += Header.m_NumRawData*sizeof(int); // v4 has uncompressed data sizes aswell
+	Size += Header.m_ItemSize;
+	
+	unsigned AllocSize = Size;
+	AllocSize += sizeof(CDatafile); // add space for info structure
+	AllocSize += Header.m_NumRawData*sizeof(void*); // add space for data pointers
+
+	m_pDataFile = (CDatafile*)mem_alloc(AllocSize, 1);
+	m_pDataFile->m_Header = Header;
+	m_pDataFile->m_DataStartOffset = sizeof(CDatafileHeader) + Size;
+	m_pDataFile->m_ppDataPtrs = (char**)(m_pDataFile+1);
+	m_pDataFile->m_pData = (char *)(m_pDataFile+1)+Header.m_NumRawData*sizeof(char *);
+	m_pDataFile->m_File = File;
+	m_pDataFile->m_Crc = Crc;
+	
+	// clear the data pointers
+	mem_zero(m_pDataFile->m_ppDataPtrs, Header.m_NumRawData*sizeof(void*));
+	
+	// read types, offsets, sizes and item data
+	unsigned ReadSize = io_read(File, m_pDataFile->m_pData, Size);
+	if(ReadSize != Size)
+	{
+		mem_free(m_pDataFile);
+		m_pDataFile = 0;
+		dbg_msg("datafile", "couldn't load the whole thing, wanted=%d got=%d", Size, ReadSize);
+		return false;
+	}
+
+#if defined(CONF_ARCH_ENDIAN_BIG)
+	swap_endian(m_pDataFile->m_pData, sizeof(int), Header.Swaplen / sizeof(int));
+#endif
+
+	//if(DEBUG)
+	{
+		dbg_msg("datafile", "allocsize=%d", AllocSize);
+		dbg_msg("datafile", "readsize=%d", ReadSize);
+		dbg_msg("datafile", "swaplen=%d", Header.m_Swaplen);
+		dbg_msg("datafile", "item_size=%d", m_pDataFile->m_Header.m_ItemSize);
+	}
+	
+	m_pDataFile->m_Info.m_pItemTypes = (CDatafileItemType *)m_pDataFile->m_pData;
+	m_pDataFile->m_Info.m_pItemOffsets = (int *)&m_pDataFile->m_Info.m_pItemTypes[m_pDataFile->m_Header.m_NumItemTypes];
+	m_pDataFile->m_Info.m_pDataOffsets = (int *)&m_pDataFile->m_Info.m_pItemOffsets[m_pDataFile->m_Header.m_NumItems];
+	m_pDataFile->m_Info.m_pDataSizes = (int *)&m_pDataFile->m_Info.m_pDataOffsets[m_pDataFile->m_Header.m_NumRawData];
+	
+	if(Header.m_Version == 4)
+		m_pDataFile->m_Info.m_pItemStart = (char *)&m_pDataFile->m_Info.m_pDataSizes[m_pDataFile->m_Header.m_NumRawData];
+	else
+		m_pDataFile->m_Info.m_pItemStart = (char *)&m_pDataFile->m_Info.m_pDataOffsets[m_pDataFile->m_Header.m_NumRawData];
+	m_pDataFile->m_Info.m_pDataStart = m_pDataFile->m_Info.m_pItemStart + m_pDataFile->m_Header.m_ItemSize;
+
+	dbg_msg("datafile", "loading done. datafile='%s'", pFilename);
+
+	if(DEBUG)
+	{
+		/*
+		for(int i = 0; i < m_pDataFile->data.num_raw_data; i++)
+		{
+			void *p = datafile_get_data(df, i);
+			dbg_msg("datafile", "%d %d", (int)((char*)p - (char*)(&m_pDataFile->data)), size);
+		}
+			
+		for(int i = 0; i < datafile_num_items(df); i++)
+		{
+			int type, id;
+			void *data = datafile_get_item(df, i, &type, &id);
+			dbg_msg("map", "\t%d: type=%x id=%x p=%p offset=%d", i, type, id, data, m_pDataFile->info.item_offsets[i]);
+			int *idata = (int*)data;
+			for(int k = 0; k < 3; k++)
+				dbg_msg("datafile", "\t\t%d=%d (%x)", k, idata[k], idata[k]);
+		}
+
+		for(int i = 0; i < m_pDataFile->data.num_m_aItemTypes; i++)
+		{
+			dbg_msg("map", "\t%d: type=%x start=%d num=%d", i,
+				m_pDataFile->info.m_aItemTypes[i].type,
+				m_pDataFile->info.m_aItemTypes[i].start,
+				m_pDataFile->info.m_aItemTypes[i].num);
+			for(int k = 0; k < m_pDataFile->info.m_aItemTypes[i].num; k++)
+			{
+				int type, id;
+				datafile_get_item(df, m_pDataFile->info.m_aItemTypes[i].start+k, &type, &id);
+				if(type != m_pDataFile->info.m_aItemTypes[i].type)
+					dbg_msg("map", "\tERROR");
+			}
+		}
+		*/
+	}
+		
+	return true;
+}
+
+int CDataFileReader::NumData()
+{
+	if(!m_pDataFile) { return 0; }
+	return m_pDataFile->m_Header.m_NumRawData;
+}
+
+// always returns the size in the file
+int CDataFileReader::GetDataSize(int Index)
+{
+	if(!m_pDataFile) { return 0; }
+	
+	if(Index == m_pDataFile->m_Header.m_NumRawData-1)
+		return m_pDataFile->m_Header.m_DataSize-m_pDataFile->m_Info.m_pDataOffsets[Index];
+	return  m_pDataFile->m_Info.m_pDataOffsets[Index+1]-m_pDataFile->m_Info.m_pDataOffsets[Index];
+}
+
+void *CDataFileReader::GetDataImpl(int Index, int Swap)
+{
+	if(!m_pDataFile) { return 0; }
+	
+	// load it if needed
+	if(!m_pDataFile->m_ppDataPtrs[Index])
+	{
+		// fetch the data size
+		int DataSize = GetDataSize(Index);
+		int SwapSize = DataSize;
+		
+		if(m_pDataFile->m_Header.m_Version == 4)
+		{
+			// v4 has compressed data
+			void *pTemp = (char *)mem_alloc(DataSize, 1);
+			unsigned long UncompressedSize = m_pDataFile->m_Info.m_pDataSizes[Index];
+			unsigned long s;
+
+			dbg_msg("datafile", "loading data index=%d size=%d uncompressed=%d", Index, DataSize, UncompressedSize);
+			m_pDataFile->m_ppDataPtrs[Index] = (char *)mem_alloc(UncompressedSize, 1);
+			
+			// read the compressed data
+			io_seek(m_pDataFile->m_File, m_pDataFile->m_DataStartOffset+m_pDataFile->m_Info.m_pDataOffsets[Index], IOSEEK_START);
+			io_read(m_pDataFile->m_File, pTemp, DataSize);
+
+			// decompress the data, TODO: check for errors
+			s = UncompressedSize;
+			uncompress((Bytef*)m_pDataFile->m_ppDataPtrs[Index], &s, (Bytef*)pTemp, DataSize); // ignore_convention
+			SwapSize = s;
+
+			// clean up the temporary buffers
+			mem_free(pTemp);
+		}
+		else
+		{
+			// load the data
+			dbg_msg("datafile", "loading data index=%d size=%d", Index, DataSize);
+			m_pDataFile->m_ppDataPtrs[Index] = (char *)mem_alloc(DataSize, 1);
+			io_seek(m_pDataFile->m_File, m_pDataFile->m_DataStartOffset+m_pDataFile->m_Info.m_pDataOffsets[Index], IOSEEK_START);
+			io_read(m_pDataFile->m_File, m_pDataFile->m_ppDataPtrs[Index], DataSize);
+		}
+
+#if defined(CONF_ARCH_ENDIAN_BIG)
+		if(Swap && SwapSize)
+			swap_endian(m_pDataFile->m_ppDataPtrs[Index], sizeof(int), SwapSize/sizeof(int));
+#endif
+	}
+	
+	return m_pDataFile->m_ppDataPtrs[Index];
+}
+
+void *CDataFileReader::GetData(int Index)
+{
+	return GetDataImpl(Index, 0);
+}
+
+void *CDataFileReader::GetDataSwapped(int Index)
+{
+	return GetDataImpl(Index, 1);
+}
+
+void CDataFileReader::UnloadData(int Index)
+{
+	if(Index < 0)
+		return;
+		
+	//
+	mem_free(m_pDataFile->m_ppDataPtrs[Index]);
+	m_pDataFile->m_ppDataPtrs[Index] = 0x0;
+}
+
+int CDataFileReader::GetItemSize(int Index)
+{
+	if(!m_pDataFile) { return 0; }
+	if(Index == m_pDataFile->m_Header.m_NumItems-1)
+		return m_pDataFile->m_Header.m_ItemSize-m_pDataFile->m_Info.m_pItemOffsets[Index];
+	return  m_pDataFile->m_Info.m_pItemOffsets[Index+1]-m_pDataFile->m_Info.m_pItemOffsets[Index];
+}
+
+void *CDataFileReader::GetItem(int Index, int *pType, int *pId)
+{
+	if(!m_pDataFile) { if(pType) *pType = 0; if(pId) *pId = 0; return 0; }
+	
+	CDatafileItem *i = (CDatafileItem *)(m_pDataFile->m_Info.m_pItemStart+m_pDataFile->m_Info.m_pItemOffsets[Index]);
+	if(pType)
+		*pType = (i->m_TypeAndId>>16)&0xffff; // remove sign extention
+	if(pId)
+		*pId = i->m_TypeAndId&0xffff;
+	return (void *)(i+1);
+}
+
+void CDataFileReader::GetType(int Type, int *pStart, int *pNum)
+{
+	*pStart = 0;
+	*pNum = 0;
+
+	if(!m_pDataFile)
+		return;
+	
+	for(int i = 0; i < m_pDataFile->m_Header.m_NumItemTypes; i++)
+	{
+		if(m_pDataFile->m_Info.m_pItemTypes[i].m_Type == Type)
+		{
+			*pStart = m_pDataFile->m_Info.m_pItemTypes[i].m_Start;
+			*pNum = m_pDataFile->m_Info.m_pItemTypes[i].m_Num;
+			return;
+		}
+	}
+}
+
+void *CDataFileReader::FindItem(int Type, int Id)
+{
+	if(!m_pDataFile) return 0;
+	
+	int Start, Num;
+	GetType(Type, &Start, &Num);
+	for(int i = 0; i < Num; i++)
+	{
+		int ItemId;
+		void *pItem = GetItem(Start+i,0, &ItemId);
+		if(Id == ItemId)
+			return pItem;
+	}
+	return 0;
+}
+
+int CDataFileReader::NumItems()
+{
+	if(!m_pDataFile) return 0;
+	return m_pDataFile->m_Header.m_NumItems;
+}
+
+bool CDataFileReader::Close()
+{
+	if(!m_pDataFile)
+		return true;
+	
+	// free the data that is loaded
+	int i;
+	for(i = 0; i < m_pDataFile->m_Header.m_NumRawData; i++)
+		mem_free(m_pDataFile->m_ppDataPtrs[i]);
+	
+	io_close(m_pDataFile->m_File);
+	mem_free(m_pDataFile);
+	m_pDataFile = 0;
+	return true;
+}
+
+unsigned CDataFileReader::Crc()
+{
+	if(!m_pDataFile) return -1;
+	return m_pDataFile->m_Crc;
+}
+
+bool CDataFileWriter::Open(class IStorage *pStorage, const char *pFilename)
+{
+	int i;
+	//DATAFILE_OUT *df = (DATAFILE_OUT*)mem_alloc(sizeof(DATAFILE_OUT), 1);
+	m_File = pStorage->OpenFile(pFilename, IOFLAG_WRITE);
+	if(!m_File)
+		return false;
+	
+	m_NumItems = 0;
+	m_NumDatas = 0;
+	m_NumItemTypes = 0;
+	mem_zero(&m_aItemTypes, sizeof(m_aItemTypes));
+
+	for(i = 0; i < 0xffff; i++)
+	{
+		m_aItemTypes[i].m_First = -1;
+		m_aItemTypes[i].m_Last = -1;
+	}
+	
+	return true;
+}
+
+int CDataFileWriter::AddItem(int Type, int Id, int Size, void *pData)
+{
+	m_aItems[m_NumItems].m_Type = Type;
+	m_aItems[m_NumItems].m_Id = Id;
+	m_aItems[m_NumItems].m_Size = Size;
+	
+	/*
+	dbg_msg("datafile", "added item type=%d id=%d size=%d", type, id, size);
+	int i;
+	for(i = 0; i < size/4; i++)
+		dbg_msg("datafile", "\t%d: %08x %d", i, ((int*)data)[i], ((int*)data)[i]);
+	*/
+	
+	// copy data
+	m_aItems[m_NumItems].m_pData = mem_alloc(Size, 1);
+	mem_copy(m_aItems[m_NumItems].m_pData, pData, Size);
+
+	if(!m_aItemTypes[Type].m_Num) // count item types
+		m_NumItemTypes++;
+
+	// link
+	m_aItems[m_NumItems].m_Prev = m_aItemTypes[Type].m_Last;
+	m_aItems[m_NumItems].m_Next = -1;
+	
+	if(m_aItemTypes[Type].m_Last != -1)
+		m_aItems[m_aItemTypes[Type].m_Last].m_Next = m_NumItems;
+	m_aItemTypes[Type].m_Last = m_NumItems;
+	
+	if(m_aItemTypes[Type].m_First == -1)
+		m_aItemTypes[Type].m_First = m_NumItems;
+	
+	m_aItemTypes[Type].m_Num++;
+		
+	m_NumItems++;
+	return m_NumItems-1;
+}
+
+int CDataFileWriter::AddData(int Size, void *pData)
+{
+	CDataInfo *pInfo = &m_aDatas[m_NumDatas];
+	unsigned long s = compressBound(Size);
+	void *pCompData = mem_alloc(s, 1); // temporary buffer that we use duing compression
+
+	int Result = compress((Bytef*)pCompData, &s, (Bytef*)pData, Size); // ignore_convention
+	if(Result != Z_OK)
+	{
+		dbg_msg("datafile", "compression error %d", Result);
+		dbg_assert(0, "zlib error");
+	}
+		
+	pInfo->m_UncompressedSize = Size;
+	pInfo->m_CompressedSize = (int)s;
+	pInfo->m_pCompressedData = mem_alloc(pInfo->m_CompressedSize, 1);
+	mem_copy(pInfo->m_pCompressedData, pCompData, pInfo->m_CompressedSize);
+	mem_free(pCompData);
+
+	m_NumDatas++;
+	return m_NumDatas-1;
+}
+
+int CDataFileWriter::AddDataSwapped(int Size, void *pData)
+{
+#if defined(CONF_ARCH_ENDIAN_BIG)
+	void *pSwapped = mem_alloc(Size, 1); // temporary buffer that we use duing compression
+	int Index;
+	mem_copy(pSwapped, pData, Size);
+	swap_endian(&pSwapped, sizeof(int), Size/sizeof(int));
+	Index = AddData(Size, Swapped);
+	mem_free(pSwapped);
+	return Index;
+#else
+	return AddData(Size, pData);
+#endif
+}
+
+
+int CDataFileWriter::Finish()
+{
+	int ItemSize = 0;
+	int TypesSize, HeaderSize, OffsetSize, FileSize, SwapSize;
+	int DataSize = 0;
+	CDatafileHeader Header;
+
+	// we should now write this file!
+	if(DEBUG)
+		dbg_msg("datafile", "writing");
+
+	// calculate sizes
+	for(int i = 0; i < m_NumItems; i++)
+	{
+		if(DEBUG)
+			dbg_msg("datafile", "item=%d size=%d (%d)", i, m_aItems[i].m_Size, m_aItems[i].m_Size+sizeof(CDatafileItem));
+		ItemSize += m_aItems[i].m_Size + sizeof(CDatafileItem);
+	}
+	
+	
+	for(int i = 0; i < m_NumDatas; i++)
+		DataSize += m_aDatas[i].m_CompressedSize;
+	
+	// calculate the complete size
+	TypesSize = m_NumItemTypes*sizeof(CDatafileItemType);
+	HeaderSize = sizeof(CDatafileHeader);
+	OffsetSize = m_NumItems*sizeof(int) + m_NumDatas*sizeof(int);
+	FileSize = HeaderSize + TypesSize + OffsetSize + ItemSize + DataSize;
+	SwapSize = FileSize - DataSize;
+	
+	(void)SwapSize;
+	
+	if(DEBUG)
+		dbg_msg("datafile", "num_m_aItemTypes=%d TypesSize=%d m_aItemsize=%d DataSize=%d", m_NumItemTypes, TypesSize, ItemSize, DataSize);
+	
+	// construct Header
+	{
+		Header.m_aId[0] = 'D';
+		Header.m_aId[1] = 'A';
+		Header.m_aId[2] = 'T';
+		Header.m_aId[3] = 'A';
+		Header.m_Version = 4;
+		Header.m_Size = FileSize - 16;
+		Header.m_Swaplen = SwapSize - 16;
+		Header.m_NumItemTypes = m_NumItemTypes;
+		Header.m_NumItems = m_NumItems;
+		Header.m_NumRawData = m_NumDatas;
+		Header.m_ItemSize = ItemSize;
+		Header.m_DataSize = DataSize;
+		
+		// TODO: apply swapping
+		// write Header
+		if(DEBUG)
+			dbg_msg("datafile", "HeaderSize=%d", sizeof(Header));
+		io_write(m_File, &Header, sizeof(Header));
+	}
+	
+	// write types
+	for(int i = 0, Count = 0; i < 0xffff; i++)
+	{
+		if(m_aItemTypes[i].m_Num)
+		{
+			// write info
+			CDatafileItemType Info;
+			Info.m_Type = i;
+			Info.m_Start = Count;
+			Info.m_Num = m_aItemTypes[i].m_Num;
+			if(DEBUG)
+				dbg_msg("datafile", "writing type=%x start=%d num=%d", Info.m_Type, Info.m_Start, Info.m_Num);
+			io_write(m_File, &Info, sizeof(Info));
+			Count += m_aItemTypes[i].m_Num;
+		}
+	}
+	
+	// write item offsets
+	for(int i = 0, Offset = 0; i < 0xffff; i++)
+	{
+		if(m_aItemTypes[i].m_Num)
+		{
+			// write all m_aItems in of this type
+			int k = m_aItemTypes[i].m_First;
+			while(k != -1)
+			{
+				if(DEBUG)
+					dbg_msg("datafile", "writing item offset num=%d offset=%d", k, Offset);
+				io_write(m_File, &Offset, sizeof(Offset));
+				Offset += m_aItems[k].m_Size + sizeof(CDatafileItem);
+				
+				// next
+				k = m_aItems[k].m_Next;
+			}
+		}
+	}
+	
+	// write data offsets
+	for(int i = 0, Offset = 0; i < m_NumDatas; i++)
+	{
+		if(DEBUG)
+			dbg_msg("datafile", "writing data offset num=%d offset=%d", i, Offset);
+		io_write(m_File, &Offset, sizeof(Offset));
+		Offset += m_aDatas[i].m_CompressedSize;
+	}
+
+	// write data uncompressed sizes
+	for(int i = 0; i < m_NumDatas; i++)
+	{
+		/*
+		if(DEBUG)
+			dbg_msg("datafile", "writing data offset num=%d offset=%d", i, offset);
+		*/
+		io_write(m_File, &m_aDatas[i].m_UncompressedSize, sizeof(int));
+	}
+	
+	// write m_aItems
+	for(int i = 0; i < 0xffff; i++)
+	{
+		if(m_aItemTypes[i].m_Num)
+		{
+			// write all m_aItems in of this type
+			int k = m_aItemTypes[i].m_First;
+			while(k != -1)
+			{
+				CDatafileItem Item;
+				Item.m_TypeAndId = (i<<16)|m_aItems[k].m_Id;
+				Item.m_Size = m_aItems[k].m_Size;
+				if(DEBUG)
+					dbg_msg("datafile", "writing item type=%x idx=%d id=%d size=%d", i, k, m_aItems[k].m_Id, m_aItems[k].m_Size);
+				
+				io_write(m_File, &Item, sizeof(Item));
+				io_write(m_File, m_aItems[k].m_pData, m_aItems[k].m_Size);
+				
+				// next
+				k = m_aItems[k].m_Next;
+			}
+		}
+	}
+	
+	// write data
+	for(int i = 0; i < m_NumDatas; i++)
+	{
+		if(DEBUG)
+			dbg_msg("datafile", "writing data id=%d size=%d", i, m_aDatas[i].m_CompressedSize);
+		io_write(m_File, m_aDatas[i].m_pCompressedData, m_aDatas[i].m_CompressedSize);
+	}
+
+	// free data
+	for(int i = 0; i < m_NumItems; i++)
+		mem_free(m_aItems[i].m_pData);
+
+	
+	io_close(m_File);
+	
+	if(DEBUG)
+		dbg_msg("datafile", "done");
+	return 0;
+}
diff --git a/src/engine/shared/datafile.h b/src/engine/shared/datafile.h
new file mode 100644
index 00000000..eddce611
--- /dev/null
+++ b/src/engine/shared/datafile.h
@@ -0,0 +1,77 @@
+#ifndef ENGINE_SHARED_DATAFILE_H
+#define ENGINE_SHARED_DATAFILE_H
+
+// raw datafile access
+class CDataFileReader
+{
+	class CDatafile *m_pDataFile;
+	void *GetDataImpl(int Index, int Swap);
+public:
+	CDataFileReader() : m_pDataFile(0) {}
+	~CDataFileReader() { Close(); }
+	
+	bool IsOpen() const { return m_pDataFile != 0; }
+	
+	bool Open(class IStorage *pStorage, const char *pFilename);
+	bool Close();
+	
+	void *GetData(int Index);
+	void *GetDataSwapped(int Index); // makes sure that the data is 32bit LE ints when saved
+	int GetDataSize(int Index);
+	void UnloadData(int Index);
+	void *GetItem(int Index, int *pType, int *pId);
+	int GetItemSize(int Index);
+	void GetType(int Type, int *pStart, int *pNum);
+	void *FindItem(int Type, int Id);
+	int NumItems();
+	int NumData();
+	void Unload();
+	
+	unsigned Crc();
+};
+
+// write access
+class CDataFileWriter
+{
+	struct CDataInfo
+	{
+		int m_UncompressedSize;
+		int m_CompressedSize;
+		void *m_pCompressedData;
+	} ;
+
+	struct CItemInfo
+	{
+		int m_Type;
+		int m_Id;
+		int m_Size;
+		int m_Next;
+		int m_Prev;
+		void *m_pData;
+	};
+
+	struct CItemTypeInfo
+	{
+		int m_Num;
+		int m_First;
+		int m_Last;
+	};
+	
+	IOHANDLE m_File;
+	int m_NumItems;
+	int m_NumDatas;
+	int m_NumItemTypes;
+	CItemTypeInfo m_aItemTypes[0xffff];
+	CItemInfo m_aItems[1024];
+	CDataInfo m_aDatas[1024];	
+	
+public:
+	bool Open(class IStorage *pStorage, const char *Filename);
+	int AddData(int Size, void *pData);
+	int AddDataSwapped(int Size, void *pData);
+	int AddItem(int Type, int Id, int Size, void *pData);
+	int Finish();
+};
+
+
+#endif
diff --git a/src/engine/shared/demorec.cpp b/src/engine/shared/demorec.cpp
new file mode 100644
index 00000000..48b06e9a
--- /dev/null
+++ b/src/engine/shared/demorec.cpp
@@ -0,0 +1,623 @@
+#include <base/system.h>
+#include <engine/shared/protocol.h>
+#include <engine/storage.h>
+#include "demorec.h"
+#include "memheap.h"
+#include "snapshot.h"
+#include "compression.h"
+#include "network.h"
+#include "engine.h"
+
+static const unsigned char gs_aHeaderMarker[8] = {'T', 'W', 'D', 'E', 'M', 'O', 0, 1};
+
+CDemoRecorder::CDemoRecorder(class CSnapshotDelta *pSnapshotDelta)
+{
+	m_File = 0;
+	m_LastTickMarker = -1;
+	m_pSnapshotDelta = pSnapshotDelta;
+}
+
+//static IOHANDLE m_File = 0;
+
+// Record
+int CDemoRecorder::Start(class IStorage *pStorage, const char *pFilename, const char *pNetVersion, const char *pMap, int Crc, const char *pType)
+{
+	CDemoHeader Header;
+	if(m_File)
+		return -1;
+
+	m_File = pStorage->OpenFile(pFilename, IOFLAG_WRITE);
+	
+	if(!m_File)
+	{
+		dbg_msg("demorec/record", "Unable to open '%s' for recording", pFilename);
+		return -1;
+	}
+	
+	// write header
+	mem_zero(&Header, sizeof(Header));
+	mem_copy(Header.m_aMarker, gs_aHeaderMarker, sizeof(Header.m_aMarker));
+	str_copy(Header.m_aNetversion, pNetVersion, sizeof(Header.m_aNetversion));
+	str_copy(Header.m_aMap, pMap, sizeof(Header.m_aMap));
+	str_copy(Header.m_aType, pType, sizeof(Header.m_aType));
+	Header.m_aCrc[0] = (Crc>>24)&0xff;
+	Header.m_aCrc[1] = (Crc>>16)&0xff;
+	Header.m_aCrc[2] = (Crc>>8)&0xff;
+	Header.m_aCrc[3] = (Crc)&0xff;
+	io_write(m_File, &Header, sizeof(Header));
+	
+	m_LastKeyFrame = -1;
+	m_LastTickMarker = -1;
+	
+	dbg_msg("demorec/record", "Recording to '%s'", pFilename);
+	return 0;
+}
+
+/*
+	Tickmarker
+		7   = Always set
+		6   = Keyframe flag
+		0-5 = Delta tick
+	
+	Normal
+		7   = Not set
+		5-6 = Type
+		0-4 = Size
+*/
+
+enum
+{
+	CHUNKTYPEFLAG_TICKMARKER = 0x80,
+	CHUNKTICKFLAG_KEYFRAME = 0x40, // only when tickmarker is set
+	
+	CHUNKMASK_TICK = 0x3f,
+	CHUNKMASK_TYPE = 0x60,
+	CHUNKMASK_SIZE = 0x1f,
+	
+	CHUNKTYPE_SNAPSHOT = 1,
+	CHUNKTYPE_MESSAGE = 2,
+	CHUNKTYPE_DELTA = 3,
+
+	CHUNKFLAG_BIGSIZE = 0x10
+};
+
+void CDemoRecorder::WriteTickMarker(int Tick, int Keyframe)
+{
+	if(m_LastTickMarker == -1 || Tick-m_LastTickMarker > 63 || Keyframe)
+	{
+		unsigned char aChunk[5];
+		aChunk[0] = CHUNKTYPEFLAG_TICKMARKER;
+		aChunk[1] = (Tick>>24)&0xff;
+		aChunk[2] = (Tick>>16)&0xff;
+		aChunk[3] = (Tick>>8)&0xff;
+		aChunk[4] = (Tick)&0xff;
+
+		if(Keyframe)
+			aChunk[0] |= CHUNKTICKFLAG_KEYFRAME;
+		
+		io_write(m_File, aChunk, sizeof(aChunk));
+	}
+	else
+	{
+		unsigned char aChunk[1];
+		aChunk[0] = CHUNKTYPEFLAG_TICKMARKER | (Tick-m_LastTickMarker);
+		io_write(m_File, aChunk, sizeof(aChunk));
+	}	
+
+	m_LastTickMarker = Tick;
+}
+
+void CDemoRecorder::Write(int Type, const void *pData, int Size)
+{
+	char aBuffer[64*1024];
+	char aBuffer2[64*1024];
+	unsigned char aChunk[3];
+	
+	if(!m_File)
+		return;
+
+	/* pad the data with 0 so we get an alignment of 4,
+	else the compression won't work and miss some bytes */
+	mem_copy(aBuffer2, pData, Size);
+	while(Size&3)
+		aBuffer2[Size++] = 0;
+	Size = CVariableInt::Compress(aBuffer2, Size, aBuffer); // buffer2 -> buffer
+	Size = CNetBase::Compress(aBuffer, Size, aBuffer2, sizeof(aBuffer2)); // buffer -> buffer2
+	
+	
+	aChunk[0] = ((Type&0x3)<<5);
+	if(Size < 30)
+	{
+		aChunk[0] |= Size;
+		io_write(m_File, aChunk, 1);
+	}
+	else
+	{
+		if(Size < 256)
+		{
+			aChunk[0] |= 30;
+			aChunk[1] = Size&0xff;
+			io_write(m_File, aChunk, 2);
+		}
+		else
+		{
+			aChunk[0] |= 31;
+			aChunk[1] = Size&0xff;
+			aChunk[2] = Size>>8;
+			io_write(m_File, aChunk, 3);
+		}
+	}
+	
+	io_write(m_File, aBuffer2, Size);
+}
+
+void CDemoRecorder::RecordSnapshot(int Tick, const void *pData, int Size)
+{
+	if(m_LastKeyFrame == -1 || (Tick-m_LastKeyFrame) > SERVER_TICK_SPEED*5)
+	{
+		// write full tickmarker
+		WriteTickMarker(Tick, 1);
+		
+		// write snapshot
+		Write(CHUNKTYPE_SNAPSHOT, pData, Size);
+			
+		m_LastKeyFrame = Tick;
+		mem_copy(m_aLastSnapshotData, pData, Size);
+	}
+	else
+	{
+		// create delta, prepend tick
+		char aDeltaData[CSnapshot::MAX_SIZE+sizeof(int)];
+		int DeltaSize;
+
+		// write tickmarker
+		WriteTickMarker(Tick, 0);
+		
+		DeltaSize = m_pSnapshotDelta->CreateDelta((CSnapshot*)m_aLastSnapshotData, (CSnapshot*)pData, &aDeltaData);
+		if(DeltaSize)
+		{
+			// record delta
+			Write(CHUNKTYPE_DELTA, aDeltaData, DeltaSize);
+			mem_copy(m_aLastSnapshotData, pData, Size);
+		}
+	}
+}
+
+void CDemoRecorder::RecordMessage(const void *pData, int Size)
+{
+	Write(CHUNKTYPE_MESSAGE, pData, Size);
+}
+
+int CDemoRecorder::Stop()
+{
+	if(!m_File)
+		return -1;
+		
+	dbg_msg("demorec/record", "Stopped recording");
+	io_close(m_File);
+	m_File = 0;
+	return 0;
+}
+
+
+
+CDemoPlayer::CDemoPlayer(class CSnapshotDelta *pSnapshotDelta)
+{
+	m_File = 0;
+	m_pKeyFrames = 0;
+
+	m_pSnapshotDelta = pSnapshotDelta;
+	m_LastSnapshotDataSize = -1;
+}
+
+void CDemoPlayer::SetListner(IListner *pListner)
+{
+	m_pListner = pListner;
+}
+
+
+int CDemoPlayer::ReadChunkHeader(int *pType, int *pSize, int *pTick)
+{
+	unsigned char Chunk = 0;
+	
+	*pSize = 0;
+	*pType = 0;
+	
+	if(io_read(m_File, &Chunk, sizeof(Chunk)) != sizeof(Chunk))
+		return -1;
+		
+	if(Chunk&CHUNKTYPEFLAG_TICKMARKER)
+	{
+		// decode tick marker
+		int Tickdelta = Chunk&(CHUNKMASK_TICK);
+		*pType = Chunk&(CHUNKTYPEFLAG_TICKMARKER|CHUNKTICKFLAG_KEYFRAME);
+		
+		if(Tickdelta == 0)
+		{
+			unsigned char aTickdata[4];
+			if(io_read(m_File, aTickdata, sizeof(aTickdata)) != sizeof(aTickdata))
+				return -1;
+			*pTick = (aTickdata[0]<<24) | (aTickdata[1]<<16) | (aTickdata[2]<<8) | aTickdata[3];
+		}
+		else
+		{
+			*pTick += Tickdelta;
+		}
+		
+	}
+	else
+	{
+		// decode normal chunk
+		*pType = (Chunk&CHUNKMASK_TYPE)>>5;
+		*pSize = Chunk&CHUNKMASK_SIZE;
+		
+		if(*pSize == 30)
+		{
+			unsigned char aSizedata[1];
+			if(io_read(m_File, aSizedata, sizeof(aSizedata)) != sizeof(aSizedata))
+				return -1;
+			*pSize = aSizedata[0];
+			
+		}
+		else if(*pSize == 31)
+		{
+			unsigned char aSizedata[2];
+			if(io_read(m_File, aSizedata, sizeof(aSizedata)) != sizeof(aSizedata))
+				return -1;
+			*pSize = (aSizedata[1]<<8) | aSizedata[0];
+		}
+	}
+	
+	return 0;
+}
+
+void CDemoPlayer::ScanFile()
+{
+	long StartPos;
+	CHeap Heap;
+	CKeyFrameSearch *pFirstKey = 0;
+	CKeyFrameSearch *pCurrentKey = 0;
+	//DEMOREC_CHUNK chunk;
+	int ChunkSize, ChunkType, ChunkTick = 0;
+	int i;
+
+	StartPos = io_tell(m_File);
+	m_Info.m_SeekablePoints = 0;
+
+	while(1)
+	{
+		long CurrentPos = io_tell(m_File);
+		
+		if(ReadChunkHeader(&ChunkType, &ChunkSize, &ChunkTick))
+			break;
+			
+		// read the chunk
+		if(ChunkType&CHUNKTYPEFLAG_TICKMARKER)
+		{
+			if(ChunkType&CHUNKTICKFLAG_KEYFRAME)
+			{
+				CKeyFrameSearch *pKey;
+				
+				// save the position
+				pKey = (CKeyFrameSearch *)Heap.Allocate(sizeof(CKeyFrameSearch));
+				pKey->m_Frame.m_Filepos = CurrentPos;
+				pKey->m_Frame.m_Tick = ChunkTick;
+				pKey->m_pNext = 0;
+				if(pCurrentKey)
+					pCurrentKey->m_pNext = pKey;
+				if(!pFirstKey)
+					pFirstKey = pKey;
+				pCurrentKey = pKey;
+				m_Info.m_SeekablePoints++;
+			}
+			
+			if(m_Info.m_Info.m_FirstTick == -1)
+				m_Info.m_Info.m_FirstTick = ChunkTick;
+			m_Info.m_Info.m_LastTick = ChunkTick;
+		}
+		else if(ChunkSize)
+			io_skip(m_File, ChunkSize);
+			
+	}
+
+	// copy all the frames to an array instead for fast access
+	m_pKeyFrames = (CKeyFrame*)mem_alloc(m_Info.m_SeekablePoints*sizeof(CKeyFrame), 1);
+	for(pCurrentKey = pFirstKey, i = 0; pCurrentKey; pCurrentKey = pCurrentKey->m_pNext, i++)
+		m_pKeyFrames[i] = pCurrentKey->m_Frame;
+		
+	// destroy the temporary heap and seek back to the start
+	io_seek(m_File, StartPos, IOSEEK_START);
+}
+
+void CDemoPlayer::DoTick()
+{
+	static char aCompresseddata[CSnapshot::MAX_SIZE];
+	static char aDecompressed[CSnapshot::MAX_SIZE];
+	static char aData[CSnapshot::MAX_SIZE];
+	int ChunkType, ChunkTick, ChunkSize;
+	int DataSize;
+	int GotSnapshot = 0;
+
+	// update ticks
+	m_Info.m_PreviousTick = m_Info.m_Info.m_CurrentTick;
+	m_Info.m_Info.m_CurrentTick = m_Info.m_NextTick;
+	ChunkTick = m_Info.m_Info.m_CurrentTick;
+
+	while(1)
+	{
+		if(ReadChunkHeader(&ChunkType, &ChunkSize, &ChunkTick))
+		{
+			// stop on error or eof
+			dbg_msg("demorec", "end of file");
+			Pause();
+			break;
+		}
+		
+		// read the chunk
+		if(ChunkSize)
+		{
+			if(io_read(m_File, aCompresseddata, ChunkSize) != (unsigned)ChunkSize)
+			{
+				// stop on error or eof
+				dbg_msg("demorec", "error reading chunk");
+				Stop();
+				break;
+			}
+			
+			DataSize = CNetBase::Decompress(aCompresseddata, ChunkSize, aDecompressed, sizeof(aDecompressed));
+			if(DataSize < 0)
+			{
+				// stop on error or eof
+				dbg_msg("demorec", "error during network decompression");
+				Stop();
+				break;
+			}
+			
+			DataSize = CVariableInt::Decompress(aDecompressed, DataSize, aData);
+
+			if(DataSize < 0)
+			{
+				dbg_msg("demorec", "error during intpack decompression");
+				Stop();
+				break;
+			}
+		}
+			
+		if(ChunkType == CHUNKTYPE_DELTA)
+		{
+			// process delta snapshot
+			static char aNewsnap[CSnapshot::MAX_SIZE];
+			
+			GotSnapshot = 1;
+			
+			DataSize = m_pSnapshotDelta->UnpackDelta((CSnapshot*)m_aLastSnapshotData, (CSnapshot*)aNewsnap, aData, DataSize);
+			
+			if(DataSize >= 0)
+			{
+				if(m_pListner)
+					m_pListner->OnDemoPlayerSnapshot(aNewsnap, DataSize);
+
+				m_LastSnapshotDataSize = DataSize;
+				mem_copy(m_aLastSnapshotData, aNewsnap, DataSize);
+			}
+			else
+				dbg_msg("demorec", "error duing unpacking of delta, err=%d", DataSize);
+		}
+		else if(ChunkType == CHUNKTYPE_SNAPSHOT)
+		{
+			// process full snapshot
+			GotSnapshot = 1;
+			
+			m_LastSnapshotDataSize = DataSize;
+			mem_copy(m_aLastSnapshotData, aData, DataSize);
+			if(m_pListner)
+				m_pListner->OnDemoPlayerSnapshot(aData, DataSize);
+		}
+		else
+		{
+			// if there were no snapshots in this tick, replay the last one
+			if(!GotSnapshot && m_pListner && m_LastSnapshotDataSize != -1)
+			{
+				GotSnapshot = 1;
+				m_pListner->OnDemoPlayerSnapshot(m_aLastSnapshotData, m_LastSnapshotDataSize);
+			}
+			
+			// check the remaining types
+			if(ChunkType&CHUNKTYPEFLAG_TICKMARKER)
+			{
+				m_Info.m_NextTick = ChunkTick;
+				break;
+			}
+			else if(ChunkType == CHUNKTYPE_MESSAGE)
+			{
+				if(m_pListner)
+					m_pListner->OnDemoPlayerMessage(aData, DataSize);
+			}
+		}
+	}
+}
+
+void CDemoPlayer::Pause()
+{
+	m_Info.m_Info.m_Paused = 1;
+}
+
+void CDemoPlayer::Unpause()
+{
+	if(m_Info.m_Info.m_Paused)
+	{
+		/*m_Info.start_tick = m_Info.current_tick;
+		m_Info.start_time = time_get();*/
+		m_Info.m_Info.m_Paused = 0;
+	}
+}
+
+int CDemoPlayer::Load(class IStorage *pStorage, const char *pFilename)
+{
+	m_File = pStorage->OpenFile(pFilename, IOFLAG_READ);
+	if(!m_File)
+	{
+		dbg_msg("demorec/playback", "could not open '%s'", pFilename);
+		return -1;
+	}
+	
+	// clear the playback info
+	mem_zero(&m_Info, sizeof(m_Info));
+	m_Info.m_Info.m_FirstTick = -1;
+	m_Info.m_Info.m_LastTick = -1;
+	//m_Info.start_tick = -1;
+	m_Info.m_NextTick = -1;
+	m_Info.m_Info.m_CurrentTick = -1;
+	m_Info.m_PreviousTick = -1;
+	m_Info.m_Info.m_Speed = 1;
+	
+	m_LastSnapshotDataSize = -1;
+
+	// read the header
+	io_read(m_File, &m_Info.m_Header, sizeof(m_Info.m_Header));
+	if(mem_comp(m_Info.m_Header.m_aMarker, gs_aHeaderMarker, sizeof(gs_aHeaderMarker)) != 0)
+	{
+		dbg_msg("demorec/playback", "'%s' is not a demo file", pFilename);
+		io_close(m_File);
+		m_File = 0;
+		return -1;
+	}
+	
+	// scan the file for interessting points
+	ScanFile();
+	
+	// ready for playback
+	return 0;
+}
+
+int CDemoPlayer::NextFrame()
+{
+	DoTick();
+	return IsPlaying();
+}
+
+int CDemoPlayer::Play()
+{
+	// fill in previous and next tick
+	while(m_Info.m_PreviousTick == -1 && IsPlaying())
+		DoTick();
+		
+	// set start info
+	/*m_Info.start_tick = m_Info.previous_tick;
+	m_Info.start_time = time_get();*/
+	m_Info.m_CurrentTime = m_Info.m_PreviousTick*time_freq()/SERVER_TICK_SPEED;
+	m_Info.m_LastUpdate = time_get();
+	return 0;
+}
+
+int CDemoPlayer::SetPos(float Percent)
+{
+	int Keyframe;
+	int WantedTick;
+	if(!m_File)
+		return -1;
+	
+	// -5 because we have to have a current tick and previous tick when we do the playback
+	WantedTick = m_Info.m_Info.m_FirstTick + (int)((m_Info.m_Info.m_LastTick-m_Info.m_Info.m_FirstTick)*Percent) - 5;
+	
+	Keyframe = (int)(m_Info.m_SeekablePoints*Percent);
+
+	if(Keyframe < 0 || Keyframe >= m_Info.m_SeekablePoints)
+		return -1;
+	
+	// get correct key frame
+	if(m_pKeyFrames[Keyframe].m_Tick < WantedTick)
+		while(Keyframe < m_Info.m_SeekablePoints-1 && m_pKeyFrames[Keyframe].m_Tick < WantedTick)
+			Keyframe++;
+
+	while(Keyframe && m_pKeyFrames[Keyframe].m_Tick > WantedTick)
+		Keyframe--;
+	
+	// seek to the correct keyframe
+	io_seek(m_File, m_pKeyFrames[Keyframe].m_Filepos, IOSEEK_START);
+
+	//m_Info.start_tick = -1;
+	m_Info.m_NextTick = -1;
+	m_Info.m_Info.m_CurrentTick = -1;
+	m_Info.m_PreviousTick = -1;
+
+	// playback everything until we hit our tick
+	while(m_Info.m_PreviousTick < WantedTick)
+		DoTick();
+	
+	Play();
+	
+	return 0;
+}
+
+void CDemoPlayer::SetSpeed(float Speed)
+{
+	m_Info.m_Info.m_Speed = Speed;
+}
+
+int CDemoPlayer::Update()
+{
+	int64 Now = time_get();
+	int64 Deltatime = Now-m_Info.m_LastUpdate;
+	m_Info.m_LastUpdate = Now;
+	
+	if(!IsPlaying())
+		return 0;
+	
+	if(m_Info.m_Info.m_Paused)
+	{
+		
+	}
+	else
+	{
+		int64 Freq = time_freq();
+		m_Info.m_CurrentTime += (int64)(Deltatime*(double)m_Info.m_Info.m_Speed);
+		
+		while(1)
+		{
+			int64 CurtickStart = (m_Info.m_Info.m_CurrentTick)*Freq/SERVER_TICK_SPEED;
+
+			// break if we are ready
+			if(CurtickStart > m_Info.m_CurrentTime)
+				break;
+			
+			// do one more tick
+			DoTick();
+			
+			if(m_Info.m_Info.m_Paused)
+				return 0;
+		}
+
+		// update intratick
+		{	
+			int64 CurtickStart = (m_Info.m_Info.m_CurrentTick)*Freq/SERVER_TICK_SPEED;
+			int64 PrevtickStart = (m_Info.m_PreviousTick)*Freq/SERVER_TICK_SPEED;
+			m_Info.m_IntraTick = (m_Info.m_CurrentTime - PrevtickStart) / (float)(CurtickStart-PrevtickStart);
+			m_Info.m_TickTime = (m_Info.m_CurrentTime - PrevtickStart) / (float)Freq;
+		}
+		
+		if(m_Info.m_Info.m_CurrentTick == m_Info.m_PreviousTick ||
+			m_Info.m_Info.m_CurrentTick == m_Info.m_NextTick)
+		{
+			dbg_msg("demorec/playback", "tick error prev=%d cur=%d next=%d",
+				m_Info.m_PreviousTick, m_Info.m_Info.m_CurrentTick, m_Info.m_NextTick);
+		}
+	}
+	
+	return 0;
+}
+
+int CDemoPlayer::Stop()
+{
+	if(!m_File)
+		return -1;
+		
+	dbg_msg("demorec/playback", "Stopped playback");
+	io_close(m_File);
+	m_File = 0;
+	mem_free(m_pKeyFrames);
+	m_pKeyFrames = 0;
+	return 0;
+}
+
+
diff --git a/src/engine/shared/demorec.h b/src/engine/shared/demorec.h
new file mode 100644
index 00000000..0936c30c
--- /dev/null
+++ b/src/engine/shared/demorec.h
@@ -0,0 +1,117 @@
+#ifndef ENGINE_SHARED_DEMOREC_H
+#define ENGINE_SHARED_DEMOREC_H
+
+#include <engine/demo.h>
+#include "snapshot.h"
+
+struct CDemoHeader
+{
+	char m_aMarker[8];
+	char m_aNetversion[64];
+	char m_aMap[64];
+	unsigned char m_aCrc[4];
+	char m_aType[8];
+};
+
+class CDemoRecorder
+{
+	IOHANDLE m_File;
+	int m_LastTickMarker;
+	int m_LastKeyFrame;
+	unsigned char m_aLastSnapshotData[CSnapshot::MAX_SIZE];
+	class CSnapshotDelta *m_pSnapshotDelta;
+	
+	void WriteTickMarker(int Tick, int Keyframe);
+	void Write(int Type, const void *pData, int Size);
+public:
+	CDemoRecorder(class CSnapshotDelta *pSnapshotDelta);
+	
+	int Start(class IStorage *pStorage, const char *pFilename, const char *pNetversion, const char *pMap, int MapCrc, const char *pType);
+	int Stop();
+
+	void RecordSnapshot(int Tick, const void *pData, int Size);
+	void RecordMessage(const void *pData, int Size);
+
+	bool IsRecording() const { return m_File != 0; }
+};
+
+class CDemoPlayer : public IDemoPlayer
+{
+public:
+	class IListner
+	{
+	public:
+		virtual void OnDemoPlayerSnapshot(void *pData, int Size) = 0;
+		virtual void OnDemoPlayerMessage(void *pData, int Size) = 0;
+	};
+	
+	struct CPlaybackInfo
+	{
+		CDemoHeader m_Header;
+		
+		IDemoPlayer::CInfo m_Info;
+
+		int64 m_LastUpdate;
+		int64 m_CurrentTime;
+		
+		int m_SeekablePoints;
+		
+		int m_NextTick;
+		int m_PreviousTick;
+		
+		float m_IntraTick;
+		float m_TickTime;
+	};
+
+private:
+	IListner *m_pListner;
+
+
+	// Playback
+	struct CKeyFrame
+	{
+		long m_Filepos;
+		int m_Tick;
+	};
+		
+	struct CKeyFrameSearch
+	{
+		CKeyFrame m_Frame;
+		CKeyFrameSearch *m_pNext;
+	};	
+
+	IOHANDLE m_File;
+	CKeyFrame *m_pKeyFrames;
+
+	CPlaybackInfo m_Info;
+	unsigned char m_aLastSnapshotData[CSnapshot::MAX_SIZE];
+	int m_LastSnapshotDataSize;
+	class CSnapshotDelta *m_pSnapshotDelta;
+
+	int ReadChunkHeader(int *pType, int *pSize, int *pTick);
+	void DoTick();
+	void ScanFile();
+	int NextFrame();
+
+public:
+	
+	CDemoPlayer(class CSnapshotDelta *m_pSnapshotDelta);
+	
+	void SetListner(IListner *pListner);
+		
+	int Load(class IStorage *pStorage, const char *pFilename);
+	int Play();
+	void Pause();
+	void Unpause();
+	int Stop();	
+	void SetSpeed(float Speed);
+	int SetPos(float Precent);
+	const CInfo *BaseInfo() const { return &m_Info.m_Info; }
+	
+	int Update();
+	
+	const CPlaybackInfo *Info() const { return &m_Info; }
+	int IsPlaying() const { return m_File != 0; }
+};
+
+#endif
diff --git a/src/engine/shared/engine.cpp b/src/engine/shared/engine.cpp
new file mode 100644
index 00000000..5cd50cf0
--- /dev/null
+++ b/src/engine/shared/engine.cpp
@@ -0,0 +1,76 @@
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+
+#include <base/system.h>
+
+#include <engine/shared/config.h>
+#include <engine/shared/engine.h>
+#include <engine/shared/network.h>
+#include <engine/console.h>
+#include "linereader.h"
+
+// compiled-in data-dir path
+#define DATA_DIR "data"
+
+//static int engine_find_datadir(char *argv0);
+/*
+static void con_dbg_dumpmem(IConsole::IResult *result, void *user_data)
+{
+	mem_debug_dump();
+}
+
+static void con_dbg_lognetwork(IConsole::IResult *result, void *user_data)
+{
+	CNetBase::OpenLog("network_sent.dat", "network_recv.dat");
+}*/
+
+/*
+static char application_save_path[512] = {0};
+static char datadir[512] = {0};
+
+const char *engine_savepath(const char *filename, char *buffer, int max)
+{
+	str_format(buffer, max, "%s/%s", application_save_path, filename);
+	return buffer;
+}*/
+
+void CEngine::Init(const char *pAppname)
+{
+	dbg_logger_stdout();
+	dbg_logger_debugger();
+	
+	//
+	dbg_msg("engine", "running on %s-%s-%s", CONF_FAMILY_STRING, CONF_PLATFORM_STRING, CONF_ARCH_STRING);
+#ifdef CONF_ARCH_ENDIAN_LITTLE
+	dbg_msg("engine", "arch is little endian");
+#elif defined(CONF_ARCH_ENDIAN_BIG)
+	dbg_msg("engine", "arch is big endian");
+#else
+	dbg_msg("engine", "unknown endian");
+#endif
+
+	// init the network
+	net_init();
+	CNetBase::Init();
+	
+	m_HostLookupPool.Init(1);
+
+	//MACRO_REGISTER_COMMAND("dbg_dumpmem", "", CFGFLAG_SERVER|CFGFLAG_CLIENT, con_dbg_dumpmem, 0x0, "Dump the memory");
+	//MACRO_REGISTER_COMMAND("dbg_lognetwork", "", CFGFLAG_SERVER|CFGFLAG_CLIENT, con_dbg_lognetwork, 0x0, "Log the network");
+	
+	// reset the config
+	//config_reset();
+}
+
+
+static int HostLookupThread(void *pUser)
+{
+	CHostLookup *pLookup = (CHostLookup *)pUser;
+	net_host_lookup(pLookup->m_aHostname, &pLookup->m_Addr, NETTYPE_IPV4);
+	return 0;
+}
+
+void CEngine::HostLookup(CHostLookup *pLookup, const char *pHostname)
+{
+	str_copy(pLookup->m_aHostname, pHostname, sizeof(pLookup->m_aHostname));
+	m_HostLookupPool.Add(&pLookup->m_Job, HostLookupThread, pLookup);
+}
diff --git a/src/engine/shared/engine.h b/src/engine/shared/engine.h
new file mode 100644
index 00000000..ad266ae4
--- /dev/null
+++ b/src/engine/shared/engine.h
@@ -0,0 +1,23 @@
+#ifndef ENGINE_SHARED_E_ENGINE_H
+#define ENGINE_SHARED_E_ENGINE_H
+
+#include "jobs.h"
+
+class CHostLookup
+{
+public:
+	CJob m_Job;
+	char m_aHostname[128];
+	NETADDR m_Addr;
+};
+
+class CEngine
+{
+	class CJobPool m_HostLookupPool;
+
+public:
+	void Init(const char *pAppname);
+	void HostLookup(CHostLookup *pLookup, const char *pHostname);
+};
+
+#endif
diff --git a/src/engine/shared/huffman.cpp b/src/engine/shared/huffman.cpp
new file mode 100644
index 00000000..8b0c1cd0
--- /dev/null
+++ b/src/engine/shared/huffman.cpp
@@ -0,0 +1,276 @@
+#include <base/system.h>
+#include "huffman.h"
+
+struct CHuffmanConstructNode
+{
+	unsigned short m_NodeId;
+ 	int m_Frequency;
+};
+
+void CHuffman::Setbits_r(CNode *pNode, int Bits, int Depth)
+{
+	if(pNode->m_aLeafs[1] != 0xffff)
+		Setbits_r(&m_aNodes[pNode->m_aLeafs[1]], Bits|(1<<Depth), Depth+1);
+	if(pNode->m_aLeafs[0] != 0xffff)
+		Setbits_r(&m_aNodes[pNode->m_aLeafs[0]], Bits, Depth+1);
+		
+	if(pNode->m_NumBits)
+	{
+		pNode->m_Bits = Bits;
+		pNode->m_NumBits = Depth;
+	}
+}
+
+// TODO: this should be something faster, but it's enough for now
+static void BubbleSort(CHuffmanConstructNode **ppList, int Size)
+{
+	int Changed = 1;
+	CHuffmanConstructNode *pTemp;
+	
+	while(Changed)
+	{
+		Changed = 0;
+		for(int i = 0; i < Size-1; i++)
+		{
+			if(ppList[i]->m_Frequency < ppList[i+1]->m_Frequency)
+			{
+				pTemp = ppList[i];
+				ppList[i] = ppList[i+1];
+				ppList[i+1] = pTemp;
+				Changed = 1;
+			}
+		}
+	}
+}
+
+void CHuffman::ConstructTree(const unsigned *pFrequencies)
+{
+	CHuffmanConstructNode aNodesLeftStorage[HUFFMAN_MAX_SYMBOLS];
+	CHuffmanConstructNode *apNodesLeft[HUFFMAN_MAX_SYMBOLS];
+	int NumNodesLeft = HUFFMAN_MAX_SYMBOLS;
+
+	// add the symbols
+	for(int i = 0; i < HUFFMAN_MAX_SYMBOLS; i++)
+	{
+		m_aNodes[i].m_NumBits = -1;
+		m_aNodes[i].m_Symbol = i;
+		m_aNodes[i].m_aLeafs[0] = -1;
+		m_aNodes[i].m_aLeafs[1] = -1;
+
+		if(i == HUFFMAN_EOF_SYMBOL)
+			aNodesLeftStorage[i].m_Frequency = 1;
+		else
+			aNodesLeftStorage[i].m_Frequency = pFrequencies[i];
+		aNodesLeftStorage[i].m_NodeId = i;
+		apNodesLeft[i] = &aNodesLeftStorage[i];
+
+	}
+	
+	m_NumNodes = HUFFMAN_MAX_SYMBOLS;
+	
+	// construct the table
+	while(NumNodesLeft > 1)
+	{
+		// we can't rely on stdlib's qsort for this, it can generate different results on different implementations
+		BubbleSort(apNodesLeft, NumNodesLeft);
+		
+		m_aNodes[m_NumNodes].m_NumBits = 0;
+		m_aNodes[m_NumNodes].m_aLeafs[0] = apNodesLeft[NumNodesLeft-1]->m_NodeId;
+		m_aNodes[m_NumNodes].m_aLeafs[1] = apNodesLeft[NumNodesLeft-2]->m_NodeId;
+		apNodesLeft[NumNodesLeft-2]->m_NodeId = m_NumNodes;
+		apNodesLeft[NumNodesLeft-2]->m_Frequency = apNodesLeft[NumNodesLeft-1]->m_Frequency + apNodesLeft[NumNodesLeft-2]->m_Frequency;
+
+		m_NumNodes++;
+		NumNodesLeft--;
+	}
+
+	// set start node
+	m_pStartNode = &m_aNodes[m_NumNodes-1];
+	
+	// build symbol bits
+	Setbits_r(m_pStartNode, 0, 0);
+}
+
+void CHuffman::Init(const unsigned *pFrequencies)
+{
+	int i;
+
+	// make sure to cleanout every thing
+	mem_zero(this, sizeof(*this));
+
+	// construct the tree
+	ConstructTree(pFrequencies);
+
+	// build decode LUT
+	for(i = 0; i < HUFFMAN_LUTSIZE; i++)
+	{
+		unsigned Bits = i;
+		int k;
+		CNode *pNode = m_pStartNode;
+		for(k = 0; k < HUFFMAN_LUTBITS; k++)
+		{
+			pNode = &m_aNodes[pNode->m_aLeafs[Bits&1]];
+			Bits >>= 1;
+
+			if(!pNode)
+				break;
+
+			if(pNode->m_NumBits)
+			{
+				m_apDecodeLut[i] = pNode;
+				break;
+			}
+		}
+
+		if(k == HUFFMAN_LUTBITS)
+			m_apDecodeLut[i] = pNode;
+	}
+
+}
+
+//***************************************************************
+int CHuffman::Compress(const void *pInput, int InputSize, void *pOutput, int OutputSize)
+{
+	// this macro loads a symbol for a byte into bits and bitcount
+#define HUFFMAN_MACRO_LOADSYMBOL(Sym) \
+	Bits |= m_aNodes[Sym].m_Bits << Bitcount; \
+	Bitcount += m_aNodes[Sym].m_NumBits;
+
+	// this macro writes the symbol stored in bits and bitcount to the dst pointer
+#define HUFFMAN_MACRO_WRITE() \
+	while(Bitcount >= 8) \
+	{ \
+		*pDst++ = (unsigned char)(Bits&0xff); \
+		if(pDst == pDstEnd) \
+			return -1; \
+		Bits >>= 8; \
+		Bitcount -= 8; \
+	}
+
+	// setup buffer pointers
+	const unsigned char *pSrc = (const unsigned char *)pInput;
+	const unsigned char *pSrcEnd = pSrc + InputSize;
+	unsigned char *pDst = (unsigned char *)pOutput;
+	unsigned char *pDstEnd = pDst + OutputSize;
+
+	// symbol variables
+	unsigned Bits = 0;
+	unsigned Bitcount = 0;
+
+	// make sure that we have data that we want to compress
+	if(InputSize)
+	{
+		// {A} load the first symbol
+		int Symbol = *pSrc++;
+
+		while(pSrc != pSrcEnd)
+		{
+			// {B} load the symbol
+			HUFFMAN_MACRO_LOADSYMBOL(Symbol)
+
+			// {C} fetch next symbol, this is done here because it will reduce dependency in the code
+			Symbol = *pSrc++;
+
+			// {B} write the symbol loaded at
+			HUFFMAN_MACRO_WRITE()
+		}
+
+		// write the last symbol loaded from {C} or {A} in the case of only 1 byte input buffer
+		HUFFMAN_MACRO_LOADSYMBOL(Symbol)
+		HUFFMAN_MACRO_WRITE()
+	}
+
+	// write EOF symbol
+	HUFFMAN_MACRO_LOADSYMBOL(HUFFMAN_EOF_SYMBOL)
+	HUFFMAN_MACRO_WRITE()
+
+	// write out the last bits
+	*pDst++ = Bits;
+
+	// return the size of the output
+	return (int)(pDst - (const unsigned char *)pOutput);
+
+	// remove macros
+#undef HUFFMAN_MACRO_LOADSYMBOL
+#undef HUFFMAN_MACRO_WRITE
+}
+
+//***************************************************************
+int CHuffman::Decompress(const void *pInput, int InputSize, void *pOutput, int OutputSize)
+{
+	// setup buffer pointers
+	unsigned char *pDst = (unsigned char *)pOutput;
+	unsigned char *pSrc = (unsigned char *)pInput;
+	unsigned char *pDstEnd = pDst + OutputSize;
+	unsigned char *pSrcEnd = pSrc + InputSize;
+
+	unsigned Bits = 0;
+	unsigned Bitcount = 0;
+
+	CNode *pEof = &m_aNodes[HUFFMAN_EOF_SYMBOL];
+	CNode *pNode = 0;
+
+	while(1)
+	{
+		// {A} try to load a node now, this will reduce dependency at location {D}
+		pNode = 0;
+		if(Bitcount >= HUFFMAN_LUTBITS)
+			pNode = m_apDecodeLut[Bits&HUFFMAN_LUTMASK];
+
+		// {B} fill with new bits
+		while(Bitcount < 24 && pSrc != pSrcEnd)
+		{
+			Bits |= (*pSrc++) << Bitcount;
+			Bitcount += 8;
+		}
+
+		// {C} load symbol now if we didn't that earlier at location {A}
+		if(!pNode)
+			pNode = m_apDecodeLut[Bits&HUFFMAN_LUTMASK];
+
+		// {D} check if we hit a symbol already
+		if(pNode->m_NumBits)
+		{
+			// remove the bits for that symbol
+			Bits >>= pNode->m_NumBits;
+			Bitcount -= pNode->m_NumBits;
+		}
+		else
+		{
+			// remove the bits that the lut checked up for us
+			Bits >>= HUFFMAN_LUTBITS;
+			Bitcount -= HUFFMAN_LUTBITS;
+
+			// walk the tree bit by bit
+			while(1)
+			{
+				// traverse tree
+				pNode = &m_aNodes[pNode->m_aLeafs[Bits&1]];
+
+				// remove bit
+				Bitcount--;
+				Bits >>= 1;
+
+				// check if we hit a symbol
+				if(pNode->m_NumBits)
+					break;
+
+				// no more bits, decoding error
+				if(Bitcount == 0)
+					return -1;
+			}
+		}
+
+		// check for eof
+		if(pNode == pEof)
+			break;
+
+		// output character
+		if(pDst == pDstEnd)
+			return -1;
+		*pDst++ = pNode->m_Symbol;
+	}
+
+	// return the size of the decompressed buffer
+	return (int)(pDst - (const unsigned char *)pOutput);
+}
diff --git a/src/engine/shared/huffman.h b/src/engine/shared/huffman.h
new file mode 100644
index 00000000..5aa56c8f
--- /dev/null
+++ b/src/engine/shared/huffman.h
@@ -0,0 +1,89 @@
+#ifndef ENGINE_SHARED_HUFFMAN_H
+#define ENGINE_SHARED_HUFFMAN_H
+
+
+
+class CHuffman
+{
+	enum
+	{
+		HUFFMAN_EOF_SYMBOL = 256,
+
+		HUFFMAN_MAX_SYMBOLS=HUFFMAN_EOF_SYMBOL+1,
+		HUFFMAN_MAX_NODES=HUFFMAN_MAX_SYMBOLS*2-1,
+		
+		HUFFMAN_LUTBITS = 10,
+		HUFFMAN_LUTSIZE = (1<<HUFFMAN_LUTBITS),
+		HUFFMAN_LUTMASK = (HUFFMAN_LUTSIZE-1)
+	};
+
+	struct CNode
+	{
+		// symbol
+		unsigned m_Bits;
+		unsigned m_NumBits;
+
+		// don't use pointers for this. shorts are smaller so we can fit more data into the cache
+		unsigned short m_aLeafs[2];
+
+		// what the symbol represents
+		unsigned char m_Symbol;
+	};
+
+	CNode m_aNodes[HUFFMAN_MAX_NODES];
+	CNode *m_apDecodeLut[HUFFMAN_LUTSIZE];
+	CNode *m_pStartNode;
+	int m_NumNodes;
+	
+	void Setbits_r(CNode *pNode, int Bits, int Depth);
+	void ConstructTree(const unsigned *pFrequencies);
+	
+public:
+	/*
+		Function: huffman_init
+			Inits the compressor/decompressor.
+
+		Parameters:
+			huff - Pointer to the state to init
+			frequencies - A pointer to an array of 256 entries of the frequencies of the bytes
+
+		Remarks:
+			- Does no allocation what so ever.
+			- You don't have to call any cleanup functions when you are done with it
+	*/
+	void Init(const unsigned *pFrequencies);
+
+	/*
+		Function: huffman_compress
+			Compresses a buffer and outputs a compressed buffer.
+
+		Parameters:
+			huff - Pointer to the huffman state
+			input - Buffer to compress
+			input_size - Size of the buffer to compress
+			output - Buffer to put the compressed data into
+			output_size - Size of the output buffer
+
+		Returns:
+			Returns the size of the compressed data. Negative value on failure.
+	*/
+	int Compress(const void *pInput, int InputSize, void *pOutput, int OutputSize);
+
+	/*
+		Function: huffman_decompress
+			Decompresses a buffer
+
+		Parameters:
+			huff - Pointer to the huffman state
+			input - Buffer to decompress
+			input_size - Size of the buffer to decompress
+			output - Buffer to put the uncompressed data into
+			output_size - Size of the output buffer
+
+		Returns:
+			Returns the size of the uncompressed data. Negative value on failure.
+	*/
+	int Decompress(const void *pInput, int InputSize, void *pOutput, int OutputSize);
+	
+};
+#endif // __HUFFMAN_HEADER__
diff --git a/src/engine/shared/jobs.cpp b/src/engine/shared/jobs.cpp
new file mode 100644
index 00000000..83d7290b
--- /dev/null
+++ b/src/engine/shared/jobs.cpp
@@ -0,0 +1,74 @@
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+#include <base/system.h>
+#include "jobs.h"
+
+CJobPool::CJobPool()
+{
+	// empty the pool
+	m_Lock = lock_create();
+	m_pFirstJob = 0;
+	m_pLastJob = 0;
+}
+
+void CJobPool::WorkerThread(void *pUser)
+{
+	CJobPool *pPool = (CJobPool *)pUser;
+	
+	while(1)
+	{
+		CJob *pJob = 0;
+		
+		// fetch job from queue
+		lock_wait(pPool->m_Lock);
+		if(pPool->m_pFirstJob)
+		{
+			pJob = pPool->m_pFirstJob;
+			pPool->m_pFirstJob = pPool->m_pFirstJob->m_pNext;
+			if(pPool->m_pFirstJob)
+				pPool->m_pFirstJob->m_pPrev = 0;
+			else
+				pPool->m_pLastJob = 0;
+		}
+		lock_release(pPool->m_Lock);
+		
+		// do the job if we have one
+		if(pJob)
+		{
+			pJob->m_Status = CJob::STATE_RUNNING;
+			pJob->m_Result = pJob->m_pfnFunc(pJob->m_pFuncData);
+			pJob->m_Status = CJob::STATE_DONE;
+		}
+		else
+			thread_sleep(10);
+	}
+	
+}
+
+int CJobPool::Init(int NumThreads)
+{
+	// start threads
+	for(int i = 0; i < NumThreads; i++)
+		thread_create(WorkerThread, this);
+	return 0;
+}
+
+int CJobPool::Add(CJob *pJob, JOBFUNC pfnFunc, void *pData)
+{
+	mem_zero(pJob, sizeof(CJob));
+	pJob->m_pfnFunc = pfnFunc;
+	pJob->m_pFuncData = pData;
+	
+	lock_wait(m_Lock);
+	
+	// add job to queue
+	pJob->m_pPrev = m_pLastJob;
+	if(m_pLastJob)
+		m_pLastJob->m_pNext = pJob;
+	m_pLastJob = pJob;
+	if(!m_pFirstJob)
+		m_pFirstJob = pJob;
+	
+	lock_release(m_Lock);
+	return 0;
+}
+
diff --git a/src/engine/shared/jobs.h b/src/engine/shared/jobs.h
new file mode 100644
index 00000000..d04815b0
--- /dev/null
+++ b/src/engine/shared/jobs.h
@@ -0,0 +1,51 @@
+#ifndef ENGINE_SHARED_JOBS_H
+#define ENGINE_SHARED_JOBS_H
+typedef int (*JOBFUNC)(void *pData);
+
+class CJobPool;
+
+class CJob
+{
+	friend class CJobPool;
+	
+	CJobPool *m_pPool;
+	CJob *m_pPrev;
+	CJob *m_pNext;
+	
+	volatile int m_Status;
+	volatile int m_Result;
+	
+	JOBFUNC m_pfnFunc;
+	void *m_pFuncData;
+public:
+	CJob()
+	{
+		m_Status = STATE_DONE;
+		m_pFuncData = 0;
+	}
+	
+	enum
+	{
+		STATE_PENDING=0,
+		STATE_RUNNING,
+		STATE_DONE
+	};
+	
+	int Status() const { return m_Status; }
+};
+
+class CJobPool
+{
+	LOCK m_Lock;
+	CJob *m_pFirstJob;
+	CJob *m_pLastJob;
+	
+	static void WorkerThread(void *pUser);
+	
+public:
+	CJobPool();
+	
+	int Init(int NumThreads);
+	int Add(CJob *pJob, JOBFUNC pfnFunc, void *pData);
+};
+#endif
diff --git a/src/engine/shared/kernel.cpp b/src/engine/shared/kernel.cpp
new file mode 100644
index 00000000..9f6850ba
--- /dev/null
+++ b/src/engine/shared/kernel.cpp
@@ -0,0 +1,93 @@
+#include <base/system.h>
+#include <engine/kernel.h>
+
+class CKernel : public IKernel
+{
+	enum
+	{
+		MAX_INTERFACES=32,
+	};
+	
+	class CInterfaceInfo
+	{
+	public:
+		CInterfaceInfo()
+		{
+			m_aName[0] = 0;
+			m_pInterface = 0x0;
+		}
+		
+		char m_aName[64];
+		IInterface *m_pInterface;
+	};
+
+	CInterfaceInfo m_aInterfaces[MAX_INTERFACES];
+	int m_NumInterfaces;
+	
+	CInterfaceInfo *FindInterfaceInfo(const char *pName)
+	{
+		for(int i = 0; i < m_NumInterfaces; i++)
+		{
+			if(str_comp(pName, m_aInterfaces[i].m_aName) == 0)
+				return &m_aInterfaces[i];
+		}
+		return 0x0;
+	}
+	
+public:
+
+	CKernel()
+	{
+		m_NumInterfaces = 0;
+	}
+
+
+	virtual bool RegisterInterfaceImpl(const char *pName, IInterface *pInterface)
+	{
+		// TODO: More error checks here
+		if(m_NumInterfaces == MAX_INTERFACES)
+		{
+			dbg_msg("kernel", "ERROR: couldn't register interface '%s'. maximum of interfaces reached", pName);
+			return false;
+		}
+			
+		if(FindInterfaceInfo(pName) != 0)
+		{
+			dbg_msg("kernel", "ERROR: couldn't register interface '%s'. interface already exists");
+			return false;
+		}
+		
+		pInterface->m_pKernel = this;
+		m_aInterfaces[m_NumInterfaces].m_pInterface = pInterface;
+		str_copy(m_aInterfaces[m_NumInterfaces].m_aName, pName, sizeof(m_aInterfaces[m_NumInterfaces].m_aName));
+		m_NumInterfaces++;
+		
+		return true;
+	}
+
+	virtual bool ReregisterInterfaceImpl(const char *pName, IInterface *pInterface)
+	{
+		if(FindInterfaceInfo(pName) == 0)
+		{
+			dbg_msg("kernel", "ERROR: couldn't reregister interface '%s'. interface doesn't exist");
+			return false;
+		}
+		
+		pInterface->m_pKernel = this;
+		
+		return true;
+	}
+	
+	virtual IInterface *RequestInterfaceImpl(const char *pName)
+	{
+		CInterfaceInfo *pInfo = FindInterfaceInfo(pName);
+		if(!pInfo)
+		{
+			dbg_msg("kernel", "failed to find interface with the name '%s'", pName);
+			return 0;
+		}
+		return pInfo->m_pInterface;
+	}
+};
+
+IKernel *IKernel::Create() { return new CKernel; }
diff --git a/src/engine/shared/linereader.cpp b/src/engine/shared/linereader.cpp
new file mode 100644
index 00000000..b3de233b
--- /dev/null
+++ b/src/engine/shared/linereader.cpp
@@ -0,0 +1,62 @@
+#include "linereader.h"
+
+void CLineReader::Init(IOHANDLE io)
+{
+	m_BufferMaxSize = 4*1024;
+	m_BufferSize = 0;
+	m_BufferPos = 0;
+	m_IO = io;
+}
+
+char *CLineReader::Get()
+{
+	unsigned LineStart = m_BufferPos;
+
+	while(1)
+	{
+		if(m_BufferPos >= m_BufferSize)
+		{
+			// fetch more
+
+			// move the remaining part to the front
+			unsigned Read;
+			unsigned Left = m_BufferSize - LineStart;
+
+			if(LineStart > m_BufferSize)
+				Left = 0;
+			if(Left)
+				mem_move(m_aBuffer, &m_aBuffer[LineStart], Left);
+			m_BufferPos = Left;
+
+			// fill the buffer
+			Read = io_read(m_IO, &m_aBuffer[m_BufferPos], m_BufferMaxSize-m_BufferPos);
+			m_BufferSize = Left + Read;
+			LineStart = 0;
+
+			if(!Read)
+			{
+				if(Left)
+				{
+					m_aBuffer[Left] = 0; // return the last line
+					m_BufferPos = Left;
+					m_BufferSize = Left;
+					return m_aBuffer;
+				}
+				else
+					return 0x0; // we are done!
+			}
+		}
+		else
+		{
+			if(m_aBuffer[m_BufferPos] == '\n' || m_aBuffer[m_BufferPos] == '\r')
+			{
+				// line found
+				m_aBuffer[m_BufferPos] = 0;
+				m_BufferPos++;
+				return &m_aBuffer[LineStart];
+			}
+			else
+				m_BufferPos++;
+		}
+	}
+}
diff --git a/src/engine/shared/linereader.h b/src/engine/shared/linereader.h
new file mode 100644
index 00000000..f28d42f6
--- /dev/null
+++ b/src/engine/shared/linereader.h
@@ -0,0 +1,17 @@
+#ifndef ENGINE_SHARED_LINEREADER_H
+#define ENGINE_SHARED_LINEREADER_H
+#include <base/system.h>
+
+// buffered stream for reading lines, should perhaps be something smaller
+class CLineReader
+{
+	char m_aBuffer[4*1024];
+	unsigned m_BufferPos;
+	unsigned m_BufferSize;
+	unsigned m_BufferMaxSize;
+	IOHANDLE m_IO;
+public:
+	void Init(IOHANDLE IoHandle);
+	char *Get();
+};
+#endif
diff --git a/src/engine/shared/map.cpp b/src/engine/shared/map.cpp
new file mode 100644
index 00000000..505d18e9
--- /dev/null
+++ b/src/engine/shared/map.cpp
@@ -0,0 +1,45 @@
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+#include <base/system.h>
+#include <engine/map.h>
+#include <engine/storage.h>
+#include "datafile.h"
+
+class CMap : public IEngineMap
+{
+	CDataFileReader m_DataFile;
+public:
+	CMap() {}
+	
+	virtual void *GetData(int Index) { return m_DataFile.GetData(Index); }
+	virtual void *GetDataSwapped(int Index) { return m_DataFile.GetDataSwapped(Index); }
+	virtual void UnloadData(int Index) { m_DataFile.UnloadData(Index); }
+	virtual void *GetItem(int Index, int *pType, int *pId) { return m_DataFile.GetItem(Index, pType, pId); }
+	virtual void GetType(int Type, int *pStart, int *pNum) { m_DataFile.GetType(Type, pStart, pNum); }
+	virtual void *FindItem(int Type, int Id) { return m_DataFile.FindItem(Type, Id); }
+	virtual int NumItems() { return m_DataFile.NumItems(); }
+	
+	virtual void Unload()
+	{
+		m_DataFile.Close();
+	}
+
+	virtual bool Load(const char *pMapName)
+	{
+		IStorage *pStorage = Kernel()->RequestInterface<IStorage>();
+		if(!pStorage)
+			return false;
+		return m_DataFile.Open(pStorage, pMapName);
+	}
+	
+	virtual bool IsLoaded()
+	{
+		return m_DataFile.IsOpen();
+	}
+	
+	virtual unsigned Crc()
+	{
+		return m_DataFile.Crc();
+	}
+};
+
+extern IEngineMap *CreateEngineMap() { return new CMap; }
diff --git a/src/engine/shared/masterserver.cpp b/src/engine/shared/masterserver.cpp
new file mode 100644
index 00000000..beade5bf
--- /dev/null
+++ b/src/engine/shared/masterserver.cpp
@@ -0,0 +1,187 @@
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+#include <stdio.h>
+
+#include <base/system.h>
+#include <engine/masterserver.h>
+#include <engine/storage.h>
+#include "engine.h"
+#include "linereader.h"
+
+class CMasterServer : public IEngineMasterServer
+{
+public:
+	// master server functions
+	struct CMasterInfo
+	{
+		char m_aHostname[128];
+		NETADDR m_Addr;
+		
+		CHostLookup m_Lookup;
+	} ;
+
+	CMasterInfo m_aMasterServers[MAX_MASTERSERVERS];
+	int m_NeedsUpdate;
+	CEngine *m_pEngine;
+	
+	CMasterServer()
+	{
+		SetDefault();
+		m_NeedsUpdate = -1;
+		m_pEngine = 0;
+	}
+
+	virtual int RefreshAddresses()
+	{
+		int i;
+		
+		if(m_NeedsUpdate != -1)
+			return 0;
+		
+		dbg_msg("engine/mastersrv", "refreshing master server addresses");
+
+		// add lookup jobs
+		for(i = 0; i < MAX_MASTERSERVERS; i++)	
+			m_pEngine->HostLookup(&m_aMasterServers[i].m_Lookup, m_aMasterServers[i].m_aHostname);
+		
+		m_NeedsUpdate = 1;
+		return 0;
+	}
+
+	virtual void Update()
+	{
+		// check if we need to update
+		if(m_NeedsUpdate != 1)
+			return;
+		m_NeedsUpdate = 0;
+		
+		for(int i = 0; i < MAX_MASTERSERVERS; i++)
+		{
+			if(m_aMasterServers[i].m_Lookup.m_Job.Status() != CJob::STATE_DONE)
+				m_NeedsUpdate = 1;
+			else
+			{
+				m_aMasterServers[i].m_Addr = m_aMasterServers[i].m_Lookup.m_Addr;
+				m_aMasterServers[i].m_Addr.port = 8300;
+			}
+		}
+		
+		if(!m_NeedsUpdate)
+		{
+			dbg_msg("engine/mastersrv", "saving addresses");
+			Save();
+		}
+	}
+
+	virtual int IsRefreshing()
+	{
+		return m_NeedsUpdate;
+	}
+
+	virtual NETADDR GetAddr(int Index) 
+	{
+		return m_aMasterServers[Index].m_Addr;
+	}
+
+	virtual const char *GetName(int Index) 
+	{
+		return m_aMasterServers[Index].m_aHostname;
+	}
+
+	virtual void DumpServers()
+	{
+		for(int i = 0; i < MAX_MASTERSERVERS; i++)
+		{
+			dbg_msg("mastersrv", "#%d = %d.%d.%d.%d", i,
+				m_aMasterServers[i].m_Addr.ip[0], m_aMasterServers[i].m_Addr.ip[1],
+				m_aMasterServers[i].m_Addr.ip[2], m_aMasterServers[i].m_Addr.ip[3]);
+		}
+	}
+
+	virtual void Init(class CEngine *pEngine)
+	{
+		m_pEngine = pEngine;
+	}
+
+	virtual void SetDefault()
+	{
+		mem_zero(m_aMasterServers, sizeof(m_aMasterServers));
+		for(int i = 0; i < MAX_MASTERSERVERS; i++)
+			str_format(m_aMasterServers[i].m_aHostname, sizeof(m_aMasterServers[i].m_aHostname), "master%d.teeworlds.com", i+1);
+	}
+
+	virtual int Load()
+	{
+		CLineReader LineReader;
+		IOHANDLE File;
+		int Count = 0;
+		IStorage *pStorage = Kernel()->RequestInterface<IStorage>();
+		if(!pStorage)
+			return -1;
+		
+		// try to open file
+		File = pStorage->OpenFile("masters.cfg", IOFLAG_READ);
+		if(!File)
+			return -1;
+		
+		LineReader.Init(File);
+		while(1)
+		{
+			CMasterInfo Info = {{0}};
+			int aIp[4];
+			const char *pLine = LineReader.Get();
+			if(!pLine)
+				break;
+
+			// parse line	
+			if(sscanf(pLine, "%s %d.%d.%d.%d", Info.m_aHostname, &aIp[0], &aIp[1], &aIp[2], &aIp[3]) == 5)
+			{
+				Info.m_Addr.ip[0] = (unsigned char)aIp[0];
+				Info.m_Addr.ip[1] = (unsigned char)aIp[1];
+				Info.m_Addr.ip[2] = (unsigned char)aIp[2];
+				Info.m_Addr.ip[3] = (unsigned char)aIp[3];
+				Info.m_Addr.port = 8300;
+				if(Count != MAX_MASTERSERVERS)
+				{
+					m_aMasterServers[Count] = Info;
+					Count++;
+				}
+				//else
+				//	dbg_msg("engine/mastersrv", "warning: skipped master server '%s' due to limit of %d", pLine, MAX_MASTERSERVERS);
+			}
+			//else
+			//	dbg_msg("engine/mastersrv", "warning: couldn't parse master server '%s'", pLine);
+		}
+		
+		io_close(File);
+		return 0;
+	}
+
+	virtual int Save()
+	{
+		IOHANDLE File;
+
+		IStorage *pStorage = Kernel()->RequestInterface<IStorage>();
+		if(!pStorage)
+			return -1;
+			
+		// try to open file
+		File = pStorage->OpenFile("masters.cfg", IOFLAG_WRITE);
+		if(!File)
+			return -1;
+
+		for(int i = 0; i < MAX_MASTERSERVERS; i++)
+		{
+			char aBuf[1024];
+			str_format(aBuf, sizeof(aBuf), "%s %d.%d.%d.%d\n", m_aMasterServers[i].m_aHostname,
+				m_aMasterServers[i].m_Addr.ip[0], m_aMasterServers[i].m_Addr.ip[1],
+				m_aMasterServers[i].m_Addr.ip[2], m_aMasterServers[i].m_Addr.ip[3]);
+				
+			io_write(File, aBuf, str_length(aBuf));
+		}
+		
+		io_close(File);
+		return 0;
+	}
+};
+
+IEngineMasterServer *CreateEngineMasterServer() { return new CMasterServer; }
diff --git a/src/engine/shared/memheap.cpp b/src/engine/shared/memheap.cpp
new file mode 100644
index 00000000..6661962b
--- /dev/null
+++ b/src/engine/shared/memheap.cpp
@@ -0,0 +1,96 @@
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+#include <base/system.h>
+#include "memheap.h"
+
+static const int CHUNK_SIZE = 1024*64;
+
+// allocates a new chunk to be used
+void CHeap::NewChunk()
+{
+	CChunk *pChunk;
+	char *pMem;
+	
+	// allocate memory
+	pMem = (char*)mem_alloc(sizeof(CChunk)+CHUNK_SIZE, 1);
+	if(!pMem)
+		return;
+
+	// the chunk structure is located in the begining of the chunk
+	// init it and return the chunk
+	pChunk = (CChunk*)pMem;
+	pChunk->m_pMemory = (char*)(pChunk+1);
+	pChunk->m_pCurrent = pChunk->m_pMemory;
+	pChunk->m_pEnd = pChunk->m_pMemory + CHUNK_SIZE;
+	pChunk->m_pNext = (CChunk *)0x0;
+
+	pChunk->m_pNext = m_pCurrent;
+	m_pCurrent = pChunk;	
+}
+
+//****************
+void *CHeap::AllocateFromChunk(unsigned int Size)
+{
+	char *pMem;
+	
+	// check if we need can fit the allocation
+	if(m_pCurrent->m_pCurrent + Size > m_pCurrent->m_pEnd)
+		return (void*)0x0;
+
+	// get memory and move the pointer forward
+	pMem = m_pCurrent->m_pCurrent;
+	m_pCurrent->m_pCurrent += Size;
+	return pMem;
+}
+
+// creates a heap
+CHeap::CHeap()
+{
+	m_pCurrent = 0x0;
+	Reset();
+}
+
+CHeap::~CHeap()
+{
+	Clear();
+}
+
+void CHeap::Reset()
+{
+	Clear();
+	NewChunk();
+}
+
+// destroys the heap
+void CHeap::Clear()
+{
+	CChunk *pChunk = m_pCurrent;
+	CChunk *pNext;
+	
+	while(pChunk)
+	{
+		pNext = pChunk->m_pNext;
+		mem_free(pChunk);
+		pChunk = pNext;
+	}
+	
+	m_pCurrent = 0x0;
+}
+
+//
+void *CHeap::Allocate(unsigned Size)
+{
+	char *pMem;
+
+	// try to allocate from current chunk
+	pMem = (char *)AllocateFromChunk(Size);
+	if(!pMem)
+	{
+		// allocate new chunk and add it to the heap
+		NewChunk();
+		
+		// try to allocate again
+		pMem = (char *)AllocateFromChunk(Size);
+	}
+	
+	return pMem;
+}
diff --git a/src/engine/shared/memheap.h b/src/engine/shared/memheap.h
new file mode 100644
index 00000000..706395f2
--- /dev/null
+++ b/src/engine/shared/memheap.h
@@ -0,0 +1,32 @@
+#ifndef ENGINE_SHARED_MEMHEAP_H
+#define ENGINE_SHARED_MEMHEAP_H
+class CHeap
+{
+	struct CChunk
+	{
+		char *m_pMemory;
+		char *m_pCurrent;
+		char *m_pEnd;
+		CChunk *m_pNext;
+	};
+	
+	enum
+	{
+		// how large each chunk should be
+		CHUNK_SIZE = 1025*64,
+	};
+	
+	CChunk *m_pCurrent;
+	
+	
+	void Clear();
+	void NewChunk();
+	void *AllocateFromChunk(unsigned int Size);
+	
+public:
+	CHeap();
+	~CHeap();
+	void Reset();
+	void *Allocate(unsigned Size);
+};
+#endif
diff --git a/src/engine/shared/message.h b/src/engine/shared/message.h
new file mode 100644
index 00000000..4e67a8e1
--- /dev/null
+++ b/src/engine/shared/message.h
@@ -0,0 +1,9 @@
+#ifndef ENGINE_SHARED_MESSAGE_H
+#define ENGINE_SHARED_MESSAGE_H
+class CMessage
+{
+public:
+	virtual bool Pack(void *pData, unsigned MaxDataSize);
+	virtual bool Unpack(const void *pData, unsigned DataSize);
+};
+#endif
diff --git a/src/engine/e_network.cpp b/src/engine/shared/network.cpp
index ac753e50..0305ffff 100644
--- a/src/engine/e_network.cpp
+++ b/src/engine/shared/network.cpp
@@ -1,12 +1,11 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
 #include <base/system.h>
 
-#include <string.h> /* strlen */
 
-#include "e_config.h"
-#include "e_engine.h"
-#include "e_network.h"
-#include "e_huffman.h"
+#include "config.h"
+#include "engine.h"
+#include "network.h"
+#include "huffman.h"
 
 void CNetRecvUnpacker::Clear()
 {
@@ -22,7 +21,7 @@ void CNetRecvUnpacker::Start(const NETADDR *pAddr, CNetConnection *pConnection,
 	m_Valid = true;
 }
 
-/* TODO: rename this function */
+// TODO: rename this function
 int CNetRecvUnpacker::FetchChunk(CNetChunk *pChunk)
 {
 	CNetChunkHeader Header;
@@ -32,21 +31,21 @@ int CNetRecvUnpacker::FetchChunk(CNetChunk *pChunk)
 	{
 		unsigned char *pData = m_Data.m_aChunkData;
 		
-		/* check for old data to unpack */
+		// check for old data to unpack
 		if(!m_Valid || m_CurrentChunk >= m_Data.m_NumChunks)
 		{
 			Clear();
 			return 0;
 		}
 		
-		/* TODO: add checking here so we don't read too far */
+		// TODO: add checking here so we don't read too far
 		for(int i = 0; i < m_CurrentChunk; i++)
 		{
 			pData = Header.Unpack(pData);
 			pData += Header.m_Size;
 		}
 		
-		/* unpack the header */
+		// unpack the header
 		pData = Header.Unpack(pData);
 		m_CurrentChunk++;
 		
@@ -56,29 +55,29 @@ int CNetRecvUnpacker::FetchChunk(CNetChunk *pChunk)
 			return 0;
 		}
 		
-		/* handle sequence stuff */
+		// handle sequence stuff
 		if(m_pConnection && (Header.m_Flags&NET_CHUNKFLAG_VITAL))
 		{
 			if(Header.m_Sequence == (m_pConnection->m_Ack+1)%NET_MAX_SEQUENCE)
 			{
-				/* in sequence */
+				// in sequence
 				m_pConnection->m_Ack = (m_pConnection->m_Ack+1)%NET_MAX_SEQUENCE;
 			}
 			else
 			{
-				/* old packet that we already got */
+				// old packet that we already got
 				if(CNetBase::IsSeqInBackroom(Header.m_Sequence, m_pConnection->m_Ack))
 					continue;
 
-				/* out of sequence, request resend */
-				if(config.debug)
+				// out of sequence, request resend
+				if(g_Config.m_Debug)
 					dbg_msg("conn", "asking for resend %d %d", Header.m_Sequence, (m_pConnection->m_Ack+1)%NET_MAX_SEQUENCE);
 				m_pConnection->SignalResend();
-				continue; /* take the next chunk in the packet */
+				continue; // take the next chunk in the packet
 			}
 		}
 		
-		/* fill in the info */
+		// fill in the info
 		pChunk->m_ClientID = m_ClientID;
 		pChunk->m_Address = m_Addr;
 		pChunk->m_Flags = 0;
@@ -88,7 +87,7 @@ int CNetRecvUnpacker::FetchChunk(CNetChunk *pChunk)
 	}
 }
 
-/* packs the data tight and sends it */
+// packs the data tight and sends it
 void CNetBase::SendPacketConnless(NETSOCKET Socket, NETADDR *pAddr, const void *pData, int DataSize)
 {
 	unsigned char aBuffer[NET_MAX_PACKETSIZE];
@@ -108,20 +107,20 @@ void CNetBase::SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct
 	int CompressedSize = -1;
 	int FinalSize = -1;
 
-	/* log the data */
+	// log the data
 	if(ms_DataLogSent)
 	{
-		int type = 1;
-		io_write(ms_DataLogSent, &type, sizeof(type));
+		int Type = 1;
+		io_write(ms_DataLogSent, &Type, sizeof(Type));
 		io_write(ms_DataLogSent, &pPacket->m_DataSize, sizeof(pPacket->m_DataSize));
 		io_write(ms_DataLogSent, &pPacket->m_aChunkData, pPacket->m_DataSize);
 		io_flush(ms_DataLogSent);
 	}
 	
-	/* compress */
-	CompressedSize = huffman_compress(&ms_HuffmanState, pPacket->m_aChunkData, pPacket->m_DataSize, &aBuffer[3], NET_MAX_PACKETSIZE-4);
+	// compress
+	CompressedSize = ms_Huffman.Compress(pPacket->m_aChunkData, pPacket->m_DataSize, &aBuffer[3], NET_MAX_PACKETSIZE-4);
 
-	/* check if the compression was enabled, successful and good enough	*/
+	// check if the compression was enabled, successful and good enough
 	if(CompressedSize > 0 && CompressedSize < pPacket->m_DataSize)
 	{
 		FinalSize = CompressedSize;
@@ -129,13 +128,13 @@ void CNetBase::SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct
 	}
 	else
 	{
-		/* use uncompressed data */
+		// use uncompressed data
 		FinalSize = pPacket->m_DataSize;
 		mem_copy(&aBuffer[3], pPacket->m_aChunkData, pPacket->m_DataSize);
 		pPacket->m_Flags &= ~NET_PACKETFLAG_COMPRESSION;
 	}
 
-	/* set header and send the packet if all things are good */
+	// set header and send the packet if all things are good
 	if(FinalSize >= 0)
 	{
 		FinalSize += NET_PACKETHEADERSIZE;
@@ -144,11 +143,11 @@ void CNetBase::SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct
 		aBuffer[2] = pPacket->m_NumChunks;
 		net_udp_send(Socket, pAddr, aBuffer, FinalSize);
 
-		/* log raw socket data */
+		// log raw socket data
 		if(ms_DataLogSent)
 		{
-			int type = 0;
-			io_write(ms_DataLogSent, &type, sizeof(type));
+			int Type = 0;
+			io_write(ms_DataLogSent, &Type, sizeof(Type));
 			io_write(ms_DataLogSent, &FinalSize, sizeof(FinalSize));
 			io_write(ms_DataLogSent, aBuffer, FinalSize);
 			io_flush(ms_DataLogSent);
@@ -156,27 +155,27 @@ void CNetBase::SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct
 	}
 }
 
-/* TODO: rename this function */
+// TODO: rename this function
 int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct *pPacket)
 {
-	/* check the size */
+	// check the size
 	if(Size < NET_PACKETHEADERSIZE || Size > NET_MAX_PACKETSIZE)
 	{
 		dbg_msg("", "packet too small, %d", Size);
 		return -1;
 	}
 
-	/* log the data */
+	// log the data
 	if(ms_DataLogRecv)
 	{
-		int type = 0;
-		io_write(ms_DataLogRecv, &type, sizeof(type));
+		int Type = 0;
+		io_write(ms_DataLogRecv, &Type, sizeof(Type));
 		io_write(ms_DataLogRecv, &Size, sizeof(Size));
 		io_write(ms_DataLogRecv, pBuffer, Size);
 		io_flush(ms_DataLogRecv);
 	}
 	
-	/* read the packet */
+	// read the packet
 	pPacket->m_Flags = pBuffer[0]>>4;
 	pPacket->m_Ack = ((pBuffer[0]&0xf)<<8) | pBuffer[1];
 	pPacket->m_NumChunks = pBuffer[2];
@@ -199,30 +198,30 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct
 	else
 	{
 		if(pPacket->m_Flags&NET_PACKETFLAG_COMPRESSION)
-			pPacket->m_DataSize = huffman_decompress(&ms_HuffmanState, &pBuffer[3], pPacket->m_DataSize, pPacket->m_aChunkData, sizeof(pPacket->m_aChunkData));
+			pPacket->m_DataSize = ms_Huffman.Decompress(&pBuffer[3], pPacket->m_DataSize, pPacket->m_aChunkData, sizeof(pPacket->m_aChunkData));
 		else
 			mem_copy(pPacket->m_aChunkData, &pBuffer[3], pPacket->m_DataSize);
 	}
 
-	/* check for errors */	
+	// check for errors
 	if(pPacket->m_DataSize < 0)
 	{
-		if(config.debug)
+		if(g_Config.m_Debug)
 			dbg_msg("network", "error during packet decoding");
 		return -1;
 	}
 
-	/* log the data */
+	// log the data
 	if(ms_DataLogRecv)
 	{
-		int type = 1;
-		io_write(ms_DataLogRecv, &type, sizeof(type));
+		int Type = 1;
+		io_write(ms_DataLogRecv, &Type, sizeof(Type));
 		io_write(ms_DataLogRecv, &pPacket->m_DataSize, sizeof(pPacket->m_DataSize));
 		io_write(ms_DataLogRecv, pPacket->m_aChunkData, pPacket->m_DataSize);
 		io_flush(ms_DataLogRecv);
 	}
 		
-	/* return success */
+	// return success
 	return 0;
 }
 
@@ -237,7 +236,7 @@ void CNetBase::SendControlMsg(NETSOCKET Socket, NETADDR *pAddr, int Ack, int Con
 	Construct.m_aChunkData[0] = ControlMsg;
 	mem_copy(&Construct.m_aChunkData[1], pExtra, ExtraSize);
 	
-	/* send the control message */
+	// send the control message
 	CNetBase::SendPacket(Socket, pAddr, &Construct);
 }
 
@@ -291,11 +290,12 @@ int CNetBase::IsSeqInBackroom(int Seq, int Ack)
 
 IOHANDLE CNetBase::ms_DataLogSent = 0;
 IOHANDLE CNetBase::ms_DataLogRecv = 0;
-HUFFMAN_STATE CNetBase::ms_HuffmanState;
+CHuffman CNetBase::ms_Huffman;
 
 
 void CNetBase::OpenLog(const char *pSentLog, const char *pRecvLog)
 {
+	/*
 	if(pSentLog)
 	{
 		ms_DataLogSent = engine_openfile(pSentLog, IOFLAG_WRITE);
@@ -312,17 +312,17 @@ void CNetBase::OpenLog(const char *pSentLog, const char *pRecvLog)
 			dbg_msg("network", "logging recv packages to '%s'", pRecvLog);
 		else
 			dbg_msg("network", "failed to open for logging '%s'", pRecvLog);
-	}
+	}*/
 }
 
 int CNetBase::Compress(const void *pData, int DataSize, void *pOutput, int OutputSize)
 {
-	return huffman_compress(&ms_HuffmanState, pData, DataSize, pOutput, OutputSize);
+	return ms_Huffman.Compress(pData, DataSize, pOutput, OutputSize);
 }
 
 int CNetBase::Decompress(const void *pData, int DataSize, void *pOutput, int OutputSize)
 {
-	return huffman_decompress(&ms_HuffmanState, pData, DataSize, pOutput, OutputSize);
+	return ms_Huffman.Decompress(pData, DataSize, pOutput, OutputSize);
 }
 
 
@@ -343,5 +343,5 @@ static const unsigned gs_aFreqTable[256+1] = {
 
 void CNetBase::Init()
 {
-	huffman_init(&ms_HuffmanState, gs_aFreqTable);
+	ms_Huffman.Init(gs_aFreqTable);
 }
diff --git a/src/engine/e_network.h b/src/engine/shared/network.h
index 19eca8da..11a1b70d 100644
--- a/src/engine/e_network.h
+++ b/src/engine/shared/network.h
@@ -1,9 +1,8 @@
-#ifndef ENGINE_NETWORK_H
-#define ENGINE_NETWORK_H
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
+#ifndef ENGINE_SHARED_NETWORK_H
+#define ENGINE_SHARED_NETWORK_H
 
-#include "e_ringbuffer.h"
-#include "e_huffman.h"
+#include "ringbuffer.h"
+#include "huffman.h"
 
 /*
 
@@ -80,15 +79,15 @@ enum
 };
 
 
-typedef int (*NETFUNC_DELCLIENT)(int cid, void *user);
-typedef int (*NETFUNC_NEWCLIENT)(int cid, void *user);
+typedef int (*NETFUNC_DELCLIENT)(int ClientID, void *pUser);
+typedef int (*NETFUNC_NEWCLIENT)(int ClientID, void *pUser);
 
 struct CNetChunk
 {
-	/* -1 means that it's a stateless packet */
-	/* 0 on the client means the server */
+	// -1 means that it's a stateless packet
+	// 0 on the client means the server
 	int m_ClientID;
-	NETADDR m_Address; /* only used when client_id == -1 */
+	NETADDR m_Address; // only used when client_id == -1
 	int m_Flags;
 	int m_DataSize;
 	const void *m_pData;
@@ -162,7 +161,7 @@ private:
 	void SetError(const char *pString);
 	void AckChunks(int Ack);
 	
-	void QueueChunkEx(int Flags, int DataSize, const void *pData, int Sequence);
+	int QueueChunkEx(int Flags, int DataSize, const void *pData, int Sequence);
 	void SendControl(int ControlMsg, const void *pExtra, int ExtraSize);
 	void ResendChunk(CNetChunkResend *pResend);
 	void Resend();
@@ -176,7 +175,7 @@ public:
 	int Flush();	
 
 	int Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr);
-	void QueueChunk(int Flags, int DataSize, const void *pData);
+	int QueueChunk(int Flags, int DataSize, const void *pData);
 
 	const char *ErrorString();
 	void SignalResend();
@@ -210,7 +209,7 @@ public:
 	int FetchChunk(CNetChunk *pChunk);	
 };
 
-/* server side */
+// server side
 class CNetServer
 {
 public:
@@ -232,11 +231,11 @@ private:
 	public:
 		CBanInfo m_Info;
 		
-		/* hash list */
+		// hash list
 		CBan *m_pHashNext;
 		CBan *m_pHashPrev;
 		
-		/* used or free list */
+		// used or free list
 		CBan *m_pNext;
 		CBan *m_pPrev;
 	};
@@ -257,13 +256,13 @@ private:
 	
 	CNetRecvUnpacker m_RecvUnpacker;
 	
-	void BanRemoveByObject(CBan *ban);
+	void BanRemoveByObject(CBan *pBan);
 	
 public:
 	int SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser);
 
 	//
-	bool Open(NETADDR bindaddr, int MaxClients, int Flags);
+	bool Open(NETADDR BindAddr, int MaxClients, int Flags);
 	int Close();
 	
 	//
@@ -277,8 +276,8 @@ public:
 	// banning
 	int BanAdd(NETADDR Addr, int Seconds);
 	int BanRemove(NETADDR Addr);
-	int BanNum(); /* caution, slow */
-	int BanGet(int Index, CBanInfo *pInfo); /* caution, slow */
+	int BanNum(); // caution, slow
+	int BanGet(int Index, CBanInfo *pInfo); // caution, slow
 
 	// status requests
 	NETADDR ClientAddr(int ClientID) const { return m_aSlots[ClientID].m_Connection.PeerAddress(); }
@@ -288,7 +287,7 @@ public:
 
 
 
-/* client side */
+// client side
 class CNetClient
 {
 	NETADDR m_ServerAddr;
@@ -327,7 +326,7 @@ class CNetBase
 {
 	static IOHANDLE ms_DataLogSent;
 	static IOHANDLE ms_DataLogRecv;
-	static HUFFMAN_STATE ms_HuffmanState;
+	static CHuffman ms_Huffman;
 public:
 	static void OpenLog(const char *pSentlog, const char *pRecvlog);
 	static void Init();
@@ -339,7 +338,7 @@ public:
 	static void SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct *pPacket);
 	static int UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct *pPacket);
 
-	/* The backroom is ack-NET_MAX_SEQUENCE/2. Used for knowing if we acked a packet or not */
+	// The backroom is ack-NET_MAX_SEQUENCE/2. Used for knowing if we acked a packet or not
 	static int IsSeqInBackroom(int Seq, int Ack);	
 };
 
diff --git a/src/engine/e_network_client.cpp b/src/engine/shared/network_client.cpp
index ce243b32..f7859c0a 100644
--- a/src/engine/e_network_client.cpp
+++ b/src/engine/shared/network_client.cpp
@@ -1,5 +1,5 @@
 #include <base/system.h>
-#include "e_network.h"
+#include "network.h"
 
 bool CNetClient::Open(NETADDR BindAddr, int Flags)
 {
@@ -14,7 +14,7 @@ bool CNetClient::Open(NETADDR BindAddr, int Flags)
 
 int CNetClient::Close()
 {
-	/* TODO: implement me */
+	// TODO: implement me
 	return 0;
 }
 
@@ -50,15 +50,15 @@ int CNetClient::Recv(CNetChunk *pChunk)
 {
 	while(1)
 	{
-		/* check for a chunk */
+		// check for a chunk
 		if(m_RecvUnpacker.FetchChunk(pChunk))
 			return 1;
 		
-		/* TODO: empty the recvinfo */
+		// TODO: empty the recvinfo
 		NETADDR Addr;
 		int Bytes = net_udp_recv(m_Socket, &Addr, m_RecvUnpacker.m_aBuffer, NET_MAX_PACKETSIZE);
 
-		/* no more packets for now */
+		// no more packets for now
 		if(Bytes <= 0)
 			break;
 
@@ -93,7 +93,7 @@ int CNetClient::Send(CNetChunk *pChunk)
 	
 	if(pChunk->m_Flags&NETSENDFLAG_CONNLESS)
 	{
-		/* send connectionless packet */
+		// send connectionless packet
 		CNetBase::SendPacketConnless(m_Socket, &pChunk->m_Address, pChunk->m_pData, pChunk->m_DataSize);
 	}
 	else
diff --git a/src/engine/e_network_conn.cpp b/src/engine/shared/network_conn.cpp
index a54c9ce3..4ed157eb 100644
--- a/src/engine/e_network_conn.cpp
+++ b/src/engine/shared/network_conn.cpp
@@ -1,7 +1,6 @@
 #include <base/system.h>
-#include <string.h>
-#include "e_config.h"
-#include "e_network.h"
+#include "config.h"
+#include "network.h"
 
 void CNetConnection::ResetStats()
 {
@@ -71,27 +70,27 @@ int CNetConnection::Flush()
 	if(!NumChunks && !m_Construct.m_Flags)
 		return 0;
 
-	/* send of the packets */	
+	// send of the packets
 	m_Construct.m_Ack = m_Ack;
 	CNetBase::SendPacket(m_Socket, &m_PeerAddr, &m_Construct);
 	
-	/* update send times */
+	// update send times
 	m_LastSendTime = time_get();
 	
-	/* clear construct so we can start building a new package */
+	// clear construct so we can start building a new package
 	mem_zero(&m_Construct, sizeof(m_Construct));
 	return NumChunks;
 }
 
-void CNetConnection::QueueChunkEx(int Flags, int DataSize, const void *pData, int Sequence)
+int CNetConnection::QueueChunkEx(int Flags, int DataSize, const void *pData, int Sequence)
 {
 	unsigned char *pChunkData;
 	
-	/* check if we have space for it, if not, flush the connection */
+	// check if we have space for it, if not, flush the connection
 	if(m_Construct.m_DataSize + DataSize + NET_MAX_CHUNKHEADERSIZE > (int)sizeof(m_Construct.m_aChunkData))
 		Flush();
 
-	/* pack all the data */
+	// pack all the data
 	CNetChunkHeader Header;
 	Header.m_Flags = Flags;
 	Header.m_Size = DataSize;
@@ -101,15 +100,15 @@ void CNetConnection::QueueChunkEx(int Flags, int DataSize, const void *pData, in
 	mem_copy(pChunkData, pData, DataSize);
 	pChunkData += DataSize;
 
-	/* */
+	//
 	m_Construct.m_NumChunks++;
 	m_Construct.m_DataSize = (int)(pChunkData-m_Construct.m_aChunkData);
 	
-	/* set packet flags aswell */
+	// set packet flags aswell
 	
 	if(Flags&NET_CHUNKFLAG_VITAL && !(Flags&NET_CHUNKFLAG_RESEND))
 	{
-		/* save packet if we need to resend */
+		// save packet if we need to resend
 		CNetChunkResend *pResend = m_Buffer.Allocate(sizeof(CNetChunkResend)+DataSize);
 		if(pResend)
 		{
@@ -123,22 +122,25 @@ void CNetConnection::QueueChunkEx(int Flags, int DataSize, const void *pData, in
 		}
 		else
 		{
-			/* out of buffer */
+			// out of buffer
 			Disconnect("too weak connection (out of buffer)");
+			return -1;
 		}
 	}
+
+	return 0;
 }
 
-void CNetConnection::QueueChunk(int Flags, int DataSize, const void *pData)
+int CNetConnection::QueueChunk(int Flags, int DataSize, const void *pData)
 {
 	if(Flags&NET_CHUNKFLAG_VITAL)
 		m_Sequence = (m_Sequence+1)%NET_MAX_SEQUENCE;
-	QueueChunkEx(Flags, DataSize, pData, m_Sequence);
+	return QueueChunkEx(Flags, DataSize, pData, m_Sequence);
 }
 
 void CNetConnection::SendControl(int ControlMsg, const void *pExtra, int ExtraSize)
 {
-	/* send the control message */
+	// send the control message
 	m_LastSendTime = time_get();
 	CNetBase::SendControlMsg(m_Socket, &m_PeerAddr, m_Ack, ControlMsg, pExtra, ExtraSize);
 }
@@ -151,7 +153,7 @@ void CNetConnection::ResendChunk(CNetChunkResend *pResend)
 
 void CNetConnection::Resend()
 {
-	for(CNetChunkResend *pResend = m_Buffer.First(); pResend; m_Buffer.Next(pResend))
+	for(CNetChunkResend *pResend = m_Buffer.First(); pResend; pResend = m_Buffer.Next(pResend))
 		ResendChunk(pResend);
 }
 
@@ -160,7 +162,7 @@ int CNetConnection::Connect(NETADDR *pAddr)
 	if(State() != NET_CONNSTATE_OFFLINE)
 		return -1;
 	
-	/* init connection */
+	// init connection
 	Reset();
 	m_PeerAddr = *pAddr;
 	mem_zero(m_ErrorString, sizeof(m_ErrorString));
@@ -177,7 +179,7 @@ void CNetConnection::Disconnect(const char *pReason)
 	if(m_RemoteClosed == 0)
 	{
 		if(pReason)
-			SendControl(NET_CTRLMSG_CLOSE, pReason, strlen(pReason)+1);
+			SendControl(NET_CTRLMSG_CLOSE, pReason, str_length(pReason)+1);
 		else
 			SendControl(NET_CTRLMSG_CLOSE, 0, 0);
 
@@ -191,41 +193,44 @@ void CNetConnection::Disconnect(const char *pReason)
 
 int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr)
 {
-	int64 now = time_get();
-	m_LastRecvTime = now;
+	int64 Now = time_get();
+	m_LastRecvTime = Now;
 	
-	/* check if resend is requested */
+	// check if resend is requested
 	if(pPacket->m_Flags&NET_PACKETFLAG_RESEND)
 		Resend();
 
-	/* */									
+	//
 	if(pPacket->m_Flags&NET_PACKETFLAG_CONTROL)
 	{
 		int CtrlMsg = pPacket->m_aChunkData[0];
 		
 		if(CtrlMsg == NET_CTRLMSG_CLOSE)
 		{
-			m_State = NET_CONNSTATE_ERROR;
-			m_RemoteClosed = 1;
-			
-			if(pPacket->m_DataSize)
+			if(net_addr_comp(&m_PeerAddr, pAddr) == 0)
 			{
-				/* make sure to sanitize the error string form the other party*/
-				char Str[128];
-				if(pPacket->m_DataSize < 128)
-					str_copy(Str, (char *)pPacket->m_aChunkData, pPacket->m_DataSize);
-				else
-					str_copy(Str, (char *)pPacket->m_aChunkData, sizeof(Str));
-				str_sanitize_strong(Str);
+				m_State = NET_CONNSTATE_ERROR;
+				m_RemoteClosed = 1;
 				
-				/* set the error string */
-				SetError(Str);
+				if(pPacket->m_DataSize)
+				{
+					// make sure to sanitize the error string form the other party
+					char Str[128];
+					if(pPacket->m_DataSize < 128)
+						str_copy(Str, (char *)pPacket->m_aChunkData, pPacket->m_DataSize);
+					else
+						str_copy(Str, (char *)pPacket->m_aChunkData, sizeof(Str));
+					str_sanitize_strong(Str);
+					
+					// set the error string
+					SetError(Str);
+				}
+				else
+					SetError("no reason given");
+					
+				if(g_Config.m_Debug)
+					dbg_msg("conn", "closed reason='%s'", ErrorString());
 			}
-			else
-				SetError("no reason given");
-				
-			if(config.debug)
-				dbg_msg("conn", "closed reason='%s'", ErrorString());
 			return 0;			
 		}
 		else
@@ -234,32 +239,32 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr)
 			{
 				if(CtrlMsg == NET_CTRLMSG_CONNECT)
 				{
-					/* send response and init connection */
+					// send response and init connection
 					Reset();
 					m_State = NET_CONNSTATE_PENDING;
 					m_PeerAddr = *pAddr;
-					m_LastSendTime = now;
-					m_LastRecvTime = now;
-					m_LastUpdateTime = now;
+					m_LastSendTime = Now;
+					m_LastRecvTime = Now;
+					m_LastUpdateTime = Now;
 					SendControl(NET_CTRLMSG_CONNECTACCEPT, 0, 0);
-					if(config.debug)
+					if(g_Config.m_Debug)
 						dbg_msg("connection", "got connection, sending connect+accept");			
 				}
 			}
 			else if(State() == NET_CONNSTATE_CONNECT)
 			{
-				/* connection made */
+				// connection made
 				if(CtrlMsg == NET_CTRLMSG_CONNECTACCEPT)
 				{
 					SendControl(NET_CTRLMSG_ACCEPT, 0, 0);
 					m_State = NET_CONNSTATE_ONLINE;
-					if(config.debug)
+					if(g_Config.m_Debug)
 						dbg_msg("connection", "got connect+accept, sending accept. connection online");
 				}
 			}
 			else if(State() == NET_CONNSTATE_ONLINE)
 			{
-				/* connection made */
+				// connection made
 				/*
 				if(ctrlmsg == NET_CTRLMSG_CONNECTACCEPT)
 				{
@@ -273,7 +278,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr)
 		if(State() == NET_CONNSTATE_PENDING)
 		{
 			m_State = NET_CONNSTATE_ONLINE;
-			if(config.debug)
+			if(g_Config.m_Debug)
 				dbg_msg("connection", "connecting online");
 		}
 	}
@@ -288,46 +293,46 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr)
 
 int CNetConnection::Update()
 {
-	int64 now = time_get();
+	int64 Now = time_get();
 
 	if(State() == NET_CONNSTATE_OFFLINE || State() == NET_CONNSTATE_ERROR)
 		return 0;
 	
-	/* check for timeout */
+	// check for timeout
 	if(State() != NET_CONNSTATE_OFFLINE &&
 		State() != NET_CONNSTATE_CONNECT &&
-		(now-m_LastRecvTime) > time_freq()*10)
+		(Now-m_LastRecvTime) > time_freq()*10)
 	{
 		m_State = NET_CONNSTATE_ERROR;
 		SetError("timeout");
 	}
 
-	/* fix resends */
+	// fix resends
 	if(m_Buffer.First())
 	{
 		CNetChunkResend *pResend = m_Buffer.First();
 
-		/* check if we have some really old stuff laying around and abort if not acked */
-		if(now-pResend->m_FirstSendTime > time_freq()*10)
+		// check if we have some really old stuff laying around and abort if not acked
+		if(Now-pResend->m_FirstSendTime > time_freq()*10)
 		{
 			m_State = NET_CONNSTATE_ERROR;
 			SetError("too weak connection (not acked for 10 seconds)");
 		}
 		else
 		{
-			/* resend packet if we havn't got it acked in 1 second */
-			if(now-pResend->m_LastSendTime > time_freq())
+			// resend packet if we havn't got it acked in 1 second
+			if(Now-pResend->m_LastSendTime > time_freq())
 				ResendChunk(pResend);
 		}
 	}
 	
-	/* send keep alives if nothing has happend for 250ms */
+	// send keep alives if nothing has happend for 250ms
 	if(State() == NET_CONNSTATE_ONLINE)
 	{
-		if(time_get()-m_LastSendTime > time_freq()/2) /* flush connection after 500ms if needed */
+		if(time_get()-m_LastSendTime > time_freq()/2) // flush connection after 500ms if needed
 		{
 			int NumFlushedChunks = Flush();
-			if(NumFlushedChunks && config.debug)
+			if(NumFlushedChunks && g_Config.m_Debug)
 				dbg_msg("connection", "flushed connection due to timeout. %d chunks.", NumFlushedChunks);
 		}
 			
@@ -336,12 +341,12 @@ int CNetConnection::Update()
 	}
 	else if(State() == NET_CONNSTATE_CONNECT)
 	{
-		if(time_get()-m_LastSendTime > time_freq()/2) /* send a new connect every 500ms */
+		if(time_get()-m_LastSendTime > time_freq()/2) // send a new connect every 500ms
 			SendControl(NET_CTRLMSG_CONNECT, 0, 0);
 	}
 	else if(State() == NET_CONNSTATE_PENDING)
 	{
-		if(time_get()-m_LastSendTime > time_freq()/2) /* send a new connect/accept every 500ms */
+		if(time_get()-m_LastSendTime > time_freq()/2) // send a new connect/accept every 500ms
 			SendControl(NET_CTRLMSG_CONNECTACCEPT, 0, 0);
 	}
 	
diff --git a/src/engine/e_network_server.cpp b/src/engine/shared/network_server.cpp
index 995290ef..32b08bf6 100644
--- a/src/engine/e_network_server.cpp
+++ b/src/engine/shared/network_server.cpp
@@ -1,28 +1,28 @@
 #include <base/system.h>
-#include "e_network.h"
+#include "network.h"
 
-#define MACRO_LIST_LINK_FIRST(object, first, prev, next) \
-	{ if(first) first->prev = object; \
-	object->prev = (struct CBan *)0; \
-	object->next = first; \
-	first = object; }
+#define MACRO_LIST_LINK_FIRST(Object, First, Prev, Next) \
+	{ if(First) First->Prev = Object; \
+	Object->Prev = (struct CBan *)0; \
+	Object->Next = First; \
+	First = Object; }
 	
-#define MACRO_LIST_LINK_AFTER(object, after, prev, next) \
-	{ object->prev = after; \
-	object->next = after->next; \
-	after->next = object; \
-	if(object->next) \
-		object->next->prev = object; \
+#define MACRO_LIST_LINK_AFTER(Object, After, Prev, Next) \
+	{ Object->Prev = After; \
+	Object->Next = After->Next; \
+	After->Next = Object; \
+	if(Object->Next) \
+		Object->Next->Prev = Object; \
 	}
 
-#define MACRO_LIST_UNLINK(object, first, prev, next) \
-	{ if(object->next) object->next->prev = object->prev; \
-	if(object->prev) object->prev->next = object->next; \
-	else first = object->next; \
-	object->next = 0; object->prev = 0; }
+#define MACRO_LIST_UNLINK(Object, First, Prev, Next) \
+	{ if(Object->Next) Object->Next->Prev = Object->Prev; \
+	if(Object->Prev) Object->Prev->Next = Object->Next; \
+	else First = Object->Next; \
+	Object->Next = 0; Object->Prev = 0; }
 	
-#define MACRO_LIST_FIND(start, next, expression) \
-	{ while(start && !(expression)) start = start->next; }
+#define MACRO_LIST_FIND(Start, Next, Expression) \
+	{ while(Start && !(Expression)) Start = Start->Next; }
 
 bool CNetServer::Open(NETADDR BindAddr, int MaxClients, int Flags)
 {
@@ -44,7 +44,7 @@ bool CNetServer::Open(NETADDR BindAddr, int MaxClients, int Flags)
 	for(int i = 0; i < NET_MAX_CLIENTS; i++)
 		m_aSlots[i].m_Connection.Init(m_Socket);
 	
-	/* setup all pointers for bans */
+	// setup all pointers for bans
 	for(int i = 1; i < NET_SERVER_MAXBANS-1; i++)
 	{
 		m_BanPool[i].m_pNext = &m_BanPool[i+1];
@@ -68,13 +68,13 @@ int CNetServer::SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT p
 
 int CNetServer::Close()
 {
-	/* TODO: implement me */
+	// TODO: implement me
 	return 0;
 }
 
 int CNetServer::Drop(int ClientID, const char *pReason)
 {
-	/* TODO: insert lots of checks here */
+	// TODO: insert lots of checks here
 	NETADDR Addr = ClientAddr(ClientID);
 
 	dbg_msg("net_server", "client dropped. cid=%d ip=%d.%d.%d.%d reason=\"%s\"",
@@ -114,18 +114,18 @@ int CNetServer::BanNum()
 
 void CNetServer::BanRemoveByObject(CBan *pBan)
 {
-	int iphash = (pBan->m_Info.m_Addr.ip[0]+pBan->m_Info.m_Addr.ip[1]+pBan->m_Info.m_Addr.ip[2]+pBan->m_Info.m_Addr.ip[3])&0xff;
+	int IpHash = (pBan->m_Info.m_Addr.ip[0]+pBan->m_Info.m_Addr.ip[1]+pBan->m_Info.m_Addr.ip[2]+pBan->m_Info.m_Addr.ip[3])&0xff;
 	dbg_msg("netserver", "removing ban on %d.%d.%d.%d",
 		pBan->m_Info.m_Addr.ip[0], pBan->m_Info.m_Addr.ip[1], pBan->m_Info.m_Addr.ip[2], pBan->m_Info.m_Addr.ip[3]);
 	MACRO_LIST_UNLINK(pBan, m_BanPool_FirstUsed, m_pPrev, m_pNext);
-	MACRO_LIST_UNLINK(pBan, m_aBans[iphash], m_pHashPrev, m_pHashNext);
+	MACRO_LIST_UNLINK(pBan, m_aBans[IpHash], m_pHashPrev, m_pHashNext);
 	MACRO_LIST_LINK_FIRST(pBan, m_BanPool_FirstFree, m_pPrev, m_pNext);
 }
 
 int CNetServer::BanRemove(NETADDR Addr)
 {
-	int iphash = (Addr.ip[0]+Addr.ip[1]+Addr.ip[2]+Addr.ip[3])&0xff;
-	CBan *pBan = m_aBans[iphash];
+	int IpHash = (Addr.ip[0]+Addr.ip[1]+Addr.ip[2]+Addr.ip[3])&0xff;
+	CBan *pBan = m_aBans[IpHash];
 	
 	MACRO_LIST_FIND(pBan, m_pHashNext, net_addr_comp(&pBan->m_Info.m_Addr, &Addr) == 0);
 	
@@ -140,22 +140,22 @@ int CNetServer::BanRemove(NETADDR Addr)
 
 int CNetServer::BanAdd(NETADDR Addr, int Seconds)
 {
-	int iphash = (Addr.ip[0]+Addr.ip[1]+Addr.ip[2]+Addr.ip[3])&0xff;
+	int IpHash = (Addr.ip[0]+Addr.ip[1]+Addr.ip[2]+Addr.ip[3])&0xff;
 	int Stamp = -1;
 	CBan *pBan;
 	
-	/* remove the port */
+	// remove the port
 	Addr.port = 0;
 	
 	if(Seconds)
 		Stamp = time_timestamp() + Seconds;
 		
-	/* search to see if it already exists */
-	pBan = m_aBans[iphash];
+	// search to see if it already exists
+	pBan = m_aBans[IpHash];
 	MACRO_LIST_FIND(pBan, m_pHashNext, net_addr_comp(&pBan->m_Info.m_Addr, &Addr) == 0);
 	if(pBan)
 	{
-		/* adjust the ban */
+		// adjust the ban
 		pBan->m_Info.m_Expires = Stamp;
 		return 0;
 	}
@@ -163,18 +163,18 @@ int CNetServer::BanAdd(NETADDR Addr, int Seconds)
 	if(!m_BanPool_FirstFree)
 		return -1;
 
-	/* fetch and clear the new ban */
+	// fetch and clear the new ban
 	pBan = m_BanPool_FirstFree;
 	MACRO_LIST_UNLINK(pBan, m_BanPool_FirstFree, m_pPrev, m_pNext);
 	
-	/* setup the ban info */
+	// setup the ban info
 	pBan->m_Info.m_Expires = Stamp;
 	pBan->m_Info.m_Addr = Addr;
 	
-	/* add it to the ban hash */
-	MACRO_LIST_LINK_FIRST(pBan, m_aBans[iphash], m_pHashPrev, m_pHashNext);
+	// add it to the ban hash
+	MACRO_LIST_LINK_FIRST(pBan, m_aBans[IpHash], m_pHashPrev, m_pHashNext);
 	
-	/* insert it into the used list */
+	// insert it into the used list
 	{
 		if(m_BanPool_FirstUsed)
 		{
@@ -185,7 +185,7 @@ int CNetServer::BanAdd(NETADDR Addr, int Seconds)
 				pInsertAfter = pInsertAfter->m_pPrev;
 			else
 			{
-				/* add to last */
+				// add to last
 				pInsertAfter = m_BanPool_FirstUsed;
 				while(pInsertAfter->m_pNext)
 					pInsertAfter = pInsertAfter->m_pNext;
@@ -206,7 +206,7 @@ int CNetServer::BanAdd(NETADDR Addr, int Seconds)
 		}
 	}
 
-	/* drop banned clients */	
+	// drop banned clients
 	{
 		char Buf[128];
 		NETADDR BanAddr;
@@ -238,7 +238,7 @@ int CNetServer::Update()
 			Drop(i, m_aSlots[i].m_Connection.ErrorString());
 	}
 	
-	/* remove expired bans */
+	// remove expired bans
 	while(m_BanPool_FirstUsed && m_BanPool_FirstUsed->m_Info.m_Expires < Now)
 	{
 		CBan *pBan = m_BanPool_FirstUsed;
@@ -253,20 +253,20 @@ int CNetServer::Update()
 */
 int CNetServer::Recv(CNetChunk *pChunk)
 {
-	unsigned now = time_timestamp();
+	unsigned Now = time_timestamp();
 	
 	while(1)
 	{
 		NETADDR Addr;
 			
-		/* check for a chunk */
+		// check for a chunk
 		if(m_RecvUnpacker.FetchChunk(pChunk))
 			return 1;
 		
-		/* TODO: empty the recvinfo */
+		// TODO: empty the recvinfo
 		int Bytes = net_udp_recv(m_Socket, &Addr, m_RecvUnpacker.m_aBuffer, NET_MAX_PACKETSIZE);
 
-		/* no more packets for now */
+		// no more packets for now
 		if(Bytes <= 0)
 			break;
 		
@@ -274,25 +274,25 @@ int CNetServer::Recv(CNetChunk *pChunk)
 		{
 			CBan *pBan = 0;
 			NETADDR BanAddr = Addr;
-			int iphash = (BanAddr.ip[0]+BanAddr.ip[1]+BanAddr.ip[2]+BanAddr.ip[3])&0xff;
+			int IpHash = (BanAddr.ip[0]+BanAddr.ip[1]+BanAddr.ip[2]+BanAddr.ip[3])&0xff;
 			int Found = 0;
 			BanAddr.port = 0;
 			
-			/* search a ban */
-			for(pBan = m_aBans[iphash]; pBan; pBan = pBan->m_pHashNext)
+			// search a ban
+			for(pBan = m_aBans[IpHash]; pBan; pBan = pBan->m_pHashNext)
 			{
 				if(net_addr_comp(&pBan->m_Info.m_Addr, &BanAddr) == 0)
 					break;
 			}
 			
-			/* check if we just should drop the packet */
+			// check if we just should drop the packet
 			if(pBan)
 			{
 				// banned, reply with a message
 				char BanStr[128];
 				if(pBan->m_Info.m_Expires)
 				{
-					int Mins = ((pBan->m_Info.m_Expires - now)+59)/60;
+					int Mins = ((pBan->m_Info.m_Expires - Now)+59)/60;
 					if(Mins == 1)
 						str_format(BanStr, sizeof(BanStr), "banned for %d minute", Mins);
 					else
@@ -315,24 +315,24 @@ int CNetServer::Recv(CNetChunk *pChunk)
 			}
 			else
 			{			
-				/* TODO: check size here */
+				// TODO: check size here
 				if(m_RecvUnpacker.m_Data.m_Flags&NET_PACKETFLAG_CONTROL && m_RecvUnpacker.m_Data.m_aChunkData[0] == NET_CTRLMSG_CONNECT)
 				{
 					Found = 0;
 				
-					/* check if we already got this client */
+					// check if we already got this client
 					for(int i = 0; i < MaxClients(); i++)
 					{
 						NETADDR PeerAddr = m_aSlots[i].m_Connection.PeerAddress();
 						if(m_aSlots[i].m_Connection.State() != NET_CONNSTATE_OFFLINE &&
 							net_addr_comp(&PeerAddr, &Addr) == 0)
 						{
-							Found = 1; /* silent ignore.. we got this client already */
+							Found = 1; // silent ignore.. we got this client already
 							break;
 						}
 					}
 					
-					/* client that wants to connect */
+					// client that wants to connect
 					if(!Found)
 					{
 						for(int i = 0; i < MaxClients(); i++)
@@ -356,7 +356,7 @@ int CNetServer::Recv(CNetChunk *pChunk)
 				}
 				else
 				{
-					/* normal packet, find matching slot */
+					// normal packet, find matching slot
 					for(int i = 0; i < MaxClients(); i++)
 					{
 						NETADDR PeerAddr = m_aSlots[i].m_Connection.PeerAddress();
@@ -386,7 +386,7 @@ int CNetServer::Send(CNetChunk *pChunk)
 	
 	if(pChunk->m_Flags&NETSENDFLAG_CONNLESS)
 	{
-		/* send connectionless packet */
+		// send connectionless packet
 		CNetBase::SendPacketConnless(m_Socket, &pChunk->m_Address, pChunk->m_pData, pChunk->m_DataSize);
 	}
 	else
@@ -398,10 +398,15 @@ int CNetServer::Send(CNetChunk *pChunk)
 		if(pChunk->m_Flags&NETSENDFLAG_VITAL)
 			Flags = NET_CHUNKFLAG_VITAL;
 		
-		m_aSlots[pChunk->m_ClientID].m_Connection.QueueChunk(Flags, pChunk->m_DataSize, pChunk->m_pData);
-
-		if(pChunk->m_Flags&NETSENDFLAG_FLUSH)
-			m_aSlots[pChunk->m_ClientID].m_Connection.Flush();
+		if(m_aSlots[pChunk->m_ClientID].m_Connection.QueueChunk(Flags, pChunk->m_DataSize, pChunk->m_pData) == 0)
+		{
+			if(pChunk->m_Flags&NETSENDFLAG_FLUSH)
+				m_aSlots[pChunk->m_ClientID].m_Connection.Flush();
+		}
+		else
+		{
+			Drop(pChunk->m_ClientID, "error sending data");
+		}
 	}
 	return 0;
 }
diff --git a/src/engine/e_packer.cpp b/src/engine/shared/packer.cpp
index 0d8aeab3..3e1d8dd6 100644
--- a/src/engine/e_packer.cpp
+++ b/src/engine/shared/packer.cpp
@@ -1,11 +1,10 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <stdlib.h> /* rand() */
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
 #include <base/system.h>
 
-#include "e_packer.h"
-#include "e_compression.h"
-#include "e_engine.h"
-#include "e_config.h"
+#include "packer.h"
+#include "compression.h"
+#include "engine.h"
+#include "config.h"
 
 void CPacker::Reset()
 {
@@ -19,14 +18,14 @@ void CPacker::AddInt(int i)
 	if(m_Error)
 		return;
 		
-	/* make sure that we have space enough */
+	// make sure that we have space enough
 	if(m_pEnd - m_pCurrent < 6)
 	{
 		dbg_break();
 		m_Error = 1;
 	}
 	else
-		m_pCurrent = vint_pack(m_pCurrent, i);
+		m_pCurrent = CVariableInt::Pack(m_pCurrent, i);
 }
 
 void CPacker::AddString(const char *pStr, int Limit)
@@ -34,7 +33,7 @@ void CPacker::AddString(const char *pStr, int Limit)
 	if(m_Error)
 		return;
 	
-	/* */
+	//
 	if(Limit > 0)
 	{
 		while(*pStr && Limit != 0)
@@ -66,7 +65,7 @@ void CPacker::AddString(const char *pStr, int Limit)
 	}
 }
 
-void CPacker::AddRaw(const unsigned char *pData, int Size)
+void CPacker::AddRaw(const void *pData, int Size)
 {
 	if(m_Error)
 		return;
@@ -77,18 +76,19 @@ void CPacker::AddRaw(const unsigned char *pData, int Size)
 		return;
 	}
 	
+	const unsigned char *pSrc = (const unsigned char *)pData;
 	while(Size)
 	{
-		*m_pCurrent++ = *pData++;
+		*m_pCurrent++ = *pSrc++;
 		Size--;
 	}
 }
 
 
-void CUnpacker::Reset(const unsigned char *pData, int Size)
+void CUnpacker::Reset(const void *pData, int Size)
 {
 	m_Error = 0;
-	m_pStart = pData;
+	m_pStart = (const unsigned char *)pData;
 	m_pEnd = m_pStart + Size;
 	m_pCurrent = m_pStart;
 }
@@ -105,7 +105,7 @@ int CUnpacker::GetInt()
 	}
 	
 	int i;
-	m_pCurrent = vint_unpack(m_pCurrent, &i);
+	m_pCurrent = CVariableInt::Unpack(m_pCurrent, &i);
 	if(m_pCurrent > m_pEnd)
 	{
 		m_Error = 1;
@@ -120,7 +120,7 @@ const char *CUnpacker::GetString()
 		return "";
 		
 	char *pPtr = (char *)m_pCurrent;
-	while(*m_pCurrent) /* skip the string */
+	while(*m_pCurrent) // skip the string
 	{
 		m_pCurrent++;
 		if(m_pCurrent == m_pEnd)
@@ -131,7 +131,7 @@ const char *CUnpacker::GetString()
 	}
 	m_pCurrent++;
 	
-	/* sanitize all strings */
+	// sanitize all strings
 	str_sanitize(pPtr);
 	return pPtr;
 }
@@ -142,14 +142,14 @@ const unsigned char *CUnpacker::GetRaw(int Size)
 	if(m_Error)
 		return 0;
 	
-	/* check for nasty sizes */
+	// check for nasty sizes
 	if(Size < 0 || m_pCurrent+Size > m_pEnd)
 	{
 		m_Error = 1;
 		return 0;
 	}
 
-	/* "unpack" the data */	
+	// "unpack" the data
 	m_pCurrent += Size;
 	return pPtr;
 }
diff --git a/src/engine/e_packer.h b/src/engine/shared/packer.h
index 5dc80e7a..7a98501a 100644
--- a/src/engine/e_packer.h
+++ b/src/engine/shared/packer.h
@@ -1,4 +1,7 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
+#ifndef ENGINE_SHARED_PACKER_H
+#define ENGINE_SHARED_PACKER_H
+
+
 
 class CPacker
 {
@@ -15,7 +18,7 @@ public:
 	void Reset();
 	void AddInt(int i);
 	void AddString(const char *pStr, int Limit);
-	void AddRaw(const unsigned char *pData, int Size);
+	void AddRaw(const void *pData, int Size);
 	
 	int Size() const { return (int)(m_pCurrent-m_aBuffer); }
 	const unsigned char *Data() const { return m_aBuffer; }
@@ -29,9 +32,11 @@ class CUnpacker
 	const unsigned char *m_pEnd;
 	int m_Error;
 public:
-	void Reset(const unsigned char *pData, int Size);
+	void Reset(const void *pData, int Size);
 	int GetInt();
 	const char *GetString();
 	const unsigned char *GetRaw(int Size);
 	bool Error() const { return m_Error; }
 };
+
+#endif
diff --git a/src/engine/shared/protocol.h b/src/engine/shared/protocol.h
new file mode 100644
index 00000000..d09cff5a
--- /dev/null
+++ b/src/engine/shared/protocol.h
@@ -0,0 +1,91 @@
+#ifndef ENGINE_SHARED_PROTOCOL_H
+#define ENGINE_SHARED_PROTOCOL_H
+
+#include <base/system.h>
+
+/*
+	Connection diagram - How the initilization works.
+	
+	Client -> INFO -> Server
+		Contains version info, name, and some other info.
+		
+	Client <- MAP <- Server
+		Contains current map.
+	
+	Client -> READY -> Server
+		The client has loaded the map and is ready to go,
+		but the mod needs to send it's information aswell.
+		modc_connected is called on the client and
+		mods_connected is called on the server.
+		The client should call client_entergame when the
+		mod has done it's initilization.
+		
+	Client -> ENTERGAME -> Server
+		Tells the server to start sending snapshots.
+		client_entergame and server_client_enter is called.
+*/
+
+
+enum
+{
+	NETMSG_NULL=0,
+	
+	// the first thing sent by the client
+	// contains the version info for the client
+	NETMSG_INFO=1,
+	
+	// sent by server
+	NETMSG_MAP_CHANGE,		// sent when client should switch map
+	NETMSG_MAP_DATA,		// map transfer, contains a chunk of the map file
+	NETMSG_SNAP,			// normal snapshot, multiple parts
+	NETMSG_SNAPEMPTY,		// empty snapshot
+	NETMSG_SNAPSINGLE,		// ?
+	NETMSG_SNAPSMALL,		//
+	NETMSG_INPUTTIMING,		// reports how off the input was
+	NETMSG_RCON_AUTH_STATUS,// result of the authentication
+	NETMSG_RCON_LINE,		// line that should be printed to the remote console
+
+	NETMSG_AUTH_CHALLANGE,	//
+	NETMSG_AUTH_RESULT,		//
+	
+	// sent by client
+	NETMSG_READY,			//
+	NETMSG_ENTERGAME,
+	NETMSG_INPUT,			// contains the inputdata from the client
+	NETMSG_RCON_CMD,		// 
+	NETMSG_RCON_AUTH,		//
+	NETMSG_REQUEST_MAP_DATA,//
+
+	NETMSG_AUTH_START,		//
+	NETMSG_AUTH_RESPONSE,	//
+	
+	// sent by both
+	NETMSG_PING,
+	NETMSG_PING_REPLY,
+	NETMSG_ERROR
+};
+
+// this should be revised
+enum
+{
+	SERVER_TICK_SPEED=50,
+	SERVER_FLAG_PASSWORD = 0x1,
+
+	MAX_CLIENTS=16,
+
+	MAX_INPUT_SIZE=128,
+	MAX_SNAPSHOT_PACKSIZE=900,
+
+	MAX_CLANNAME_LENGTH=32,
+	MAX_NAME_LENGTH=24,
+	
+
+	// message packing
+	MSGFLAG_VITAL=1,
+	MSGFLAG_FLUSH=2,
+	MSGFLAG_NORECORD=4,
+	MSGFLAG_RECORD=8,
+	MSGFLAG_NOSEND=16
+};
+
+#endif
diff --git a/src/engine/e_ringbuffer.cpp b/src/engine/shared/ringbuffer.cpp
index eb8a8af4..45a845ee 100644
--- a/src/engine/e_ringbuffer.cpp
+++ b/src/engine/shared/ringbuffer.cpp
@@ -1,6 +1,6 @@
 #include <base/system.h>
 
-#include "e_ringbuffer.h"
+#include "ringbuffer.h"
 	
 CRingBufferBase::CItem *CRingBufferBase::NextBlock(CItem *pItem)
 {
@@ -18,15 +18,15 @@ CRingBufferBase::CItem *CRingBufferBase::PrevBlock(CItem *pItem)
 
 CRingBufferBase::CItem *CRingBufferBase::MergeBack(CItem *pItem)
 {
-	/* make sure that this block and previous block is free */
+	// make sure that this block and previous block is free
 	if(!pItem->m_Free || !pItem->m_pPrev || !pItem->m_pPrev->m_Free)
 		return pItem;
 
-	/* merge the blocks */
+	// merge the blocks
 	pItem->m_pPrev->m_Size += pItem->m_Size;
 	pItem->m_pPrev->m_pNext = pItem->m_pNext;
 	
-	/* fixup pointers */
+	// fixup pointers
 	if(pItem->m_pNext)
 		pItem->m_pNext->m_pPrev = pItem->m_pPrev;
 	else
@@ -38,7 +38,7 @@ CRingBufferBase::CItem *CRingBufferBase::MergeBack(CItem *pItem)
 	if(pItem == m_pConsume)
 		m_pConsume = pItem->m_pPrev;
 	
-	/* return the current block */
+	// return the current block
 	return pItem->m_pPrev;
 }
 
@@ -61,20 +61,20 @@ void *CRingBufferBase::Allocate(int Size)
 	int WantedSize = (Size+sizeof(CItem)+sizeof(CItem)-1)/sizeof(CItem)*sizeof(CItem);
 	CItem *pBlock = 0;
 
-	/* check if we even can fit this block */
+	// check if we even can fit this block
 	if(WantedSize > m_Size)
 		return 0;
 
 	while(1)	
 	{
-		/* check for space */
+		// check for space
 		if(m_pProduce->m_Free)
 		{
 			if(m_pProduce->m_Size >= WantedSize)
 				pBlock = m_pProduce;
 			else
 			{
-				/* wrap around to try to find a block */
+				// wrap around to try to find a block
 				if(m_pFirst->m_Free && m_pFirst->m_Size >= WantedSize)
 					pBlock = m_pFirst;
 			}
@@ -84,7 +84,7 @@ void *CRingBufferBase::Allocate(int Size)
 			break;
 		else
 		{
-			/* we have no block, check our policy and see what todo */
+			// we have no block, check our policy and see what todo
 			if(m_Flags&FLAG_RECYCLE)
 			{
 				if(!PopFirst())
@@ -95,10 +95,10 @@ void *CRingBufferBase::Allocate(int Size)
 		}
 	}
 	
-	/* okey, we have our block */
+	// okey, we have our block
 	
-	/* split the block if needed */
-	if(pBlock->m_Size > WantedSize)
+	// split the block if needed
+	if(pBlock->m_Size > WantedSize+sizeof(CItem))
 	{
 		CItem *pNewItem = (CItem *)((char *)pBlock + WantedSize);
 		pNewItem->m_pPrev = pBlock;
@@ -116,10 +116,10 @@ void *CRingBufferBase::Allocate(int Size)
 	}
 	
 	
-	/* set next block */
+	// set next block
 	m_pProduce = NextBlock(pBlock);
 	
-	/* set as used and return the item pointer */
+	// set as used and return the item pointer
 	pBlock->m_Free = 0;
 	return (void *)(pBlock+1);
 }
@@ -129,13 +129,13 @@ int CRingBufferBase::PopFirst()
 	if(m_pConsume->m_Free)
 		return 0;
 	
-	/* set the free flag */
+	// set the free flag
 	m_pConsume->m_Free = 1;
 	
-	/* previous block is also free, merge them */
+	// previous block is also free, merge them
 	m_pConsume = MergeBack(m_pConsume);
 	
-	/* advance the consume pointer */
+	// advance the consume pointer
 	m_pConsume = NextBlock(m_pConsume);
 	while(m_pConsume->m_Free && m_pConsume != m_pProduce)
 	{
@@ -143,8 +143,8 @@ int CRingBufferBase::PopFirst()
 		m_pConsume = NextBlock(m_pConsume);
 	}
 		
-	/* in the case that we have catched up with the produce pointer */
-	/* we might stand on a free block so merge em */
+	// in the case that we have catched up with the produce pointer
+	// we might stand on a free block so merge em
 	MergeBack(m_pConsume);
 	return 1;
 }
@@ -187,8 +187,6 @@ void *CRingBufferBase::First()
 
 void *CRingBufferBase::Last()
 {
-	if(!m_pProduce->m_Free)
-		return m_pProduce+1;
 	return Prev(m_pProduce+1);
 }
 
diff --git a/src/engine/e_ringbuffer.h b/src/engine/shared/ringbuffer.h
index b9f7219c..aa02b8d9 100644
--- a/src/engine/e_ringbuffer.h
+++ b/src/engine/shared/ringbuffer.h
@@ -1,5 +1,5 @@
-#ifndef _RINGBUFFER_H
-#define _RINGBUFFER_H
+#ifndef ENGINE_SHARED_RINGBUFFER_H
+#define ENGINE_SHARED_RINGBUFFER_H
 
 typedef struct RINGBUFFER RINGBUFFER;
 
@@ -40,7 +40,7 @@ protected:
 public:
 	enum
 	{
-		/* Will start to destroy items to try to fit the next one */
+		// Will start to destroy items to try to fit the next one
 		FLAG_RECYCLE=1
 	};
 };
diff --git a/src/engine/shared/snapshot.cpp b/src/engine/shared/snapshot.cpp
new file mode 100644
index 00000000..d566d3a3
--- /dev/null
+++ b/src/engine/shared/snapshot.cpp
@@ -0,0 +1,537 @@
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+#include "snapshot.h"
+#include "engine.h"
+#include "compression.h"
+
+// CSnapshot
+
+CSnapshotItem *CSnapshot::GetItem(int Index)
+{
+	return (CSnapshotItem *)(DataStart() + Offsets()[Index]);
+}
+
+int CSnapshot::GetItemSize(int Index)
+{
+    if(Index == m_NumItems-1)
+        return (m_DataSize - Offsets()[Index]) - sizeof(CSnapshotItem);
+    return (Offsets()[Index+1] - Offsets()[Index]) - sizeof(CSnapshotItem);
+}
+
+int CSnapshot::GetItemIndex(int Key)
+{
+    // TODO: OPT: this should not be a linear search. very bad
+    for(int i = 0; i < m_NumItems; i++)
+    {
+        if(GetItem(i)->Key() == Key)
+            return i;
+    }
+    return -1;
+}
+
+int CSnapshot::Crc()
+{
+	int Crc = 0;
+	
+	for(int i = 0; i < m_NumItems; i++)
+	{
+		CSnapshotItem *pItem = GetItem(i);
+		int Size = GetItemSize(i);
+		
+		for(int b = 0; b < Size/4; b++)
+			Crc += pItem->Data()[b];
+	}
+	return Crc;
+}
+
+void CSnapshot::DebugDump()
+{
+	dbg_msg("snapshot", "data_size=%d num_items=%d", m_DataSize, m_NumItems);
+	for(int i = 0; i < m_NumItems; i++)
+	{
+		CSnapshotItem *pItem = GetItem(i);
+		int Size = GetItemSize(i);
+		dbg_msg("snapshot", "\ttype=%d id=%d", pItem->Type(), pItem->ID());
+		for(int b = 0; b < Size/4; b++)
+			dbg_msg("snapshot", "\t\t%3d %12d\t%08x", b, pItem->Data()[b], pItem->Data()[b]);
+	}
+}
+
+
+// CSnapshotDelta
+
+struct CItemList
+{
+	int m_Num;
+	int m_aKeys[64];
+	int m_aIndex[64];
+};
+
+enum
+{
+	HASHLIST_SIZE = 256,
+};
+
+static void GenerateHash(CItemList *pHashlist, CSnapshot *pSnapshot)
+{
+	for(int i = 0; i < HASHLIST_SIZE; i++)
+		pHashlist[i].m_Num = 0;
+		
+	for(int i = 0; i < pSnapshot->NumItems(); i++)
+	{
+		int Key = pSnapshot->GetItem(i)->Key();
+		int HashID = ((Key>>8)&0xf0) | (Key&0xf);
+		if(pHashlist[HashID].m_Num != 64)
+		{
+			pHashlist[HashID].m_aIndex[pHashlist[HashID].m_Num] = i;
+			pHashlist[HashID].m_aKeys[pHashlist[HashID].m_Num] = Key;
+			pHashlist[HashID].m_Num++;
+		}
+	}
+}
+
+static int GetItemIndexHashed(int Key, const CItemList *pHashlist)
+{
+		int HashID = ((Key>>8)&0xf0) | (Key&0xf);
+		for(int i = 0; i < pHashlist[HashID].m_Num; i++)
+		{
+			if(pHashlist[HashID].m_aKeys[i] == Key)
+				return pHashlist[HashID].m_aIndex[i];
+	}
+	
+	return -1;
+}
+
+static int DiffItem(int *pPast, int *pCurrent, int *pOut, int Size)
+{
+	int Needed = 0;
+	while(Size)
+	{
+		*pOut = *pCurrent-*pPast;
+		Needed |= *pOut;
+		pOut++;
+		pPast++;
+		pCurrent++;
+		Size--;
+	}
+	
+	return Needed;
+}
+
+void CSnapshotDelta::UndiffItem(int *pPast, int *pDiff, int *pOut, int Size)
+{
+	while(Size)
+	{
+		*pOut = *pPast+*pDiff;
+		
+		if(*pDiff == 0)
+			m_aSnapshotDataRate[m_SnapshotCurrent] += 1;
+		else
+		{
+			unsigned char aBuf[16];
+			unsigned char *pEnd = CVariableInt::Pack(aBuf,  *pDiff);
+			m_aSnapshotDataRate[m_SnapshotCurrent] += (int)(pEnd - (unsigned char*)aBuf) * 8;
+		}
+		
+		pOut++;
+		pPast++;
+		pDiff++;
+		Size--;
+	}
+}
+
+CSnapshotDelta::CSnapshotDelta()
+{
+	mem_zero(m_aItemSizes, sizeof(m_aItemSizes));
+	mem_zero(m_aSnapshotDataRate, sizeof(m_aSnapshotDataRate));
+	mem_zero(m_aSnapshotDataUpdates, sizeof(m_aSnapshotDataUpdates));
+	m_SnapshotCurrent = 0;
+	mem_zero(&m_Empty, sizeof(m_Empty));
+}
+
+void CSnapshotDelta::SetStaticsize(int ItemType, int Size)
+{
+	m_aItemSizes[ItemType] = Size;
+}
+
+CSnapshotDelta::CData *CSnapshotDelta::EmptyDelta()
+{
+	return &m_Empty;
+}
+
+// TODO: OPT: this should be made much faster
+int CSnapshotDelta::CreateDelta(CSnapshot *pFrom, CSnapshot *pTo, void *pDstData)
+{
+	CData *pDelta = (CData *)pDstData;
+	int *pData = (int *)pDelta->m_pData;
+	int i, ItemSize, PastIndex;
+	CSnapshotItem *pFromItem;
+	CSnapshotItem *pCurItem;
+	CSnapshotItem *pPastItem;
+	int Count = 0;
+	int SizeCount = 0;
+	
+	pDelta->m_NumDeletedItems = 0;
+	pDelta->m_NumUpdateItems = 0;
+	pDelta->m_NumTempItems = 0;
+	
+	CItemList Hashlist[HASHLIST_SIZE];
+	GenerateHash(Hashlist, pTo);
+
+	// pack deleted stuff
+	for(i = 0; i < pFrom->NumItems(); i++)
+	{
+		pFromItem = pFrom->GetItem(i);
+		if(GetItemIndexHashed(pFromItem->Key(), Hashlist) == -1)
+		{
+			// deleted
+			pDelta->m_NumDeletedItems++;
+			*pData = pFromItem->Key();
+			pData++;
+		}
+	}
+	
+	GenerateHash(Hashlist, pFrom);
+	int aPastIndecies[1024];
+
+	// fetch previous indices
+	// we do this as a separate pass because it helps the cache
+	for(i = 0; i < pTo->NumItems(); i++)
+	{
+		pCurItem = pTo->GetItem(i);  // O(1) .. O(n)
+		aPastIndecies[i] = GetItemIndexHashed(pCurItem->Key(), Hashlist); // O(n) .. O(n^n)
+	}
+		
+	for(i = 0; i < pTo->NumItems(); i++)
+	{
+		// do delta
+		ItemSize = pTo->GetItemSize(i); // O(1) .. O(n)
+		pCurItem = pTo->GetItem(i);  // O(1) .. O(n)
+		PastIndex = aPastIndecies[i];
+		
+		if(PastIndex != -1)
+		{
+			int *pItemDataDst = pData+3;
+	
+			pPastItem = pFrom->GetItem(PastIndex);
+			
+			if(m_aItemSizes[pCurItem->Type()])
+				pItemDataDst = pData+2;
+			
+			if(DiffItem((int*)pPastItem->Data(), (int*)pCurItem->Data(), pItemDataDst, ItemSize/4))
+			{
+				
+				*pData++ = pCurItem->Type();
+				*pData++ = pCurItem->ID();
+				if(!m_aItemSizes[pCurItem->Type()])
+					*pData++ = ItemSize/4;
+				pData += ItemSize/4;
+				pDelta->m_NumUpdateItems++;
+			}
+		}
+		else
+		{
+			*pData++ = pCurItem->Type();
+			*pData++ = pCurItem->ID();
+			if(!m_aItemSizes[pCurItem->Type()])
+				*pData++ = ItemSize/4;
+			
+			mem_copy(pData, pCurItem->Data(), ItemSize);
+			SizeCount += ItemSize;
+			pData += ItemSize/4;
+			pDelta->m_NumUpdateItems++;
+			Count++;
+		}
+	}
+	
+	if(0)
+	{
+		dbg_msg("snapshot", "%d %d %d",
+			pDelta->m_NumDeletedItems,
+			pDelta->m_NumUpdateItems,
+			pDelta->m_NumTempItems);
+	}
+
+	/*
+	// TODO: pack temp stuff
+	
+	// finish
+	//mem_copy(pDelta->offsets, deleted, pDelta->num_deleted_items*sizeof(int));
+	//mem_copy(&(pDelta->offsets[pDelta->num_deleted_items]), update, pDelta->num_update_items*sizeof(int));
+	//mem_copy(&(pDelta->offsets[pDelta->num_deleted_items+pDelta->num_update_items]), temp, pDelta->num_temp_items*sizeof(int));
+	//mem_copy(pDelta->data_start(), data, data_size);
+	//pDelta->data_size = data_size;
+	* */
+	
+	if(!pDelta->m_NumDeletedItems && !pDelta->m_NumUpdateItems && !pDelta->m_NumTempItems)
+		return 0;
+	
+	return (int)((char*)pData-(char*)pDstData);
+}
+
+static int RangeCheck(void *pEnd, void *pPtr, int Size)
+{
+	if((const char *)pPtr + Size > (const char *)pEnd)
+		return -1;
+	return 0;
+}
+
+int CSnapshotDelta::UnpackDelta(CSnapshot *pFrom, CSnapshot *pTo, void *pSrcData, int DataSize)
+{
+	CSnapshotBuilder Builder;
+	CData *pDelta = (CData *)pSrcData;
+	int *pData = (int *)pDelta->m_pData;
+	int *pEnd = (int *)(((char *)pSrcData + DataSize));
+	
+	CSnapshotItem *pFromItem;
+	int Keep, ItemSize;
+	int *pDeleted;
+	int Id, Type, Key;
+	int FromIndex;
+	int *pNewData;
+			
+	Builder.Init();
+	
+	// unpack deleted stuff
+	pDeleted = pData;
+	pData += pDelta->m_NumDeletedItems;
+	if(pData > pEnd)
+		return -1;
+
+	// copy all non deleted stuff
+	for(int i = 0; i < pFrom->NumItems(); i++)
+	{
+		// dbg_assert(0, "fail!");
+		pFromItem = pFrom->GetItem(i);
+		ItemSize = pFrom->GetItemSize(i); 
+		Keep = 1;
+		for(int d = 0; d < pDelta->m_NumDeletedItems; d++)
+		{
+			if(pDeleted[d] == pFromItem->Key())
+			{
+				Keep = 0;
+				break;
+			}
+		}
+		
+		if(Keep)
+		{
+			// keep it
+			mem_copy(
+				Builder.NewItem(pFromItem->Type(), pFromItem->ID(), ItemSize),
+				pFromItem->Data(), ItemSize);
+		}
+	}
+		
+	// unpack updated stuff
+	for(int i = 0; i < pDelta->m_NumUpdateItems; i++)
+	{
+		if(pData+2 > pEnd)
+			return -1;
+		
+		Type = *pData++;
+		Id = *pData++;
+		if(m_aItemSizes[Type])
+			ItemSize = m_aItemSizes[Type];
+		else
+		{
+			if(pData+1 > pEnd)
+				return -2;
+			ItemSize = (*pData++) * 4;
+		}
+		m_SnapshotCurrent = Type;
+		
+		if(RangeCheck(pEnd, pData, ItemSize) || ItemSize < 0) return -3;
+		
+		Key = (Type<<16)|Id;
+		
+		// create the item if needed
+		pNewData = Builder.GetItemData(Key);
+		if(!pNewData)
+			pNewData = (int *)Builder.NewItem(Key>>16, Key&0xffff, ItemSize);
+
+		//if(range_check(pEnd, pNewData, ItemSize)) return -4;
+			
+		FromIndex = pFrom->GetItemIndex(Key);
+		if(FromIndex != -1)
+		{
+			// we got an update so we need pTo apply the diff
+			UndiffItem((int *)pFrom->GetItem(FromIndex)->Data(), pData, pNewData, ItemSize/4);
+			m_aSnapshotDataUpdates[m_SnapshotCurrent]++;
+		}
+		else // no previous, just copy the pData
+		{
+			mem_copy(pNewData, pData, ItemSize);
+			m_aSnapshotDataRate[m_SnapshotCurrent] += ItemSize*8;
+			m_aSnapshotDataUpdates[m_SnapshotCurrent]++;
+		}
+			
+		pData += ItemSize/4;
+	}
+	
+	// finish up
+	return Builder.Finish(pTo);
+}
+
+
+// CSnapshotStorage
+
+void CSnapshotStorage::Init()
+{
+	m_pFirst = 0;
+	m_pLast = 0;
+}
+
+void CSnapshotStorage::PurgeAll()
+{
+	CHolder *pHolder = m_pFirst;
+	CHolder *pNext;
+
+	while(pHolder)
+	{
+		pNext = pHolder->m_pNext;
+		mem_free(pHolder);
+		pHolder = pNext;
+	}
+
+	// no more snapshots in storage
+	m_pFirst = 0;
+	m_pLast = 0;
+}
+
+void CSnapshotStorage::PurgeUntil(int Tick)
+{
+	CHolder *pHolder = m_pFirst;
+	CHolder *pNext;
+	
+	while(pHolder)
+	{
+		pNext = pHolder->m_pNext;
+		if(pHolder->m_Tick >= Tick)
+			return; // no more to remove
+		mem_free(pHolder);
+		
+		// did we come to the end of the list?
+        if (!pNext)
+            break;
+
+		m_pFirst = pNext;
+		pNext->m_pPrev = 0x0;
+		
+		pHolder = pNext;
+	}
+	
+	// no more snapshots in storage
+	m_pFirst = 0;
+	m_pLast = 0;
+}
+
+void CSnapshotStorage::Add(int Tick, int64 Tagtime, int DataSize, void *pData, int CreateAlt)
+{
+	// allocate memory for holder + snapshot_data
+	int TotalSize = sizeof(CHolder)+DataSize;
+	
+	if(CreateAlt)
+		TotalSize += DataSize;
+	
+	CHolder *pHolder = (CHolder *)mem_alloc(TotalSize, 1);
+	
+	// set data
+	pHolder->m_Tick = Tick;
+	pHolder->m_Tagtime = Tagtime;
+	pHolder->m_SnapSize = DataSize;
+	pHolder->m_pSnap = (CSnapshot*)(pHolder+1);
+	mem_copy(pHolder->m_pSnap, pData, DataSize);
+
+	if(CreateAlt) // create alternative if wanted
+	{
+		pHolder->m_pAltSnap = (CSnapshot*)(((char *)pHolder->m_pSnap) + DataSize);
+		mem_copy(pHolder->m_pAltSnap, pData, DataSize);
+	}
+	else
+		pHolder->m_pAltSnap = 0;
+		
+	
+	// link
+	pHolder->m_pNext = 0;
+	pHolder->m_pPrev = m_pLast;
+	if(m_pLast)
+		m_pLast->m_pNext = pHolder;
+	else
+		m_pFirst = pHolder;
+	m_pLast = pHolder;
+}
+
+int CSnapshotStorage::Get(int Tick, int64 *pTagtime, CSnapshot **ppData, CSnapshot **ppAltData)
+{
+	CHolder *pHolder = m_pFirst;
+	
+	while(pHolder)
+	{
+		if(pHolder->m_Tick == Tick)
+		{
+			if(pTagtime)
+				*pTagtime = pHolder->m_Tagtime;
+			if(ppData)
+				*ppData = pHolder->m_pSnap;
+			if(ppAltData)
+				*ppData = pHolder->m_pAltSnap;
+			return pHolder->m_SnapSize;
+		}
+		
+		pHolder = pHolder->m_pNext;
+	}
+	
+	return -1;
+}
+
+// CSnapshotBuilder
+
+void CSnapshotBuilder::Init()
+{
+	m_DataSize = 0;
+	m_NumItems = 0;
+}
+
+CSnapshotItem *CSnapshotBuilder::GetItem(int Index) 
+{
+	return (CSnapshotItem *)&(m_aData[m_aOffsets[Index]]);
+}
+
+int *CSnapshotBuilder::GetItemData(int Key)
+{
+	int i;
+	for(i = 0; i < m_NumItems; i++)
+	{
+		if(GetItem(i)->Key() == Key)
+			return (int *)GetItem(i)->Data();
+	}
+	return 0;
+}
+
+int CSnapshotBuilder::Finish(void *SpnapData)
+{
+	// flattern and make the snapshot
+	CSnapshot *pSnap = (CSnapshot *)SpnapData;
+	int OffsetSize = sizeof(int)*m_NumItems;
+	pSnap->m_DataSize = m_DataSize;
+	pSnap->m_NumItems = m_NumItems;
+	mem_copy(pSnap->Offsets(), m_aOffsets, OffsetSize);
+	mem_copy(pSnap->DataStart(), m_aData, m_DataSize);
+	return sizeof(CSnapshot) + OffsetSize + m_DataSize;
+}
+
+void *CSnapshotBuilder::NewItem(int Type, int ID, int Size)
+{
+	CSnapshotItem *pObj = (CSnapshotItem *)(m_aData + m_DataSize);
+
+	mem_zero(pObj, sizeof(CSnapshotItem) + Size);
+	pObj->m_TypeAndID = (Type<<16)|ID;
+	m_aOffsets[m_NumItems] = m_DataSize;
+	m_DataSize += sizeof(CSnapshotItem) + Size;
+	m_NumItems++;
+	
+	dbg_assert(m_DataSize < CSnapshot::MAX_SIZE, "too much data");
+	dbg_assert(m_NumItems < MAX_ITEMS, "too many items");
+
+	return pObj->Data();
+}
diff --git a/src/engine/e_snapshot.h b/src/engine/shared/snapshot.h
index 60dc254c..ec27d004 100644
--- a/src/engine/e_snapshot.h
+++ b/src/engine/shared/snapshot.h
@@ -1,12 +1,9 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef ENGINE_SNAPSHOT_H
-#define ENGINE_SNAPSHOT_H
+#ifndef ENGINE_SHARED_SNAPSHOT_H
+#define ENGINE_SHARED_SNAPSHOT_H
 
 #include <base/system.h>
 
-/* CSnapshot */
-
-
+// CSnapshot
 
 class CSnapshotItem
 {
@@ -19,48 +16,69 @@ public:
 	int Key() { return m_TypeAndID; }
 };
 
-class CSnapshotDelta
-{
-public:
-	int m_NumDeletedItems;
-	int m_NumUpdateItems;
-	int m_NumTempItems; /* needed? */
-	int m_pData[1];
-};
 
-// TODO: hide a lot of these members
 class CSnapshot
 {
+	friend class CSnapshotBuilder;
+	int m_DataSize;
+	int m_NumItems;
+
+	int *Offsets() const { return (int *)(this+1); }
+	char *DataStart() const { return (char*)(Offsets()+m_NumItems); }
+
 public:
 	enum
 	{
 		MAX_SIZE=64*1024
 	};
 
-	int m_DataSize;
-	int m_NumItems;
-	
-	int *Offsets() const { return (int *)(this+1); }
-	char *DataStart() const { return (char*)(Offsets()+m_NumItems); }
+	void Clear() { m_DataSize = 0; m_NumItems = 0; }
+	int NumItems() const { return m_NumItems; }
 	CSnapshotItem *GetItem(int Index);
 	int GetItemSize(int Index);
 	int GetItemIndex(int Key);
 
 	int Crc();
 	void DebugDump();
+};
 
-	// TODO: move these
-	int GetItemIndexHashed(int Key);
-	int GenerateHash();
-	
-	//
-	static CSnapshotDelta *EmptyDelta();
-	static int CreateDelta(CSnapshot *pFrom, CSnapshot *pTo, void *pData);
-	static int UnpackDelta(CSnapshot *pFrom, CSnapshot *pTo, void *pData, int DataSize);
+
+// CSnapshotDelta
+
+class CSnapshotDelta
+{
+public:
+	class CData
+	{
+	public:
+		int m_NumDeletedItems;
+		int m_NumUpdateItems;
+		int m_NumTempItems; // needed?
+		int m_pData[1];
+	};
+
+private:
+	// TODO: strange arbitrary number
+	short m_aItemSizes[64];
+	int m_aSnapshotDataRate[0xffff];
+	int m_aSnapshotDataUpdates[0xffff];
+	int m_SnapshotCurrent;
+	CData m_Empty;
+
+	void UndiffItem(int *pPast, int *pDiff, int *pOut, int Size);
+
+public:
+	CSnapshotDelta();
+	int GetDataRate(int Index) { return m_aSnapshotDataRate[Index]; }
+	int GetDataUpdates(int Index) { return m_aSnapshotDataUpdates[Index]; }
+	void SetStaticsize(int ItemType, int Size);
+	CData *EmptyDelta();
+	int CreateDelta(class CSnapshot *pFrom, class CSnapshot *pTo, void *pData);
+	int UnpackDelta(class CSnapshot *pFrom, class CSnapshot *pTo, void *pData, int DataSize);
 };
 
-/* CSnapshotStorage */
 
+// CSnapshotStorage
 
 class CSnapshotStorage
 {
@@ -115,4 +133,4 @@ public:
 };
 
 
-#endif /* ENGINE_SNAPSHOT_H */
+#endif // ENGINE_SNAPSHOT_H
diff --git a/src/engine/shared/storage.cpp b/src/engine/shared/storage.cpp
new file mode 100644
index 00000000..491795ad
--- /dev/null
+++ b/src/engine/shared/storage.cpp
@@ -0,0 +1,196 @@
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+#include <base/system.h>
+#include <engine/storage.h>
+#include "engine.h"
+
+// compiled-in data-dir path
+#define DATA_DIR "data"
+
+class CStorage : public IStorage
+{
+public:
+	char m_aApplicationSavePath[512];
+	char m_aDatadir[512];
+	
+	CStorage()
+	{
+		m_aApplicationSavePath[0] = 0;
+		m_aDatadir[0] = 0;
+	}
+	
+	int Init(const char *pApplicationName, const char *pArgv0)
+	{
+		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/downloadedmaps", m_aApplicationSavePath);
+			fs_makedir(aPath);
+
+			str_format(aPath, sizeof(aPath), "%s/demos", m_aApplicationSavePath);
+			fs_makedir(aPath);
+		}
+		
+		return FindDatadir(pArgv0);
+	}
+		
+	int FindDatadir(const char *pArgv0)
+	{
+		// 1) use provided data-dir override
+		if(m_aDatadir[0])
+		{
+			if(fs_is_dir(m_aDatadir))
+				return 0;
+			else
+			{
+				dbg_msg("engine/datadir", "specified data-dir '%s' does not exist", m_aDatadir);
+				return -1;
+			}
+		}
+		
+		// 2) use data-dir in PWD if present
+		if(fs_is_dir("data/mapres"))
+		{
+			str_copy(m_aDatadir, "data", sizeof(m_aDatadir));
+			return 0;
+		}
+		
+		// 3) use compiled-in data-dir if present
+		if (fs_is_dir(DATA_DIR "/mapres"))
+		{
+			str_copy(m_aDatadir, DATA_DIR, sizeof(m_aDatadir));
+			return 0;
+		}
+		
+		// 4) check for usable path in argv[0]
+		{
+			unsigned int Pos = ~0U;
+			for(unsigned i = 0; pArgv0[i]; i++)
+				if(pArgv0[i] == '/')
+					Pos = i;
+			
+			if (Pos < sizeof(m_aDatadir))
+			{
+				char aBaseDir[sizeof(m_aDatadir)];
+				str_copy(aBaseDir, pArgv0, Pos);
+				aBaseDir[Pos] = '\0';
+				str_format(m_aDatadir, sizeof(m_aDatadir), "%s/data", aBaseDir);
+				
+				if (fs_is_dir(m_aDatadir))
+					return 0;
+			}
+		}
+		
+	#if defined(CONF_FAMILY_UNIX)
+		// 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"
+			};
+			const int DirsCount = sizeof(aDirs) / sizeof(aDirs[0]);
+			
+			int i;
+			for (i = 0; i < DirsCount; i++)
+			{
+				if (fs_is_dir(aDirs[i]))
+				{
+					str_copy(m_aDatadir, aDirs[i], sizeof(m_aDatadir));
+					return 0;
+				}
+			}
+		}
+	#endif
+		
+		// no data-dir found
+		dbg_msg("engine/datadir", "warning no data directory found");
+		return -1;
+	}
+
+	virtual void ListDirectory(int Types, const char *pPath, FS_LISTDIR_CALLBACK pfnCallback, void *pUser)
+	{
+		char aBuffer[1024];
+		
+		// list current directory
+		if(Types&TYPE_CURRENT)
+		{
+			fs_listdir(pPath, pfnCallback, pUser);
+		}
+		
+		// list users directory
+		if(Types&TYPE_SAVE)
+		{
+			str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_aApplicationSavePath, pPath);
+			fs_listdir(aBuffer, pfnCallback, pUser);
+		}
+		
+		// list datadir directory
+		if(Types&TYPE_DATA)
+		{
+			str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_aDatadir, pPath);
+			fs_listdir(aBuffer, pfnCallback, pUser);
+		}		
+	}
+	
+	virtual IOHANDLE OpenFile(const char *pFilename, int Flags, char *pBuffer = 0, int BufferSize = 0)
+	{
+		char aBuffer[1024];
+		if(!pBuffer)
+		{
+			pBuffer = aBuffer;
+			BufferSize = sizeof(aBuffer);
+		}
+		
+		if(Flags&IOFLAG_WRITE)
+		{
+			str_format(pBuffer, BufferSize, "%s/%s", m_aApplicationSavePath, pFilename);
+			return io_open(pBuffer, 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;
+		}
+		
+		pBuffer[0] = 0;
+		return 0;		
+	}
+
+	static IStorage *Create(const char *pApplicationName, const char *pArgv0)
+	{
+		CStorage *p = new CStorage();
+		if(p->Init(pApplicationName, pArgv0))
+		{
+			delete p;
+			p = 0;
+		}
+		return p;
+	}
+};
+
+IStorage *CreateStorage(const char *pApplicationName, const char *pArgv0) { return CStorage::Create(pApplicationName, pArgv0); }
diff --git a/src/engine/sound.h b/src/engine/sound.h
new file mode 100644
index 00000000..bbbc4288
--- /dev/null
+++ b/src/engine/sound.h
@@ -0,0 +1,40 @@
+#ifndef ENGINE_SOUND_H
+#define ENGINE_SOUND_H
+
+#include "kernel.h"
+
+class ISound : public IInterface
+{
+	MACRO_INTERFACE("sound", 0)
+public:
+	enum
+	{
+		FLAG_LOOP=1,
+		FLAG_POS=2,
+		FLAG_ALL=3
+	};
+
+	virtual int LoadWV(const char *pFilename) = 0;
+	
+	virtual void SetChannel(int ChannelId, float Volume, float Panning) = 0;
+	virtual void SetListenerPos(float x, float y) = 0;
+	
+	virtual int PlayAt(int ChannelId, int SoundId, int Flags, float x, float y) = 0;
+	virtual int Play(int ChannelId, int SoundId, int Flags) = 0;
+	virtual void Stop(int VoiceId) = 0;
+	virtual void StopAll() = 0;
+};
+
+
+class IEngineSound : public ISound
+{
+	MACRO_INTERFACE("enginesound", 0)
+public:
+	virtual int Init() = 0;
+	virtual int Update() = 0;
+	virtual int Shutdown() = 0;
+};
+
+extern IEngineSound *CreateEngineSound();
+
+#endif
diff --git a/src/engine/storage.h b/src/engine/storage.h
new file mode 100644
index 00000000..4f875d40
--- /dev/null
+++ b/src/engine/storage.h
@@ -0,0 +1,25 @@
+#ifndef ENGINE_STORAGE_H
+#define ENGINE_STORAGE_H
+
+#include "kernel.h"
+
+class IStorage : public IInterface
+{
+	MACRO_INTERFACE("storage", 0)
+public:
+	enum
+	{
+		TYPE_SAVE = 1,
+		TYPE_CURRENT = 2,
+		TYPE_DATA = 4,
+		TYPE_ALL = ~0
+	};
+	
+	virtual void ListDirectory(int Types, const char *pPath, FS_LISTDIR_CALLBACK pfnCallback, void *pUser) = 0;
+	virtual IOHANDLE OpenFile(const char *pFilename, int Flags, char *pBuffer = 0, int BufferSize = 0) = 0;
+};
+
+extern IStorage *CreateStorage(const char *pApplicationName, const char *pArgv0);
+
+
+#endif
diff --git a/src/engine/textrender.h b/src/engine/textrender.h
new file mode 100644
index 00000000..7c7e036b
--- /dev/null
+++ b/src/engine/textrender.h
@@ -0,0 +1,60 @@
+#ifndef ENGINE_TEXTRENDER_H
+#define ENGINE_TEXTRENDER_H
+#include "kernel.h"
+
+enum
+{
+	TEXTFLAG_RENDER=1,
+	TEXTFLAG_ALLOW_NEWLINE=2,
+	TEXTFLAG_STOP_AT_END=4
+};
+
+class CFont;
+
+class CTextCursor
+{
+public:
+	int m_Flags;
+	int m_LineCount;
+	int m_CharCount;
+	
+	float m_StartX;
+	float m_StartY;
+	float m_LineWidth;
+	float m_X, m_Y;
+	
+	struct CFont *m_pFont;
+	float m_FontSize;
+};
+
+class ITextRender : public IInterface
+{
+	MACRO_INTERFACE("textrender", 0)
+public:
+	virtual void SetCursor(CTextCursor *pCursor, float x, float y, float FontSize, int Flags) = 0;
+	
+	virtual CFont *LoadFont(const char *pFilename) = 0;
+	virtual void DestroyFont(CFont *pFont) = 0;
+	
+	virtual void SetDefaultFont(struct CFont *pFont) = 0;
+
+	//
+	virtual void TextEx(CTextCursor *pCursor, const char *pText, int Length) = 0;
+	
+	// old foolish interface
+	virtual void TextColor(float r, float g, float b, float a) = 0;
+	virtual void Text(void *pFontSetV, float x, float y, float Size, const char *pText, int MaxWidth) = 0;
+	virtual float TextWidth(void *pFontSetV, float Size, const char *pText, int Length) = 0;
+	virtual float TextLineCount(void *pFontSetV, float Size, const char *pText, int LineWidth) = 0;
+};
+
+class IEngineTextRender : public ITextRender
+{
+	MACRO_INTERFACE("enginetextrender", 0)
+public:
+	virtual void Init() = 0;
+};
+
+extern IEngineTextRender *CreateEngineTextRender();
+
+#endif
diff --git a/src/game/client/animstate.cpp b/src/game/client/animstate.cpp
index d8c20dec..cb706774 100644
--- a/src/game/client/animstate.cpp
+++ b/src/game/client/animstate.cpp
@@ -1,95 +1,94 @@
 
-#include <base/math.hpp>
-#include <engine/e_client_interface.h>
-#include <game/generated/g_protocol.hpp>
-#include <game/generated/gc_data.hpp>
+#include <base/math.h>
+#include <game/generated/protocol.h>
+#include <game/generated/client_data.h>
 
-#include "animstate.hpp"
+#include "animstate.h"
 
-static void anim_seq_eval(ANIM_SEQUENCE *seq, float time, ANIM_KEYFRAME *frame)
+static void AnimSeqEval(ANIM_SEQUENCE *pSeq, float Time, ANIM_KEYFRAME *pFrame)
 {
-	if(seq->num_frames == 0)
+	if(pSeq->m_NumFrames == 0)
 	{
-		frame->time = 0;
-		frame->x = 0;
-		frame->y = 0;
-		frame->angle = 0;
+		pFrame->m_Time = 0;
+		pFrame->m_X = 0;
+		pFrame->m_Y = 0;
+		pFrame->m_Angle = 0;
 	}
-	else if(seq->num_frames == 1)
+	else if(pSeq->m_NumFrames == 1)
 	{
-		*frame = seq->frames[0];
+		*pFrame = pSeq->m_aFrames[0];
 	}
 	else
 	{
 		//time = max(0.0f, min(1.0f, time / duration)); // TODO: use clamp
-		ANIM_KEYFRAME *frame1 = 0;
-		ANIM_KEYFRAME *frame2 = 0;
-		float blend = 0.0f;
+		ANIM_KEYFRAME *pFrame1 = 0;
+		ANIM_KEYFRAME *pFrame2 = 0;
+		float Blend = 0.0f;
 
 		// TODO: make this smarter.. binary search
-		for (int i = 1; i < seq->num_frames; i++)
+		for (int i = 1; i < pSeq->m_NumFrames; i++)
 		{
-			if (seq->frames[i-1].time <= time && seq->frames[i].time >= time)
+			if (pSeq->m_aFrames[i-1].m_Time <= Time && pSeq->m_aFrames[i].m_Time >= Time)
 			{
-				frame1 = &seq->frames[i-1];
-				frame2 = &seq->frames[i];
-				blend = (time - frame1->time) / (frame2->time - frame1->time);
+				pFrame1 = &pSeq->m_aFrames[i-1];
+				pFrame2 = &pSeq->m_aFrames[i];
+				Blend = (Time - pFrame1->m_Time) / (pFrame2->m_Time - pFrame1->m_Time);
 				break;
 			}
 		}
 
-		if (frame1 && frame2)
+		if (pFrame1 && pFrame2)
 		{
-			frame->time = time;
-			frame->x = mix(frame1->x, frame2->x, blend);
-			frame->y = mix(frame1->y, frame2->y, blend);
-			frame->angle = mix(frame1->angle, frame2->angle, blend);
+			pFrame->m_Time = Time;
+			pFrame->m_X = mix(pFrame1->m_X, pFrame2->m_X, Blend);
+			pFrame->m_Y = mix(pFrame1->m_Y, pFrame2->m_Y, Blend);
+			pFrame->m_Angle = mix(pFrame1->m_Angle, pFrame2->m_Angle, Blend);
 		}
 	}
 }
 
-static void anim_add_keyframe(ANIM_KEYFRAME *seq, ANIM_KEYFRAME *added, float amount)
+static void AnimAddKeyframe(ANIM_KEYFRAME *pSeq, ANIM_KEYFRAME *pAdded, float Amount)
 {
-	seq->x += added->x*amount;
-	seq->y += added->y*amount;
-	seq->angle += added->angle*amount;
+	pSeq->m_X += pAdded->m_X*Amount;
+	pSeq->m_Y += pAdded->m_Y*Amount;
+	pSeq->m_Angle += pAdded->m_Angle*Amount;
 }
 
-static void anim_add(ANIMSTATE *state, ANIMSTATE *added, float amount)
+static void AnimAdd(CAnimState *pState, CAnimState *pAdded, float Amount)
 {
-	anim_add_keyframe(&state->body, &added->body, amount);
-	anim_add_keyframe(&state->back_foot, &added->back_foot, amount);
-	anim_add_keyframe(&state->front_foot, &added->front_foot, amount);
-	anim_add_keyframe(&state->attach, &added->attach, amount);
+	AnimAddKeyframe(pState->GetBody(), pAdded->GetBody(), Amount);
+	AnimAddKeyframe(pState->GetBackFoot(), pAdded->GetBackFoot(), Amount);
+	AnimAddKeyframe(pState->GetFrontFoot(), pAdded->GetFrontFoot(), Amount);
+	AnimAddKeyframe(pState->GetAttach(), pAdded->GetAttach(), Amount);
 }
 
 
-void ANIMSTATE::set(ANIMATION *anim, float time)
+void CAnimState::Set(ANIMATION *pAnim, float Time)
 {
-	anim_seq_eval(&anim->body, time, &body);
-	anim_seq_eval(&anim->back_foot, time, &back_foot);
-	anim_seq_eval(&anim->front_foot, time, &front_foot);
-	anim_seq_eval(&anim->attach, time, &attach);
+	AnimSeqEval(&pAnim->m_Body, Time, &m_Body);
+	AnimSeqEval(&pAnim->m_BackFoot, Time, &m_BackFoot);
+	AnimSeqEval(&pAnim->m_FrontFoot, Time, &m_FrontFoot);
+	AnimSeqEval(&pAnim->m_Attach, Time, &m_Attach);
 }
 
-void ANIMSTATE::add(ANIMATION *anim, float time, float amount)
+void CAnimState::Add(ANIMATION *pAnim, float Time, float Amount)
 {
-	ANIMSTATE add;
-	add.set(anim, time);
-	anim_add(this, &add, amount);
+	CAnimState Add;
+	Add.Set(pAnim, Time);
+	AnimAdd(this, &Add, Amount);
 }
 
-ANIMSTATE *ANIMSTATE::get_idle()
+CAnimState *CAnimState::GetIdle()
 {
-	static ANIMSTATE state;
-	static bool init = true;
+	static CAnimState State;
+	static bool Init = true;
 	
-	if(init)
+	if(Init)
 	{
-		state.set(&data->animations[ANIM_BASE], 0);
-		state.add(&data->animations[ANIM_IDLE], 0, 1.0f);
-		init = false;
+		State.Set(&g_pData->m_aAnimations[ANIM_BASE], 0);
+		State.Add(&g_pData->m_aAnimations[ANIM_IDLE], 0, 1.0f);
+		Init = false;
 	}
 	
-	return &state;
+	return &State;
 }
diff --git a/src/game/client/animstate.h b/src/game/client/animstate.h
new file mode 100644
index 00000000..e7fce9a1
--- /dev/null
+++ b/src/game/client/animstate.h
@@ -0,0 +1,22 @@
+#ifndef GAME_CLIENT_ANIMSTATE_H
+#define GAME_CLIENT_ANIMSTATE_H
+
+class CAnimState
+{
+	ANIM_KEYFRAME m_Body;
+	ANIM_KEYFRAME m_BackFoot;
+	ANIM_KEYFRAME m_FrontFoot;
+	ANIM_KEYFRAME m_Attach;
+
+public:
+	ANIM_KEYFRAME *GetBody() { return &m_Body; };
+	ANIM_KEYFRAME *GetBackFoot() { return &m_BackFoot; };
+	ANIM_KEYFRAME *GetFrontFoot() { return &m_FrontFoot; };
+	ANIM_KEYFRAME *GetAttach() { return &m_Attach; };
+	void Set(ANIMATION *pAnim, float Time);
+	void Add(ANIMATION *pAdded, float Time, float Amount);
+	
+	static CAnimState *GetIdle();
+};
+
+#endif
diff --git a/src/game/client/animstate.hpp b/src/game/client/animstate.hpp
deleted file mode 100644
index 4b84dd66..00000000
--- a/src/game/client/animstate.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef GAME_CLIENT_ANIMATION_H
-#define GAME_CLIENT_ANIMATION_H
-
-class ANIMSTATE
-{
-public:
-	ANIM_KEYFRAME body;
-	ANIM_KEYFRAME back_foot;
-	ANIM_KEYFRAME front_foot;
-	ANIM_KEYFRAME attach;
-	
-	void set(ANIMATION *anim, float time);
-	void add(ANIMATION *added, float time, float amount);
-	
-	static ANIMSTATE *get_idle();
-};
-
-//void anim_seq_eval(ANIM_SEQUENCE *seq, float time, ANIM_KEYFRAME *frame);
-//void anim_eval(ANIMATION *anim, float time, ANIM_STATE *state);
-//void anim_add_keyframe(ANIM_KEYFRAME *seq, ANIM_KEYFRAME *added, float amount);
-//void anim_add(ANIM_STATE *state, ANIM_STATE *added, float amount);
-//void anim_eval_add(ANIM_STATE *state, ANIMATION *anim, float time, float amount);
-
-#endif
diff --git a/src/game/client/clienthooks.cpp b/src/game/client/clienthooks.cpp
deleted file mode 100644
index 76fa8dcd..00000000
--- a/src/game/client/clienthooks.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-#include <string.h>
-#include <engine/e_client_interface.h>
-#include <game/version.hpp>
-
-#include "gameclient.hpp"
-#include "components/console.hpp"
-
-
-
-// clean hooks
-void modc_entergame() {}
-void modc_shutdown() {}
-void modc_console_init() { gameclient.on_console_init(); }
-void modc_save_config() { gameclient.on_save(); }
-void modc_init() { gameclient.on_init(); }
-void modc_connected() { gameclient.on_connected(); }
-void modc_predict() { gameclient.on_predict(); }
-void modc_newsnapshot() { gameclient.on_snapshot(); }
-int modc_snap_input(int *data) { return gameclient.on_snapinput(data); }
-void modc_statechange(int state, int old) { gameclient.on_statechange(state, old); }
-void modc_render() { gameclient.on_render(); }
-void modc_message(int msgtype) { gameclient.on_message(msgtype); }
-void modc_rcon_line(const char *line) { gameclient.console->print_line(1, line); }
-
-const char *modc_net_version() { return GAME_NETVERSION; }
-const char *modc_getitemname(int type) { return netobj_get_name(type); }
-
diff --git a/src/game/client/component.h b/src/game/client/component.h
new file mode 100644
index 00000000..410be623
--- /dev/null
+++ b/src/game/client/component.h
@@ -0,0 +1,43 @@
+#ifndef GAME_CLIENT_COMPONENT_H
+#define GAME_CLIENT_COMPONENT_H
+
+#include <engine/input.h>
+#include "gameclient.h"
+
+class CComponent
+{
+protected:
+	friend class CGameClient;
+
+	CGameClient *m_pClient;
+	
+	// perhaps propagte pointers for these as well
+	class IKernel *Kernel() const { return m_pClient->Kernel(); }
+	class IGraphics *Graphics() const { return m_pClient->Graphics(); }
+	class ITextRender *TextRender() const { return m_pClient->TextRender(); }
+	class IClient *Client() const { return m_pClient->Client(); }
+	class IInput *Input() const { return m_pClient->Input(); }
+	class IStorage *Storage() const { return m_pClient->Storage(); }
+	class CUI *UI() const { return m_pClient->UI(); }
+	class ISound *Sound() const { return m_pClient->Sound(); }
+	class CRenderTools *RenderTools() const { return m_pClient->RenderTools(); }
+	class IConsole *Console() const { return m_pClient->Console(); }
+	class IDemoPlayer *DemoPlayer() const { return m_pClient->DemoPlayer(); }
+	class IServerBrowser *ServerBrowser() const { return m_pClient->ServerBrowser(); }
+	class CLayers *Layers() const { return m_pClient->Layers(); }
+	class CCollision *Collision() const { return m_pClient->Collision(); }
+public:
+	virtual ~CComponent() {}
+	
+	virtual void OnStateChange(int NewState, int OldState) {};
+	virtual void OnConsoleInit() {};
+	virtual void OnInit() {};
+	virtual void OnReset() {};
+	virtual void OnRender() {};
+	virtual void OnMapLoad() {};
+	virtual void OnMessage(int Msg, void *pRawMsg) {}
+	virtual bool OnMouseMove(float x, float y) { return false; }
+	virtual bool OnInput(IInput::CEvent e) { return false; }
+};
+
+#endif
diff --git a/src/game/client/component.hpp b/src/game/client/component.hpp
deleted file mode 100644
index 6534e56b..00000000
--- a/src/game/client/component.hpp
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef GAME_CLIENT_GAMESYSTEM_H
-#define GAME_CLIENT_GAMESYSTEM_H
-
-#include <engine/e_client_interface.h>
-#include "gameclient.hpp"
-
-class GAMECLIENT;
-
-class COMPONENT
-{
-protected:
-	friend class GAMECLIENT;
-
-	GAMECLIENT *client;
-	
-	// perhaps propagte pointers for these as well
-	class IGraphics *Graphics() const { return client->Graphics(); }
-	class CUI *UI() const { return client->UI(); }
-	class CRenderTools *RenderTools() const { return client->RenderTools(); }
-public:
-	virtual ~COMPONENT() {}
-	
-	virtual void on_statechange(int new_state, int old_state) {};
-	virtual void on_console_init() {};
-	virtual void on_init() {};
-	virtual void on_save() {};
-	virtual void on_reset() {};
-	virtual void on_render() {};
-	virtual void on_mapload() {};
-	virtual void on_message(int msg, void *rawmsg) {}
-	virtual bool on_mousemove(float x, float y) { return false; }
-	virtual bool on_input(INPUT_EVENT e) { return false; }
-};
-
-#endif
diff --git a/src/game/client/components/binds.cpp b/src/game/client/components/binds.cpp
index e4252656..533658f2 100644
--- a/src/game/client/components/binds.cpp
+++ b/src/game/client/components/binds.cpp
@@ -1,184 +1,188 @@
-#include <stdlib.h> // atoi
-#include <string.h> // strcmp
-#include <engine/e_client_interface.h>
-#include "binds.hpp"
+#include <engine/config.h>
+#include <engine/shared/config.h>
+#include "binds.h"
 
-bool BINDS::BINDS_SPECIAL::on_input(INPUT_EVENT e)
+bool CBinds::CBindsSpecial::OnInput(IInput::CEvent Event)
 {
 	// don't handle invalid events and keys that arn't set to anything
-	if(e.key >= KEY_F1 && e.key <= KEY_F15 && binds->keybindings[e.key][0] != 0)
+	if(Event.m_Key >= KEY_F1 && Event.m_Key <= KEY_F15 && m_pBinds->m_aaKeyBindings[Event.m_Key][0] != 0)
 	{
-		int stroke = 0;
-		if(e.flags&INPFLAG_PRESS)
-			stroke = 1;
-		console_execute_line_stroked(stroke, binds->keybindings[e.key]);
+		int Stroke = 0;
+		if(Event.m_Flags&IInput::FLAG_PRESS)
+			Stroke = 1;
+			
+		m_pBinds->GetConsole()->ExecuteLineStroked(Stroke, m_pBinds->m_aaKeyBindings[Event.m_Key]);
 		return true;
 	}
 	
 	return false;
 }
 
-BINDS::BINDS()
+CBinds::CBinds()
 {
-	mem_zero(keybindings, sizeof(keybindings));
-	special_binds.binds = this;
+	mem_zero(m_aaKeyBindings, sizeof(m_aaKeyBindings));
+	m_SpecialBinds.m_pBinds = this;
 }
 
-void BINDS::bind(int keyid, const char *str)
+void CBinds::Bind(int KeyId, const char *pStr)
 {
-	if(keyid < 0 || keyid >= KEY_LAST)
+	if(KeyId < 0 || KeyId >= KEY_LAST)
 		return;
 		
-	str_copy(keybindings[keyid], str, sizeof(keybindings[keyid]));
-	if(!keybindings[keyid][0])
-		dbg_msg("binds", "unbound %s (%d)", inp_key_name(keyid), keyid);
+	str_copy(m_aaKeyBindings[KeyId], pStr, sizeof(m_aaKeyBindings[KeyId]));
+	if(!m_aaKeyBindings[KeyId][0])
+		dbg_msg("binds", "unbound %s (%d)", Input()->KeyName(KeyId), KeyId);
 	else
-		dbg_msg("binds", "bound %s (%d) = %s", inp_key_name(keyid), keyid, keybindings[keyid]);
+		dbg_msg("binds", "bound %s (%d) = %s", Input()->KeyName(KeyId), KeyId, m_aaKeyBindings[KeyId]);
 }
 
 
-bool BINDS::on_input(INPUT_EVENT e)
+bool CBinds::OnInput(IInput::CEvent e)
 {
 	// don't handle invalid events and keys that arn't set to anything
-	if(e.key <= 0 || e.key >= KEY_LAST || keybindings[e.key][0] == 0)
+	if(e.m_Key <= 0 || e.m_Key >= KEY_LAST || m_aaKeyBindings[e.m_Key][0] == 0)
 		return false;
 
-	int stroke = 0;
-	if(e.flags&INPFLAG_PRESS)
-		stroke = 1;
-	console_execute_line_stroked(stroke, keybindings[e.key]);
+	int Stroke = 0;
+	if(e.m_Flags&IInput::FLAG_PRESS)
+		Stroke = 1;
+	Console()->ExecuteLineStroked(Stroke, m_aaKeyBindings[e.m_Key]);
 	return true;
 }
 
-void BINDS::unbindall()
+void CBinds::UnbindAll()
 {
 	for(int i = 0; i < KEY_LAST; i++)
-		keybindings[i][0] = 0;
+		m_aaKeyBindings[i][0] = 0;
 }
 
-const char *BINDS::get(int keyid)
+const char *CBinds::Get(int KeyId)
 {
-	if(keyid > 0 && keyid < KEY_LAST)
-		return keybindings[keyid];
+	if(KeyId > 0 && KeyId < KEY_LAST)
+		return m_aaKeyBindings[KeyId];
 	return "";
 }
 
-const char *BINDS::get_key(const char *bindstr)
+const char *CBinds::GetKey(const char *pBindStr)
 {
-	for(int keyid = 0; keyid < KEY_LAST; keyid++)
+	for(int KeyId = 0; KeyId < KEY_LAST; KeyId++)
 	{
-		const char *bind = get(keyid);
-		if(!bind[0])
+		const char *pBind = Get(KeyId);
+		if(!pBind[0])
 			continue;
 			
-		if(strcmp(bind, bindstr) == 0)
-			return inp_key_name(keyid);
+		if(str_comp(pBind, pBindStr) == 0)
+			return Input()->KeyName(KeyId);
 	}
 	
 	return "";
 }
 
-void BINDS::set_defaults()
+void CBinds::SetDefaults()
 {
 	// set default key bindings
-	unbindall();
-	bind(KEY_F1, "toggle_local_console");
-	bind(KEY_F2, "toggle_remote_console");
-	bind(KEY_TAB, "+scoreboard");
-	bind(KEY_F10, "screenshot");
-
-	bind('a', "+left");
-	bind('d', "+right");
-
-	bind(KEY_SPACE, "+jump");
-	bind(KEY_MOUSE_1, "+fire");
-	bind(KEY_MOUSE_2, "+hook");
-	bind(KEY_LSHIFT, "+emote");
-
-	bind('1', "+weapon1");
-	bind('2', "+weapon2");
-	bind('3', "+weapon3");
-	bind('4', "+weapon4");
-	bind('5', "+weapon5");
+	UnbindAll();
+	Bind(KEY_F1, "toggle_local_console");
+	Bind(KEY_F2, "toggle_remote_console");
+	Bind(KEY_TAB, "+scoreboard");
+	Bind(KEY_F10, "screenshot");
+
+	Bind('a', "+left");
+	Bind('d', "+right");
+
+	Bind(KEY_SPACE, "+jump");
+	Bind(KEY_MOUSE_1, "+fire");
+	Bind(KEY_MOUSE_2, "+hook");
+	Bind(KEY_LSHIFT, "+emote");
+
+	Bind('1', "+weapon1");
+	Bind('2', "+weapon2");
+	Bind('3', "+weapon3");
+	Bind('4', "+weapon4");
+	Bind('5', "+weapon5");
 	
-	bind(KEY_MOUSE_WHEEL_UP, "+prevweapon");
-	bind(KEY_MOUSE_WHEEL_DOWN, "+nextweapon");
+	Bind(KEY_MOUSE_WHEEL_UP, "+prevweapon");
+	Bind(KEY_MOUSE_WHEEL_DOWN, "+nextweapon");
 	
-	bind('t', "chat all");
-	bind('y', "chat team");	
+	Bind('t', "chat all");
+	Bind('y', "chat team");	
 
-	bind(KEY_F3, "vote yes");
-	bind(KEY_F4, "vote no");	
+	Bind(KEY_F3, "vote yes");
+	Bind(KEY_F4, "vote no");	
 }
 
-void BINDS::on_console_init()
+void CBinds::OnConsoleInit()
 {
 	// bindings
-	MACRO_REGISTER_COMMAND("bind", "sr", CFGFLAG_CLIENT, con_bind, this, "Bind key to execute the command");
-	MACRO_REGISTER_COMMAND("unbind", "s", CFGFLAG_CLIENT, con_unbind, this, "Unbind key");
-	MACRO_REGISTER_COMMAND("unbindall", "", CFGFLAG_CLIENT, con_unbindall, this, "Unbind all keys");
-	MACRO_REGISTER_COMMAND("dump_binds", "", CFGFLAG_CLIENT, con_dump_binds, this, "Dump binds");
+	IConfig *pConfig = Kernel()->RequestInterface<IConfig>();
+	if(pConfig)
+		pConfig->RegisterCallback(ConfigSaveCallback, this);
+	
+	Console()->Register("bind", "sr", CFGFLAG_CLIENT, ConBind, this, "Bind key to execute the command");
+	Console()->Register("unbind", "s", CFGFLAG_CLIENT, ConUnbind, this, "Unbind key");
+	Console()->Register("unbindall", "", CFGFLAG_CLIENT, ConUnbindAll, this, "Unbind all keys");
+	Console()->Register("dump_binds", "", CFGFLAG_CLIENT, ConDumpBinds, this, "Dump binds");
 	
 	// default bindings
-	set_defaults();
+	SetDefaults();
 }
 
-void BINDS::con_bind(void *result, void *user_data)
+void CBinds::ConBind(IConsole::IResult *pResult, void *pUserData)
 {
-	BINDS *binds = (BINDS *)user_data;
-	const char *key_name = console_arg_string(result, 0);
-	int id = binds->get_key_id(key_name);
+	CBinds *pBinds = (CBinds *)pUserData;
+	const char *pKeyName = pResult->GetString(0);
+	int id = pBinds->GetKeyId(pKeyName);
 	
 	if(!id)
 	{
-		dbg_msg("binds", "key %s not found", key_name);
+		dbg_msg("binds", "key %s not found", pKeyName);
 		return;
 	}
 	
-	binds->bind(id, console_arg_string(result, 1));
+	pBinds->Bind(id, pResult->GetString(1));
 }
 
 
-void BINDS::con_unbind(void *result, void *user_data)
+void CBinds::ConUnbind(IConsole::IResult *pResult, void *pUserData)
 {
-	BINDS *binds = (BINDS *)user_data;
-	const char *key_name = console_arg_string(result, 0);
-	int id = binds->get_key_id(key_name);
+	CBinds *pBinds = (CBinds *)pUserData;
+	const char *pKeyName = pResult->GetString(0);
+	int id = pBinds->GetKeyId(pKeyName);
 	
 	if(!id)
 	{
-		dbg_msg("binds", "key %s not found", key_name);
+		dbg_msg("binds", "key %s not found", pKeyName);
 		return;
 	}
 	
-	binds->bind(id, "");
+	pBinds->Bind(id, "");
 }
 
 
-void BINDS::con_unbindall(void *result, void *user_data)
+void CBinds::ConUnbindAll(IConsole::IResult *pResult, void *pUserData)
 {
-	BINDS *binds = (BINDS *)user_data;
-	binds->unbindall();
+	CBinds *pBinds = (CBinds *)pUserData;
+	pBinds->UnbindAll();
 }
 
 
-void BINDS::con_dump_binds(void *result, void *user_data)
+void CBinds::ConDumpBinds(IConsole::IResult *pResult, void *pUserData)
 {
-	BINDS *binds = (BINDS *)user_data;
+	CBinds *pBinds = (CBinds *)pUserData;
 	for(int i = 0; i < KEY_LAST; i++)
 	{
-		if(binds->keybindings[i][0] == 0)
+		if(pBinds->m_aaKeyBindings[i][0] == 0)
 			continue;
-		dbg_msg("binds", "%s (%d) = %s", inp_key_name(i), i, binds->keybindings[i]);
+		dbg_msg("binds", "%s (%d) = %s", pBinds->Input()->KeyName(i), i, pBinds->m_aaKeyBindings[i]);
 	}
 }
 
-int BINDS::get_key_id(const char *key_name)
+int CBinds::GetKeyId(const char *pKeyName)
 {
 	// check for numeric
-	if(key_name[0] == '&')
+	if(pKeyName[0] == '&')
 	{
-		int i = atoi(key_name+1);
+		int i = str_toint(pKeyName+1);
 		if(i > 0 && i < KEY_LAST)
 			return i; // numeric
 	}
@@ -186,37 +190,39 @@ int BINDS::get_key_id(const char *key_name)
 	// search for key
 	for(int i = 0; i < KEY_LAST; i++)
 	{
-		if(strcmp(key_name, inp_key_name(i)) == 0)
+		if(str_comp(pKeyName, Input()->KeyName(i)) == 0)
 			return i;
 	}
 	
 	return 0;
 }
 
-void BINDS::on_save()
+void CBinds::ConfigSaveCallback(IConfig *pConfig, void *pUserData)
 {
-	char buffer[256];
-	char *end = buffer+sizeof(buffer)-8;
-	client_save_line("unbindall");
+	CBinds *pSelf = (CBinds *)pUserData;
+	
+	char aBuffer[256];
+	char *pEnd = aBuffer+sizeof(aBuffer)-8;
+	pConfig->WriteLine("unbindall");
 	for(int i = 0; i < KEY_LAST; i++)
 	{
-		if(keybindings[i][0] == 0)
+		if(pSelf->m_aaKeyBindings[i][0] == 0)
 			continue;
-		str_format(buffer, sizeof(buffer), "bind %s ", inp_key_name(i));
+		str_format(aBuffer, sizeof(aBuffer), "bind %s ", pSelf->Input()->KeyName(i));
 		
 		// process the string. we need to escape some characters
-		const char *src = keybindings[i];
-		char *dst = buffer + strlen(buffer);
-		*dst++ = '"';
-		while(*src && dst < end)
+		const char *pSrc = pSelf->m_aaKeyBindings[i];
+		char *pDst = aBuffer + str_length(aBuffer);
+		*pDst++ = '"';
+		while(*pSrc && pDst < pEnd)
 		{
-			if(*src == '"' || *src == '\\') // escape \ and "
-				*dst++ = '\\';
-			*dst++ = *src++;
+			if(*pSrc == '"' || *pSrc == '\\') // escape \ and "
+				*pDst++ = '\\';
+			*pDst++ = *pSrc++;
 		}
-		*dst++ = '"';
-		*dst++ = 0;
+		*pDst++ = '"';
+		*pDst++ = 0;
 		
-		client_save_line(buffer);
+		pConfig->WriteLine(aBuffer);
 	}
 }
diff --git a/src/game/client/components/binds.h b/src/game/client/components/binds.h
new file mode 100644
index 00000000..e8393979
--- /dev/null
+++ b/src/game/client/components/binds.h
@@ -0,0 +1,41 @@
+#ifndef GAME_CLIENT_COMPONENTS_BINDS_H
+#define GAME_CLIENT_COMPONENTS_BINDS_H
+#include <game/client/component.h>
+#include <engine/keys.h>
+
+class CBinds : public CComponent
+{
+	char m_aaKeyBindings[KEY_LAST][128];
+
+	int GetKeyId(const char *pKeyName);
+
+	static void ConBind(IConsole::IResult *pResult, void *pUserData);
+	static void ConUnbind(IConsole::IResult *pResult, void *pUserData);
+	static void ConUnbindAll(IConsole::IResult *pResult, void *pUserData);
+	static void ConDumpBinds(IConsole::IResult *pResult, void *pUserData);
+	class IConsole *GetConsole() const { return Console(); }
+	
+	static void ConfigSaveCallback(class IConfig *pConfig, void *pUserData);
+	
+public:
+	CBinds();
+	
+	class CBindsSpecial : public CComponent
+	{
+	public:
+		CBinds *m_pBinds;
+		virtual bool OnInput(IInput::CEvent Event);
+	};
+	
+	CBindsSpecial m_SpecialBinds;
+	
+	void Bind(int KeyId, const char *pStr);
+	void SetDefaults();
+	void UnbindAll();
+	const char *Get(int KeyId);
+	const char *GetKey(const char *pBindStr);
+	
+	virtual void OnConsoleInit();
+	virtual bool OnInput(IInput::CEvent Event);
+};
+#endif
diff --git a/src/game/client/components/binds.hpp b/src/game/client/components/binds.hpp
deleted file mode 100644
index bdf242f9..00000000
--- a/src/game/client/components/binds.hpp
+++ /dev/null
@@ -1,35 +0,0 @@
-#include <game/client/component.hpp>
-
-class BINDS : public COMPONENT
-{
-	char keybindings[KEY_LAST][128];
-
-	int get_key_id(const char *key_name);
-
-	static void con_bind(void *result, void *user_data);
-	static void con_unbind(void *result, void *user_data);
-	static void con_unbindall(void *result, void *user_data);
-	static void con_dump_binds(void *result, void *user_data);
-	
-public:
-	BINDS();
-	
-	class BINDS_SPECIAL : public COMPONENT
-	{
-	public:
-		BINDS *binds;
-		virtual bool on_input(INPUT_EVENT e);
-	};
-	
-	BINDS_SPECIAL special_binds;
-	
-	void bind(int keyid, const char *str);
-	void set_defaults();
-	void unbindall();
-	const char *get(int keyid);
-	const char *get_key(const char *bindstr);
-	
-	virtual void on_save();
-	virtual void on_console_init();
-	virtual bool on_input(INPUT_EVENT e);
-};
diff --git a/src/game/client/components/broadcast.cpp b/src/game/client/components/broadcast.cpp
index b86ed658..c3eb3b56 100644
--- a/src/game/client/components/broadcast.cpp
+++ b/src/game/client/components/broadcast.cpp
@@ -1,36 +1,36 @@
-#include <engine/e_client_interface.h>
-#include <engine/e_config.h>
-#include <engine/client/graphics.h>
-#include <game/generated/g_protocol.hpp>
-#include <game/generated/gc_data.hpp>
+#include <engine/shared/config.h>
+#include <engine/graphics.h>
+#include <engine/textrender.h>
+#include <game/generated/protocol.h>
+#include <game/generated/client_data.h>
 
-#include <game/client/gameclient.hpp>
+#include <game/client/gameclient.h>
 
-#include "broadcast.hpp"
+#include "broadcast.h"
 	
-void BROADCAST::on_reset()
+void CBroadcast::OnReset()
 {
-	broadcast_time = 0;
+	m_BroadcastTime = 0;
 }
 
-void BROADCAST::on_render()
+void CBroadcast::OnRender()
 {
 	Graphics()->MapScreen(0, 0, 300*Graphics()->ScreenAspect(), 300);
 		
-	if(time_get() < broadcast_time)
+	if(time_get() < m_BroadcastTime)
 	{
-		float w = gfx_text_width(0, 14, broadcast_text, -1);
-		gfx_text(0, 150*Graphics()->ScreenAspect()-w/2, 35, 14, broadcast_text, -1);
+		float w = TextRender()->TextWidth(0, 14, m_aBroadcastText, -1);
+		TextRender()->Text(0, 150*Graphics()->ScreenAspect()-w/2, 35, 14, m_aBroadcastText, -1);
 	}
 }
 
-void BROADCAST::on_message(int msgtype, void *rawmsg)
+void CBroadcast::OnMessage(int MsgType, void *pRawMsg)
 {
-	if(msgtype == NETMSGTYPE_SV_BROADCAST)
+	if(MsgType == NETMSGTYPE_SV_BROADCAST)
 	{
-		NETMSG_SV_BROADCAST *msg = (NETMSG_SV_BROADCAST *)rawmsg;
-		str_copy(broadcast_text, msg->message, sizeof(broadcast_text));
-		broadcast_time = time_get()+time_freq()*10;
+		CNetMsg_Sv_Broadcast *pMsg = (CNetMsg_Sv_Broadcast *)pRawMsg;
+		str_copy(m_aBroadcastText, pMsg->m_pMessage, sizeof(m_aBroadcastText));
+		m_BroadcastTime = time_get()+time_freq()*10;
 	}
 }
 
diff --git a/src/game/client/components/broadcast.h b/src/game/client/components/broadcast.h
new file mode 100644
index 00000000..ed281a2f
--- /dev/null
+++ b/src/game/client/components/broadcast.h
@@ -0,0 +1,17 @@
+#ifndef GAME_CLIENT_COMPONENTS_BROADCAST_H
+#define GAME_CLIENT_COMPONENTS_BROADCAST_H
+#include <game/client/component.h>
+
+class CBroadcast : public CComponent
+{
+public:
+	// broadcasts
+	char m_aBroadcastText[1024];
+	int64 m_BroadcastTime;
+	
+	virtual void OnReset();
+	virtual void OnRender();
+	virtual void OnMessage(int MsgType, void *pRawMsg);
+};
+
+#endif
diff --git a/src/game/client/components/broadcast.hpp b/src/game/client/components/broadcast.hpp
deleted file mode 100644
index 102201cc..00000000
--- a/src/game/client/components/broadcast.hpp
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <game/client/component.hpp>
-
-class BROADCAST : public COMPONENT
-{
-public:
-	// broadcasts
-	char broadcast_text[1024];
-	int64 broadcast_time;
-	
-	virtual void on_reset();
-	virtual void on_render();
-	virtual void on_message(int msgtype, void *rawmsg);
-};
-
diff --git a/src/game/client/components/camera.cpp b/src/game/client/components/camera.cpp
index 7b188e00..96baf459 100644
--- a/src/game/client/components/camera.cpp
+++ b/src/game/client/components/camera.cpp
@@ -1,40 +1,37 @@
-extern "C" {
-	#include <engine/e_config.h>
-	#include <engine/e_client_interface.h>
-}
+#include <engine/shared/config.h>
 
-#include <base/math.hpp>
-#include <game/collision.hpp>
-#include <game/client/gameclient.hpp>
-#include <game/client/component.hpp>
+#include <base/math.h>
+#include <game/collision.h>
+#include <game/client/gameclient.h>
+#include <game/client/component.h>
 
-#include "camera.hpp"
-#include "controls.hpp"
+#include "camera.h"
+#include "controls.h"
 
-CAMERA::CAMERA()
+CCamera::CCamera()
 {
 }
 
-void CAMERA::on_render()
+void CCamera::OnRender()
 {
 	//vec2 center;
-	zoom = 1.0f;
+	m_Zoom = 1.0f;
 
 	// update camera center		
-	if(gameclient.snap.spectate)
-		center = gameclient.controls->mouse_pos;
+	if(m_pClient->m_Snap.m_Spectate)
+		m_Center = m_pClient->m_pControls->m_MousePos;
 	else
 	{
 
-		float l = length(gameclient.controls->mouse_pos);
-		float deadzone = config.cl_mouse_deadzone;
-		float follow_factor = config.cl_mouse_followfactor/100.0f;
-		vec2 camera_offset(0, 0);
+		float l = length(m_pClient->m_pControls->m_MousePos);
+		float DeadZone = g_Config.m_ClMouseDeadzone;
+		float FollowFactor = g_Config.m_ClMouseFollowfactor/100.0f;
+		vec2 CameraOffset(0, 0);
 
-		float offset_amount = max(l-deadzone, 0.0f) * follow_factor;
+		float OffsetAmount = max(l-DeadZone, 0.0f) * FollowFactor;
 		if(l > 0.0001f) // make sure that this isn't 0
-			camera_offset = normalize(gameclient.controls->mouse_pos)*offset_amount;
+			CameraOffset = normalize(m_pClient->m_pControls->m_MousePos)*OffsetAmount;
 		
-		center = gameclient.local_character_pos + camera_offset;
+		m_Center = m_pClient->m_LocalCharacterPos + CameraOffset;
 	}
 }
diff --git a/src/game/client/components/camera.h b/src/game/client/components/camera.h
new file mode 100644
index 00000000..9654bdf6
--- /dev/null
+++ b/src/game/client/components/camera.h
@@ -0,0 +1,16 @@
+#ifndef GAME_CLIENT_COMPONENTS_CAMERA_H
+#define GAME_CLIENT_COMPONENTS_CAMERA_H
+#include <base/vmath.h>
+#include <game/client/component.h>
+
+class CCamera : public CComponent
+{	
+public:
+	vec2 m_Center;
+	float m_Zoom;
+
+	CCamera();
+	virtual void OnRender();
+};
+
+#endif
diff --git a/src/game/client/components/camera.hpp b/src/game/client/components/camera.hpp
deleted file mode 100644
index 1cb05f5b..00000000
--- a/src/game/client/components/camera.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <base/vmath.hpp>
-#include <game/client/component.hpp>
-
-class CAMERA : public COMPONENT
-{	
-public:
-	vec2 center;
-	float zoom;
-
-	CAMERA();
-	virtual void on_render();
-};
-
diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp
index fdf1d21b..1a2c828d 100644
--- a/src/game/client/components/chat.cpp
+++ b/src/game/client/components/chat.cpp
@@ -1,227 +1,263 @@
-#include <string.h> // strcmp
 
-#include <engine/e_client_interface.h>
-#include <engine/client/graphics.h>
-#include <game/generated/g_protocol.hpp>
-#include <game/generated/gc_data.hpp>
+#include <engine/graphics.h>
+#include <engine/textrender.h>
+#include <engine/keys.h>
+#include <engine/shared/config.h>
 
-#include <game/client/gameclient.hpp>
+#include <game/generated/protocol.h>
+#include <game/generated/client_data.h>
 
-#include <game/client/components/sounds.hpp>
+#include <game/client/gameclient.h>
 
-#include "chat.hpp"
+#include <game/client/components/sounds.h>
+#include <game/localization.h>
 
-void CHAT::on_statechange(int new_state, int old_state)
+#include "chat.h"
+
+
+CChat::CChat()
 {
-	if(old_state <= CLIENTSTATE_CONNECTING)
+	OnReset();
+}
+
+void CChat::OnReset()
+{
+	for(int i = 0; i < MAX_LINES; i++)
 	{
-		mode = MODE_NONE;
+		m_aLines[i].m_Time = 0;
+		m_aLines[i].m_aText[0] = 0;
+		m_aLines[i].m_aName[0] = 0;
+	}
+}
+
+void CChat::OnStateChange(int NewState, int OldState)
+{
+	if(OldState <= IClient::STATE_CONNECTING)
+	{
+		m_Mode = MODE_NONE;
 		for(int i = 0; i < MAX_LINES; i++)
-			lines[i].time = 0;
-		current_line = 0;
+			m_aLines[i].m_Time = 0;
+		m_CurrentLine = 0;
 	}
 }
 
-void CHAT::con_say(void *result, void *user_data)
+void CChat::ConSay(IConsole::IResult *pResult, void *pUserData)
 {
-	((CHAT*)user_data)->say(0, console_arg_string(result, 0));
+	((CChat*)pUserData)->Say(0, pResult->GetString(0));
 }
 
-void CHAT::con_sayteam(void *result, void *user_data)
+void CChat::ConSayTeam(IConsole::IResult *pResult, void *pUserData)
 {
-	((CHAT*)user_data)->say(1, console_arg_string(result, 0));
+	((CChat*)pUserData)->Say(1, pResult->GetString(0));
 }
 
-void CHAT::con_chat(void *result, void *user_data)
+void CChat::ConChat(IConsole::IResult *pResult, void *pUserData)
 {
-	const char *mode = console_arg_string(result, 0);
-	if(strcmp(mode, "all") == 0)
-		((CHAT*)user_data)->enable_mode(0);
-	else if(strcmp(mode, "team") == 0)
-		((CHAT*)user_data)->enable_mode(1);
+	const char *pMode = pResult->GetString(0);
+	if(str_comp(pMode, "all") == 0)
+		((CChat*)pUserData)->EnableMode(0);
+	else if(str_comp(pMode, "team") == 0)
+		((CChat*)pUserData)->EnableMode(1);
 	else
 		dbg_msg("console", "expected all or team as mode");
 }
 
-void CHAT::on_console_init()
+void CChat::OnConsoleInit()
 {
-	MACRO_REGISTER_COMMAND("say", "r", CFGFLAG_CLIENT, con_say, this, "Say in chat");
-	MACRO_REGISTER_COMMAND("say_team", "r", CFGFLAG_CLIENT, con_sayteam, this, "Say in team chat");
-	MACRO_REGISTER_COMMAND("chat", "s", CFGFLAG_CLIENT, con_chat, this, "Enable chat with all/team mode");
+	Console()->Register("say", "r", CFGFLAG_CLIENT, ConSay, this, "Say in chat");
+	Console()->Register("say_team", "r", CFGFLAG_CLIENT, ConSayTeam, this, "Say in team chat");
+	Console()->Register("chat", "s", CFGFLAG_CLIENT, ConChat, this, "Enable chat with all/team mode");
 }
 
-bool CHAT::on_input(INPUT_EVENT e)
+bool CChat::OnInput(IInput::CEvent e)
 {
-	if(mode == MODE_NONE)
+	if(m_Mode == MODE_NONE)
 		return false;
 
-	if(e.flags&INPFLAG_PRESS && e.key == KEY_ESCAPE)
-		mode = MODE_NONE;
-	else if(e.flags&INPFLAG_PRESS && (e.key == KEY_RETURN || e.key == KEY_KP_ENTER))
+	if(e.m_Flags&IInput::FLAG_PRESS && e.m_Key == KEY_ESCAPE)
+		m_Mode = MODE_NONE;
+	else if(e.m_Flags&IInput::FLAG_PRESS && (e.m_Key == KEY_RETURN || e.m_Key == KEY_KP_ENTER))
 	{
-		if(input.get_string()[0])
-			gameclient.chat->say(mode == MODE_ALL ? 0 : 1, input.get_string());
-		mode = MODE_NONE;
+		if(m_Input.GetString()[0])
+			Say(m_Mode == MODE_ALL ? 0 : 1, m_Input.GetString());
+		m_Mode = MODE_NONE;
 	}
 	else
-		input.process_input(e);
+		m_Input.ProcessInput(e);
 	
 	return true;
 }
 
 
-void CHAT::enable_mode(int team)
+void CChat::EnableMode(int Team)
 {
-	if(mode == MODE_NONE)
+	if(m_Mode == MODE_NONE)
 	{
-		if(team)
-			mode = MODE_TEAM;
+		if(Team)
+			m_Mode = MODE_TEAM;
 		else
-			mode = MODE_ALL;
+			m_Mode = MODE_ALL;
 		
-		input.clear();
-		inp_clear_events();
+		m_Input.Clear();
+		Input()->ClearEvents();
 	}
 }
 
-void CHAT::on_message(int msgtype, void *rawmsg)
+void CChat::OnMessage(int MsgType, void *pRawMsg)
 {
-	if(msgtype == NETMSGTYPE_SV_CHAT)
+	if(MsgType == NETMSGTYPE_SV_CHAT)
 	{
-		NETMSG_SV_CHAT *msg = (NETMSG_SV_CHAT *)rawmsg;
-		add_line(msg->cid, msg->team, msg->message);
+		CNetMsg_Sv_Chat *pMsg = (CNetMsg_Sv_Chat *)pRawMsg;
+		AddLine(pMsg->m_Cid, pMsg->m_Team, pMsg->m_pMessage);
 	}
 }
 
-void CHAT::add_line(int client_id, int team, const char *line)
+void CChat::AddLine(int ClientId, int Team, const char *pLine)
 {
-	current_line = (current_line+1)%MAX_LINES;
-	lines[current_line].time = time_get();
-	lines[current_line].client_id = client_id;
-	lines[current_line].team = team;
-	lines[current_line].name_color = -2;
-
-	if(client_id == -1) // server message
+	char *p = const_cast<char*>(pLine);
+	while(*p)
 	{
-		str_copy(lines[current_line].name, "*** ", sizeof(lines[current_line].name));
-		str_format(lines[current_line].text, sizeof(lines[current_line].text), "%s", line);
-	}
-	else
-	{
-		if(gameclient.clients[client_id].team == -1)
-			lines[current_line].name_color = -1;
+		pLine = p;
+		// find line seperator and strip multiline
+		while(*p)
+		{
+			if(*p++ == '\n')
+			{
+				*(p-1) = 0;
+				break;
+			}
+		}
 
-		if(gameclient.snap.gameobj && gameclient.snap.gameobj->flags&GAMEFLAG_TEAMS)
+		m_CurrentLine = (m_CurrentLine+1)%MAX_LINES;
+		m_aLines[m_CurrentLine].m_Time = time_get();
+		m_aLines[m_CurrentLine].m_ClientId = ClientId;
+		m_aLines[m_CurrentLine].m_Team = Team;
+		m_aLines[m_CurrentLine].m_NameColor = -2;
+
+		if(ClientId == -1) // server message
+		{
+			str_copy(m_aLines[m_CurrentLine].m_aName, "*** ", sizeof(m_aLines[m_CurrentLine].m_aName));
+			str_format(m_aLines[m_CurrentLine].m_aText, sizeof(m_aLines[m_CurrentLine].m_aText), "%s", pLine);
+		}
+		else
 		{
-			if(gameclient.clients[client_id].team == 0)
-				lines[current_line].name_color = 0;
-			else if(gameclient.clients[client_id].team == 1)
-				lines[current_line].name_color = 1;
+			if(m_pClient->m_aClients[ClientId].m_Team == -1)
+				m_aLines[m_CurrentLine].m_NameColor = -1;
+
+			if(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_Flags&GAMEFLAG_TEAMS)
+			{
+				if(m_pClient->m_aClients[ClientId].m_Team == 0)
+					m_aLines[m_CurrentLine].m_NameColor = 0;
+				else if(m_pClient->m_aClients[ClientId].m_Team == 1)
+					m_aLines[m_CurrentLine].m_NameColor = 1;
+			}
+			
+			str_copy(m_aLines[m_CurrentLine].m_aName, m_pClient->m_aClients[ClientId].m_aName, sizeof(m_aLines[m_CurrentLine].m_aName));
+			str_format(m_aLines[m_CurrentLine].m_aText, sizeof(m_aLines[m_CurrentLine].m_aText), ": %s", pLine);
 		}
 		
-		str_copy(lines[current_line].name, gameclient.clients[client_id].name, sizeof(lines[current_line].name));
-		str_format(lines[current_line].text, sizeof(lines[current_line].text), ": %s", line);
+		char aBuf[1024];
+		str_format(aBuf, sizeof(aBuf), "[chat]%s%s", m_aLines[m_CurrentLine].m_aName, m_aLines[m_CurrentLine].m_aText);
+		Console()->Print(aBuf);
 	}
-	
+
 	// play sound
-	if(client_id >= 0)
-		gameclient.sounds->play(SOUNDS::CHN_GUI, SOUND_CHAT_CLIENT, 0, vec2(0,0));
+	if(ClientId >= 0)
+		m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_CLIENT, 0, vec2(0,0));
 	else
-		gameclient.sounds->play(SOUNDS::CHN_GUI, SOUND_CHAT_SERVER, 0, vec2(0,0));
-	
-	dbg_msg("chat", "%s%s", lines[current_line].name, lines[current_line].text);
+		m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_SERVER, 0, vec2(0,0));
 }
 
-void CHAT::on_render()
+void CChat::OnRender()
 {
 	Graphics()->MapScreen(0,0,300*Graphics()->ScreenAspect(),300);
 	float x = 10.0f;
 	float y = 300.0f-20.0f;
-	if(mode != MODE_NONE)
+	if(m_Mode != MODE_NONE)
 	{
 		// render chat input
-		TEXT_CURSOR cursor;
-		gfx_text_set_cursor(&cursor, x, y, 8.0f, TEXTFLAG_RENDER);
-		cursor.line_width = 200.0f;
+		CTextCursor Cursor;
+		TextRender()->SetCursor(&Cursor, x, y, 8.0f, TEXTFLAG_RENDER);
+		Cursor.m_LineWidth = 200.0f;
 		
-		if(mode == MODE_ALL)
-			gfx_text_ex(&cursor, localize("All"), -1);
-		else if(mode == MODE_TEAM)
-			gfx_text_ex(&cursor, localize("Team"), -1);
+		if(m_Mode == MODE_ALL)
+			TextRender()->TextEx(&Cursor, Localize("All"), -1);
+		else if(m_Mode == MODE_TEAM)
+			TextRender()->TextEx(&Cursor, Localize("Team"), -1);
 		else
-			gfx_text_ex(&cursor, localize("Chat"), -1);
+			TextRender()->TextEx(&Cursor, Localize("Chat"), -1);
 
-		gfx_text_ex(&cursor, ": ", -1);
+		TextRender()->TextEx(&Cursor, ": ", -1);
 			
-		gfx_text_ex(&cursor, input.get_string(), input.cursor_offset());
-		TEXT_CURSOR marker = cursor;
-		gfx_text_ex(&marker, "|", -1);
-		gfx_text_ex(&cursor, input.get_string()+input.cursor_offset(), -1);
+		TextRender()->TextEx(&Cursor, m_Input.GetString(), m_Input.GetCursorOffset());
+		CTextCursor Marker = Cursor;
+		TextRender()->TextEx(&Marker, "|", -1);
+		TextRender()->TextEx(&Cursor, m_Input.GetString()+m_Input.GetCursorOffset(), -1);
 	}
 
 	y -= 8;
 
 	int i;
+	int64 Now = time_get();
 	for(i = 0; i < MAX_LINES; i++)
 	{
-		int r = ((current_line-i)+MAX_LINES)%MAX_LINES;
-		if(time_get() > lines[r].time+15*time_freq())
+		int r = ((m_CurrentLine-i)+MAX_LINES)%MAX_LINES;
+		if(Now > m_aLines[r].m_Time+15*time_freq())
 			break;
 
-		float begin = x;
-		float fontsize = 7.0f;
+		float Begin = x;
+		float FontSize = 7.0f;
 		
 		// get the y offset
-		TEXT_CURSOR cursor;
-		gfx_text_set_cursor(&cursor, begin, 0, fontsize, 0);
-		cursor.line_width = 200.0f;
-		gfx_text_ex(&cursor, lines[r].name, -1);
-		gfx_text_ex(&cursor, lines[r].text, -1);
-		y -= cursor.y + cursor.font_size;
+		CTextCursor Cursor;
+		TextRender()->SetCursor(&Cursor, Begin, 0, FontSize, 0);
+		Cursor.m_LineWidth = 200.0f;
+		TextRender()->TextEx(&Cursor, m_aLines[r].m_aName, -1);
+		TextRender()->TextEx(&Cursor, m_aLines[r].m_aText, -1);
+		y -= Cursor.m_Y + Cursor.m_FontSize;
 
 		// cut off if msgs waste too much space
 		if(y < 200.0f)
 			break;
 		
 		// reset the cursor
-		gfx_text_set_cursor(&cursor, begin, y, fontsize, TEXTFLAG_RENDER);
-		cursor.line_width = 200.0f;
+		TextRender()->SetCursor(&Cursor, Begin, y, FontSize, TEXTFLAG_RENDER);
+		Cursor.m_LineWidth = 200.0f;
 
 		// render name
-		gfx_text_color(0.8f,0.8f,0.8f,1);
-		if(lines[r].client_id == -1)
-			gfx_text_color(1,1,0.5f,1); // system
-		else if(lines[r].team)
-			gfx_text_color(0.45f,0.9f,0.45f,1); // team message
-		else if(lines[r].name_color == 0)
-			gfx_text_color(1.0f,0.5f,0.5f,1); // red
-		else if(lines[r].name_color == 1)
-			gfx_text_color(0.7f,0.7f,1.0f,1); // blue
-		else if(lines[r].name_color == -1)
-			gfx_text_color(0.75f,0.5f,0.75f, 1); // spectator
+		TextRender()->TextColor(0.8f,0.8f,0.8f,1);
+		if(m_aLines[r].m_ClientId == -1)
+			TextRender()->TextColor(1,1,0.5f,1); // system
+		else if(m_aLines[r].m_Team)
+			TextRender()->TextColor(0.45f,0.9f,0.45f,1); // team message
+		else if(m_aLines[r].m_NameColor == 0)
+			TextRender()->TextColor(1.0f,0.5f,0.5f,1); // red
+		else if(m_aLines[r].m_NameColor == 1)
+			TextRender()->TextColor(0.7f,0.7f,1.0f,1); // blue
+		else if(m_aLines[r].m_NameColor == -1)
+			TextRender()->TextColor(0.75f,0.5f,0.75f, 1); // spectator
 			
 		// render name
-		gfx_text_ex(&cursor, lines[r].name, -1);
+		TextRender()->TextEx(&Cursor, m_aLines[r].m_aName, -1);
 
 		// render line
-		gfx_text_color(1,1,1,1);
-		if(lines[r].client_id == -1)
-			gfx_text_color(1,1,0.5f,1); // system
-		else if(lines[r].team)
-			gfx_text_color(0.65f,1,0.65f,1); // team message
+		TextRender()->TextColor(1,1,1,1);
+		if(m_aLines[r].m_ClientId == -1)
+			TextRender()->TextColor(1,1,0.5f,1); // system
+		else if(m_aLines[r].m_Team)
+			TextRender()->TextColor(0.65f,1,0.65f,1); // team message
 
-		gfx_text_ex(&cursor, lines[r].text, -1);
+		TextRender()->TextEx(&Cursor, m_aLines[r].m_aText, -1);
 	}
 
-	gfx_text_color(1,1,1,1);
+	TextRender()->TextColor(1,1,1,1);
 }
 
-void CHAT::say(int team, const char *line)
+void CChat::Say(int Team, const char *pLine)
 {
 	// send chat message
-	NETMSG_CL_SAY msg;
-	msg.team = team;
-	msg.message = line;
-	msg.pack(MSGFLAG_VITAL);
-	client_send_msg();
+	CNetMsg_Cl_Say Msg;
+	Msg.m_Team = Team;
+	Msg.m_pMessage = pLine;
+	Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
 }
diff --git a/src/game/client/components/chat.h b/src/game/client/components/chat.h
new file mode 100644
index 00000000..8a33e9e8
--- /dev/null
+++ b/src/game/client/components/chat.h
@@ -0,0 +1,60 @@
+#ifndef GAME_CLIENT_COMPONENTS_CHAT_H
+#define GAME_CLIENT_COMPONENTS_CHAT_H
+#include <game/client/component.h>
+#include <game/client/lineinput.h>
+
+class CChat : public CComponent
+{
+	CLineInput m_Input;
+	
+	enum 
+	{
+		MAX_LINES = 10,
+	};
+
+	struct CLine
+	{
+		int64 m_Time;
+		int m_ClientId;
+		int m_Team;
+		int m_NameColor;
+		char m_aName[64];
+		char m_aText[512];
+	};
+
+	CLine m_aLines[MAX_LINES];
+	int m_CurrentLine;
+
+	// chat
+	enum
+	{
+		MODE_NONE=0,
+		MODE_ALL,
+		MODE_TEAM,
+	};
+
+	int m_Mode;
+	
+	static void ConSay(IConsole::IResult *pResult, void *pUserData);
+	static void ConSayTeam(IConsole::IResult *pResult, void *pUserData);
+	static void ConChat(IConsole::IResult *pResult, void *pUserData);
+	
+public:
+	CChat();
+
+	bool IsActive() const { return m_Mode != MODE_NONE; }
+	
+	void AddLine(int ClientId, int Team, const char *pLine);
+	
+	void EnableMode(int Team);
+	
+	void Say(int Team, const char *pLine);
+	
+	virtual void OnReset();
+	virtual void OnConsoleInit();
+	virtual void OnStateChange(int NewState, int OldState);
+	virtual void OnRender();
+	virtual void OnMessage(int MsgType, void *pRawMsg);
+	virtual bool OnInput(IInput::CEvent Event);
+};
+#endif
diff --git a/src/game/client/components/chat.hpp b/src/game/client/components/chat.hpp
deleted file mode 100644
index ca34237d..00000000
--- a/src/game/client/components/chat.hpp
+++ /dev/null
@@ -1,54 +0,0 @@
-#include <game/client/component.hpp>
-#include <game/client/lineinput.hpp>
-
-class CHAT : public COMPONENT
-{
-	LINEINPUT input;
-	
-	enum 
-	{
-		MAX_LINES = 10,
-	};
-
-	struct LINE
-	{
-		int64 time;
-		int client_id;
-		int team;
-		int name_color;
-		char name[64];
-		char text[512];
-	};
-
-	LINE lines[MAX_LINES];
-	int current_line;
-
-	// chat
-	enum
-	{
-		MODE_NONE=0,
-		MODE_ALL,
-		MODE_TEAM,
-	};
-
-	int mode;
-	
-	static void con_say(void *result, void *user_data);
-	static void con_sayteam(void *result, void *user_data);
-	static void con_chat(void *result, void *user_data);
-	
-public:
-	bool is_active() const { return mode != MODE_NONE; }
-	
-	void add_line(int client_id, int team, const char *line);
-	
-	void enable_mode(int team);
-	
-	void say(int team, const char *line);
-	
-	virtual void on_console_init();
-	virtual void on_statechange(int new_state, int old_state);
-	virtual void on_render();
-	virtual void on_message(int msgtype, void *rawmsg);
-	virtual bool on_input(INPUT_EVENT e);
-};
diff --git a/src/game/client/components/console.cpp b/src/game/client/components/console.cpp
index 382cb134..7de85f69 100644
--- a/src/game/client/components/console.cpp
+++ b/src/game/client/components/console.cpp
@@ -1,26 +1,29 @@
-//#include "gc_console.hpp"
+//#include "gc_console.h"
 #include <math.h>
 
-#include <game/generated/gc_data.hpp>
+#include <game/generated/client_data.h>
 
 #include <base/system.h>
 
-#include <engine/e_client_interface.h>
-#include <engine/client/graphics.h>
-
-#include <engine/e_ringbuffer.h>
+#include <engine/shared/ringbuffer.h>
+#include <engine/shared/config.h>
+#include <engine/graphics.h>
+#include <engine/textrender.h>
+#include <engine/keys.h>
+#include <engine/console.h>
 
 #include <cstring>
 #include <cstdio>
 
-#include <game/client/ui.hpp>
+#include <game/client/ui.h>
 
-#include <game/version.hpp>
+#include <game/version.h>
 
-#include <game/client/lineinput.hpp>
-#include <game/client/render.hpp>
+#include <game/client/lineinput.h>
+#include <game/client/render.h>
+#include <game/client/components/menus.h>
 
-#include "console.hpp"
+#include "console.h"
 
 enum
 {
@@ -30,479 +33,550 @@ enum
 	CONSOLE_CLOSING,
 };
 
-CONSOLE::INSTANCE::INSTANCE(int t)
+CGameConsole::CInstance::CInstance(CGameConsole *pGameConsole, int Type)
 {
+	m_pGameConsole = pGameConsole;
 	// init ringbuffers
 	//history = ringbuf_init(history_data, sizeof(history_data), RINGBUF_FLAG_RECYCLE);
 	//backlog = ringbuf_init(backlog_data, sizeof(backlog_data), RINGBUF_FLAG_RECYCLE);
 	
-	history_entry = 0x0;
+	m_pHistoryEntry = 0x0;
 	
-	type = t;
+	m_Type = Type;
 	
-	if(t == 0)
-		completion_flagmask = CFGFLAG_CLIENT;
+	if(Type == 0)
+		m_CompletionFlagmask = CFGFLAG_CLIENT;
 	else
-		completion_flagmask = CFGFLAG_SERVER;
+		m_CompletionFlagmask = CFGFLAG_SERVER;
 
-	completion_buffer[0] = 0;
-	completion_chosen = -1;
+	m_aCompletionBuffer[0] = 0;
+	m_CompletionChosen = -1;
 	
-	command = 0x0;
+	m_pCommand = 0x0;
 }
 
-void CONSOLE::INSTANCE::execute_line(const char *line)
+void CGameConsole::CInstance::ExecuteLine(const char *pLine)
 {
-	if(type == 0)
-		console_execute_line(line);
+	if(m_Type == 0)
+		m_pGameConsole->m_pConsole->ExecuteLine(pLine);
 	else
 	{
-		if(client_rcon_authed())
-			client_rcon(line);
+		if(m_pGameConsole->Client()->RconAuthed())
+			m_pGameConsole->Client()->Rcon(pLine);
 		else
-			client_rcon_auth("", line);
+			m_pGameConsole->Client()->RconAuth("", pLine);
 	}
 }
 
-void CONSOLE::INSTANCE::possible_commands_complete_callback(const char *str, void *user)
+void CGameConsole::CInstance::PossibleCommandsCompleteCallback(const char *pStr, void *pUser)
 {
-	CONSOLE::INSTANCE *instance = (CONSOLE::INSTANCE *)user;
-	if(instance->completion_chosen == instance->completion_enumeration_count)
-		instance->input.set(str);
-	instance->completion_enumeration_count++;
+	CGameConsole::CInstance *pInstance = (CGameConsole::CInstance *)pUser;
+	if(pInstance->m_CompletionChosen == pInstance->m_CompletionEnumerationCount)
+		pInstance->m_Input.Set(pStr);
+	pInstance->m_CompletionEnumerationCount++;
 }
 
-void CONSOLE::INSTANCE::on_input(INPUT_EVENT e)
+void CGameConsole::CInstance::OnInput(IInput::CEvent Event)
 {
-	bool handled = false;
+	bool Handled = false;
 	
-	if(e.flags&INPFLAG_PRESS)
+	if(Event.m_Flags&IInput::FLAG_PRESS)
 	{
-		if(e.key == KEY_RETURN || e.key == KEY_KP_ENTER)
+		if(Event.m_Key == KEY_RETURN || Event.m_Key == KEY_KP_ENTER)
 		{
-			if(input.get_string()[0])
+			if(m_Input.GetString()[0])
 			{
-				char *entry = history.Allocate(input.get_length()+1);
-				mem_copy(entry, input.get_string(), input.get_length()+1);
-				
-				execute_line(input.get_string());
-				input.clear();
-				history_entry = 0x0;
+				char *pEntry = m_History.Allocate(m_Input.GetLength()+1);
+				mem_copy(pEntry, m_Input.GetString(), m_Input.GetLength()+1);				
+				ExecuteLine(m_Input.GetString());
+				m_Input.Clear();
+				m_pHistoryEntry = 0x0;
 			}
 			
-			handled = true;
+			Handled = true;
 		}
-		else if (e.key == KEY_UP)
+		else if (Event.m_Key == KEY_UP)
 		{
-			if (history_entry)
+			if (m_pHistoryEntry)
 			{
-				char *test = history.Prev(history_entry);
+				char *pTest = m_History.Prev(m_pHistoryEntry);
 
-				if (test)
-					history_entry = test;
+				if (pTest)
+					m_pHistoryEntry = pTest;
 			}
 			else
-				history_entry = history.Last();
+				m_pHistoryEntry = m_History.Last();
 
-			if (history_entry)
+			if (m_pHistoryEntry)
 			{
-				unsigned int len = strlen(history_entry);
-				if (len < sizeof(input) - 1)
-					input.set(history_entry);
+				unsigned int Len = str_length(m_pHistoryEntry);
+				if (Len < sizeof(m_Input) - 1) // TODO: WTF?
+					m_Input.Set(m_pHistoryEntry);
 			}
-			handled = true;
+			Handled = true;
 		}
-		else if (e.key == KEY_DOWN)
+		else if (Event.m_Key == KEY_DOWN)
 		{
-			if (history_entry)
-				history_entry = history.Next(history_entry);
+			if (m_pHistoryEntry)
+				m_pHistoryEntry = m_History.Next(m_pHistoryEntry);
 
-			if (history_entry)
+			if (m_pHistoryEntry)
 			{
-				unsigned int len = strlen(history_entry);
-				if (len < sizeof(input) - 1)
-					input.set(history_entry);
+				unsigned int Len = str_length(m_pHistoryEntry);
+				if (Len < sizeof(m_Input) - 1) // TODO: WTF?
+					m_Input.Set(m_pHistoryEntry);
 			}
 			else
-				input.clear();
-			handled = true;
+				m_Input.Clear();
+			Handled = true;
 		}
-		else if(e.key == KEY_TAB)
+		else if(Event.m_Key == KEY_TAB)
 		{
-			completion_chosen++;
-			completion_enumeration_count = 0;
-			console_possible_commands(completion_buffer, completion_flagmask, possible_commands_complete_callback, this);
-
-			// handle wrapping
-			if(completion_enumeration_count && completion_chosen >= completion_enumeration_count)
+			if(m_Type == 0 || m_pGameConsole->Client()->RconAuthed())
 			{
-				completion_chosen %= completion_enumeration_count;
-				completion_enumeration_count = 0;
-				console_possible_commands(completion_buffer, completion_flagmask, possible_commands_complete_callback, this);
+				m_CompletionChosen++;
+				m_CompletionEnumerationCount = 0;
+				m_pGameConsole->m_pConsole->PossibleCommands(m_aCompletionBuffer, m_CompletionFlagmask, PossibleCommandsCompleteCallback, this);
+
+				// handle wrapping
+				if(m_CompletionEnumerationCount && m_CompletionChosen >= m_CompletionEnumerationCount)
+				{
+					m_CompletionChosen %= m_CompletionEnumerationCount;
+					m_CompletionEnumerationCount = 0;
+					m_pGameConsole->m_pConsole->PossibleCommands(m_aCompletionBuffer, m_CompletionFlagmask, PossibleCommandsCompleteCallback, this);
+				}
 			}
 		}
-		
-		if(e.key != KEY_TAB)
+		else if(Event.m_Key == KEY_PAGEUP)
+		{
+			++m_BacklogActPage;
+		}
+		else if(Event.m_Key == KEY_PAGEDOWN)
 		{
-			completion_chosen = -1;
-			str_copy(completion_buffer, input.get_string(), sizeof(completion_buffer));
+			--m_BacklogActPage;
+			if(m_BacklogActPage < 0)
+				m_BacklogActPage = 0;
+		}
+	}
+
+	if(!Handled)
+		m_Input.ProcessInput(Event);
+
+	if(Event.m_Flags&IInput::FLAG_PRESS)
+	{
+		if(Event.m_Key != KEY_TAB)
+		{
+			m_CompletionChosen = -1;
+			str_copy(m_aCompletionBuffer, m_Input.GetString(), sizeof(m_aCompletionBuffer));
 		}
 
 		// find the current command
 		{
-			char buf[64] = {0};
-			const char *src = get_string();
+			char aBuf[64] = {0};
+			const char *pSrc = GetString();
 			int i = 0;
-			for(; i < (int)sizeof(buf) && *src && *src != ' '  && *src != ' '; i++, src++)
-				buf[i] = *src;
-			buf[i] = 0;
+			for(; i < (int)sizeof(aBuf) && *pSrc && *pSrc != ' '  && *pSrc != ' '; i++, pSrc++)
+				aBuf[i] = *pSrc;
+			aBuf[i] = 0;
 			
-			command = console_get_command(buf);
+			m_pCommand = m_pGameConsole->m_pConsole->GetCommandInfo(aBuf);
 		}
 	}
-	
-	if(!handled)
-		input.process_input(e);
 }
 
-void CONSOLE::INSTANCE::print_line(const char *line)
+void CGameConsole::CInstance::PrintLine(const char *pLine)
 {
-	int len = strlen(line);
+	int Len = str_length(pLine);
 
-	if (len > 255)
-		len = 255;
+	if (Len > 255)
+		Len = 255;
 
-	char *entry = backlog.Allocate(len+1);
-	mem_copy(entry, line, len+1);
+	char *pEntry = m_Backlog.Allocate(Len+1);
+	mem_copy(pEntry, pLine, Len);
+	pEntry[Len] = 0;
 }
 
-CONSOLE::CONSOLE()
-: local_console(0), remote_console(1)
+CGameConsole::CGameConsole()
+: m_LocalConsole(this, 0), m_RemoteConsole(this, 1)
 {
-	console_type = 0;
-	console_state = CONSOLE_CLOSED;
-	state_change_end = 0.0f;
-	state_change_duration = 0.1f;
+	m_ConsoleType = 0;
+	m_ConsoleState = CONSOLE_CLOSED;
+	m_StateChangeEnd = 0.0f;
+	m_StateChangeDuration = 0.1f;
 }
 
-float CONSOLE::time_now()
+float CGameConsole::TimeNow()
 {
-	static long long time_start = time_get();
-	return float(time_get()-time_start)/float(time_freq());
+	static long long s_TimeStart = time_get();
+	return float(time_get()-s_TimeStart)/float(time_freq());
 }
 
-CONSOLE::INSTANCE *CONSOLE::current_console()
+CGameConsole::CInstance *CGameConsole::CurrentConsole()
 {
-    if(console_type != 0)
-    	return &remote_console;
-    return &local_console;
+    if(m_ConsoleType != 0)
+    	return &m_RemoteConsole;
+    return &m_LocalConsole;
 }
 
-void CONSOLE::on_reset()
+void CGameConsole::OnReset()
 {
 }
 
 // only defined for 0<=t<=1
-static float console_scale_func(float t)
+static float ConsoleScaleFunc(float t)
 {
 	//return t;
 	return sinf(acosf(1.0f-t));
 }
 
-struct RENDERINFO
+struct CRenderInfo
 {
-	CONSOLE *self;
-	TEXT_CURSOR cursor;
-	const char *current_cmd;
-	int wanted_completion;
-	int enum_count;
+	CGameConsole *m_pSelf;
+	CTextCursor m_Cursor;
+	const char *m_pCurrentCmd;
+	int m_WantedCompletion;
+	int m_EnumCount;
 };
 
-void CONSOLE::possible_commands_render_callback(const char *str, void *user)
+void CGameConsole::PossibleCommandsRenderCallback(const char *pStr, void *pUser)
 {
-	RENDERINFO *info = (RENDERINFO *)user;
+	CRenderInfo *pInfo = static_cast<CRenderInfo *>(pUser);
 	
-	if(info->enum_count == info->wanted_completion)
+	if(pInfo->m_EnumCount == pInfo->m_WantedCompletion)
 	{
-		float tw = gfx_text_width(info->cursor.font, info->cursor.font_size, str, -1);
-		info->self->Graphics()->TextureSet(-1);
-		info->self->Graphics()->QuadsBegin();
-			info->self->Graphics()->SetColor(229.0f/255.0f,185.0f/255.0f,4.0f/255.0f,0.85f);
-			info->self->RenderTools()->draw_round_rect(info->cursor.x-3, info->cursor.y, tw+5, info->cursor.font_size+4, info->cursor.font_size/3);
-		info->self->Graphics()->QuadsEnd();
+		float tw = pInfo->m_pSelf->TextRender()->TextWidth(pInfo->m_Cursor.m_pFont, pInfo->m_Cursor.m_FontSize, pStr, -1);
+		pInfo->m_pSelf->Graphics()->TextureSet(-1);
+		pInfo->m_pSelf->Graphics()->QuadsBegin();
+			pInfo->m_pSelf->Graphics()->SetColor(229.0f/255.0f,185.0f/255.0f,4.0f/255.0f,0.85f);
+			pInfo->m_pSelf->RenderTools()->DrawRoundRect(pInfo->m_Cursor.m_X-3, pInfo->m_Cursor.m_Y, tw+5, pInfo->m_Cursor.m_FontSize+4, pInfo->m_Cursor.m_FontSize/3);
+		pInfo->m_pSelf->Graphics()->QuadsEnd();
 		
-		gfx_text_color(0.05f, 0.05f, 0.05f,1);
-		gfx_text_ex(&info->cursor, str, -1);
+		pInfo->m_pSelf->TextRender()->TextColor(0.05f, 0.05f, 0.05f,1);
+		pInfo->m_pSelf->TextRender()->TextEx(&pInfo->m_Cursor, pStr, -1);
 	}
 	else
 	{
-		const char *match_start = str_find_nocase(str, info->current_cmd);
+		const char *pMatchStart = str_find_nocase(pStr, pInfo->m_pCurrentCmd);
 		
-		if(match_start)
+		if(pMatchStart)
 		{
-			gfx_text_color(0.5f,0.5f,0.5f,1);
-			gfx_text_ex(&info->cursor, str, match_start-str);
-			gfx_text_color(229.0f/255.0f,185.0f/255.0f,4.0f/255.0f,1);
-			gfx_text_ex(&info->cursor, match_start, strlen(info->current_cmd));
-			gfx_text_color(0.5f,0.5f,0.5f,1);
-			gfx_text_ex(&info->cursor, match_start+strlen(info->current_cmd), -1);
+			pInfo->m_pSelf->TextRender()->TextColor(0.5f,0.5f,0.5f,1);
+			pInfo->m_pSelf->TextRender()->TextEx(&pInfo->m_Cursor, pStr, pMatchStart-pStr);
+			pInfo->m_pSelf->TextRender()->TextColor(229.0f/255.0f,185.0f/255.0f,4.0f/255.0f,1);
+			pInfo->m_pSelf->TextRender()->TextEx(&pInfo->m_Cursor, pMatchStart, str_length(pInfo->m_pCurrentCmd));
+			pInfo->m_pSelf->TextRender()->TextColor(0.5f,0.5f,0.5f,1);
+			pInfo->m_pSelf->TextRender()->TextEx(&pInfo->m_Cursor, pMatchStart+str_length(pInfo->m_pCurrentCmd), -1);
 		}
 		else
 		{
-			gfx_text_color(0.75f,0.75f,0.75f,1);
-			gfx_text_ex(&info->cursor, str, -1);
+			pInfo->m_pSelf->TextRender()->TextColor(0.75f,0.75f,0.75f,1);
+			pInfo->m_pSelf->TextRender()->TextEx(&pInfo->m_Cursor, pStr, -1);
 		}
 	}
 	
-	info->enum_count++;
-	info->cursor.x += 7.0f;
+	pInfo->m_EnumCount++;
+	pInfo->m_Cursor.m_X += 7.0f;
 }
 
-void CONSOLE::on_render()
+void CGameConsole::OnRender()
 {
-    CUIRect screen = *UI()->Screen();
-	float console_max_height = screen.h*3/5.0f;
-	float console_height;
+    CUIRect Screen = *UI()->Screen();
+	float ConsoleMaxHeight = Screen.h*3/5.0f;
+	float ConsoleHeight;
 
-	float progress = (time_now()-(state_change_end-state_change_duration))/float(state_change_duration);
+	float Progress = (TimeNow()-(m_StateChangeEnd-m_StateChangeDuration))/float(m_StateChangeDuration);
 
-	if (progress >= 1.0f)
+	if (Progress >= 1.0f)
 	{
-		if (console_state == CONSOLE_CLOSING)
-			console_state = CONSOLE_CLOSED;
-		else if (console_state == CONSOLE_OPENING)
-			console_state = CONSOLE_OPEN;
+		if (m_ConsoleState == CONSOLE_CLOSING)
+			m_ConsoleState = CONSOLE_CLOSED;
+		else if (m_ConsoleState == CONSOLE_OPENING)
+			m_ConsoleState = CONSOLE_OPEN;
 
-		progress = 1.0f;
+		Progress = 1.0f;
 	}
 
-	if (console_state == CONSOLE_OPEN && config.cl_editor)
-		toggle(0);	
+	if (m_ConsoleState == CONSOLE_OPEN && g_Config.m_ClEditor)
+		Toggle(0);	
 		
-	if (console_state == CONSOLE_CLOSED)
+	if (m_ConsoleState == CONSOLE_CLOSED)
 		return;
 		
-	if (console_state == CONSOLE_OPEN)
-		inp_mouse_mode_absolute();
+	if (m_ConsoleState == CONSOLE_OPEN)
+		Input()->MouseModeAbsolute();
 
-	float console_height_scale;
+	float ConsoleHeightScale;
 
-	if (console_state == CONSOLE_OPENING)
-		console_height_scale = console_scale_func(progress);
-	else if (console_state == CONSOLE_CLOSING)
-		console_height_scale = console_scale_func(1.0f-progress);
+	if (m_ConsoleState == CONSOLE_OPENING)
+		ConsoleHeightScale = ConsoleScaleFunc(Progress);
+	else if (m_ConsoleState == CONSOLE_CLOSING)
+		ConsoleHeightScale = ConsoleScaleFunc(1.0f-Progress);
 	else //if (console_state == CONSOLE_OPEN)
-		console_height_scale = console_scale_func(1.0f);
+		ConsoleHeightScale = ConsoleScaleFunc(1.0f);
 
-	console_height = console_height_scale*console_max_height;
+	ConsoleHeight = ConsoleHeightScale*ConsoleMaxHeight;
 
-	Graphics()->MapScreen(screen.x, screen.y, screen.w, screen.h);
+	Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);
 
 	// do console shadow
 	Graphics()->TextureSet(-1);
     Graphics()->QuadsBegin();
-    Graphics()->SetColorVertex(0, 0,0,0, 0.5f);
-    Graphics()->SetColorVertex(1, 0,0,0, 0.5f);
-    Graphics()->SetColorVertex(2, 0,0,0, 0.0f);
-    Graphics()->SetColorVertex(3, 0,0,0, 0.0f);
-    Graphics()->QuadsDrawTL(0,console_height,screen.w,10.0f);
+	IGraphics::CColorVertex Array[4] = {
+    	IGraphics::CColorVertex(0, 0,0,0, 0.5f),
+    	IGraphics::CColorVertex(1, 0,0,0, 0.5f),
+    	IGraphics::CColorVertex(2, 0,0,0, 0.0f),
+		IGraphics::CColorVertex(3, 0,0,0, 0.0f)};
+	Graphics()->SetColorVertex(Array, 4);
+	IGraphics::CQuadItem QuadItem(0, ConsoleHeight, Screen.w, 10.0f);
+	Graphics()->QuadsDrawTL(&QuadItem, 1);
     Graphics()->QuadsEnd();
 
 	// do background
-	Graphics()->TextureSet(data->images[IMAGE_CONSOLE_BG].id);
+	Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CONSOLE_BG].m_Id);
     Graphics()->QuadsBegin();
     Graphics()->SetColor(0.2f, 0.2f, 0.2f,0.9f);
-    if(console_type != 0)
+    if(m_ConsoleType != 0)
 	    Graphics()->SetColor(0.4f, 0.2f, 0.2f,0.9f);
-    Graphics()->QuadsSetSubset(0,-console_height*0.075f,screen.w*0.075f*0.5f,0);
-    Graphics()->QuadsDrawTL(0,0,screen.w,console_height);
+    Graphics()->QuadsSetSubset(0,-ConsoleHeight*0.075f,Screen.w*0.075f*0.5f,0);
+	QuadItem = IGraphics::CQuadItem(0, 0, Screen.w, ConsoleHeight);
+	Graphics()->QuadsDrawTL(&QuadItem, 1);
     Graphics()->QuadsEnd();
 
 	// do small bar shadow
 	Graphics()->TextureSet(-1);
     Graphics()->QuadsBegin();
-    Graphics()->SetColorVertex(0, 0,0,0, 0.0f);
-    Graphics()->SetColorVertex(1, 0,0,0, 0.0f);
-    Graphics()->SetColorVertex(2, 0,0,0, 0.25f);
-    Graphics()->SetColorVertex(3, 0,0,0, 0.25f);
-    Graphics()->QuadsDrawTL(0,console_height-20,screen.w,10);
+	Array[0] = IGraphics::CColorVertex(0, 0,0,0, 0.0f);
+	Array[1] = IGraphics::CColorVertex(1, 0,0,0, 0.0f);
+	Array[2] = IGraphics::CColorVertex(2, 0,0,0, 0.25f);
+	Array[3] = IGraphics::CColorVertex(3, 0,0,0, 0.25f);
+	Graphics()->SetColorVertex(Array, 4);
+	QuadItem = IGraphics::CQuadItem(0, ConsoleHeight-20, Screen.w, 10);
+	Graphics()->QuadsDrawTL(&QuadItem, 1);
     Graphics()->QuadsEnd();
 
 	// do the lower bar
-	Graphics()->TextureSet(data->images[IMAGE_CONSOLE_BAR].id);
+	Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CONSOLE_BAR].m_Id);
     Graphics()->QuadsBegin();
     Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.9f);
-    Graphics()->QuadsSetSubset(0,0.1f,screen.w*0.015f,1-0.1f);
-    Graphics()->QuadsDrawTL(0,console_height-10.0f,screen.w,10.0f);
+    Graphics()->QuadsSetSubset(0,0.1f,Screen.w*0.015f,1-0.1f);
+	QuadItem = IGraphics::CQuadItem(0,ConsoleHeight-10.0f,Screen.w,10.0f);
+	Graphics()->QuadsDrawTL(&QuadItem, 1);
     Graphics()->QuadsEnd();
     
-    console_height -= 22.0f;
+    ConsoleHeight -= 22.0f;
     
-    INSTANCE *console = current_console();
+    CInstance *pConsole = CurrentConsole();
 
 	{
-		float font_size = 10.0f;
-		float row_height = font_size*1.25f;
+		float FontSize = 10.0f;
+		float RowHeight = FontSize*1.25f;
 		float x = 3;
-		float y = console_height - row_height - 2;
+		float y = ConsoleHeight - RowHeight - 2;
 
 		// render prompt		
-		TEXT_CURSOR cursor;
-		gfx_text_set_cursor(&cursor, x, y, font_size, TEXTFLAG_RENDER);
-
-		RENDERINFO info;
-		info.self = this;
-		info.wanted_completion = console->completion_chosen;
-		info.enum_count = 0;
-		info.current_cmd = console->completion_buffer;
-		gfx_text_set_cursor(&info.cursor, x, y+12.0f, font_size, TEXTFLAG_RENDER);
-
-		const char *prompt = "> ";
-		if(console_type)
+		CTextCursor Cursor;
+		TextRender()->SetCursor(&Cursor, x, y, FontSize, TEXTFLAG_RENDER);
+
+		CRenderInfo Info;
+		Info.m_pSelf = this;
+		Info.m_WantedCompletion = pConsole->m_CompletionChosen;
+		Info.m_EnumCount = 0;
+		Info.m_pCurrentCmd = pConsole->m_aCompletionBuffer;
+		TextRender()->SetCursor(&Info.m_Cursor, x, y+12.0f, FontSize, TEXTFLAG_RENDER);
+
+		const char *pPrompt = "> ";
+		if(m_ConsoleType)
 		{
-			if(client_state() == CLIENTSTATE_ONLINE)
+			if(Client()->State() == IClient::STATE_ONLINE)
 			{
-				if(client_rcon_authed())
-					prompt = "rcon> ";
+				if(Client()->RconAuthed())
+					pPrompt = "rcon> ";
 				else
-					prompt = "ENTER PASSWORD> ";
+					pPrompt = "ENTER PASSWORD> ";
 			}
 			else
-				prompt = "NOT CONNECTED> ";
+				pPrompt = "NOT CONNECTED> ";
 		}
 
-		gfx_text_ex(&cursor, prompt, -1);
-		
-		// render console input
-		gfx_text_ex(&cursor, console->input.get_string(), console->input.cursor_offset());
-		TEXT_CURSOR marker = cursor;
-		gfx_text_ex(&marker, "|", -1);
-		gfx_text_ex(&cursor, console->input.get_string()+console->input.cursor_offset(), -1);
+		TextRender()->TextEx(&Cursor, pPrompt, -1);
+		x = Cursor.m_X;
 		
 		// render version
-		char buf[128];
-		str_format(buf, sizeof(buf), "v%s", GAME_VERSION);
-		float version_width = gfx_text_width(0, font_size, buf, -1);
-		gfx_text(0, screen.w-version_width-5, y, font_size, buf, -1);
-
-		// render possible commands
-		if(console->input.get_string()[0] != 0)
+		char aBuf[128];
+		str_format(aBuf, sizeof(aBuf), "v%s", GAME_VERSION);
+		float VersionWidth = TextRender()->TextWidth(0, FontSize, aBuf, -1);
+		TextRender()->Text(0, Screen.w-VersionWidth-5, y, FontSize, aBuf, -1);
+
+		// render console input (wrap line)
+		int Lines = TextRender()->TextLineCount(0, FontSize, pConsole->m_Input.GetString(), Screen.w - (VersionWidth + 10 + x));
+		y -= (Lines - 1) * FontSize;
+		TextRender()->SetCursor(&Cursor, x, y, FontSize, TEXTFLAG_RENDER);
+		Cursor.m_LineWidth = Screen.w - (VersionWidth + 10 + x);
+		
+		//hide rcon password
+		char aInputString[256];
+		str_copy(aInputString, pConsole->m_Input.GetString(), sizeof(aInputString));
+		if(m_ConsoleType && Client()->State() == IClient::STATE_ONLINE && !Client()->RconAuthed())
 		{
-			console_possible_commands(console->completion_buffer, console->completion_flagmask, possible_commands_render_callback, &info);
+			for(int i = 0; i < pConsole->m_Input.GetLength(); ++i)
+				aInputString[i] = '*';
+		}
 			
-			if(info.enum_count <= 0)
+		TextRender()->TextEx(&Cursor, aInputString, pConsole->m_Input.GetCursorOffset());
+		CTextCursor Marker = Cursor;
+		TextRender()->TextEx(&Marker, "|", -1);
+		TextRender()->TextEx(&Cursor, aInputString+pConsole->m_Input.GetCursorOffset(), -1);
+		
+		// render possible commands
+		if(m_ConsoleType == 0 || Client()->RconAuthed())
+		{
+			if(pConsole->m_Input.GetString()[0] != 0)
 			{
-				if(console->command)
+				m_pConsole->PossibleCommands(pConsole->m_aCompletionBuffer, pConsole->m_CompletionFlagmask, PossibleCommandsRenderCallback, &Info);
+				
+				if(Info.m_EnumCount <= 0)
 				{
-					
-					char buf[512];
-					str_format(buf, sizeof(buf), "Help: %s ", console->command->help);
-					gfx_text_ex(&info.cursor, buf, -1);
-					gfx_text_color(0.75f, 0.75f, 0.75f, 1);
-					str_format(buf, sizeof(buf), "Syntax: %s %s", console->command->name, console->command->params);
-					gfx_text_ex(&info.cursor, buf, -1);
+					if(pConsole->m_pCommand)
+					{
+						
+						char aBuf[512];
+						str_format(aBuf, sizeof(aBuf), "Help: %s ", pConsole->m_pCommand->m_pHelp);
+						TextRender()->TextEx(&Info.m_Cursor, aBuf, -1);
+						TextRender()->TextColor(0.75f, 0.75f, 0.75f, 1);
+						str_format(aBuf, sizeof(aBuf), "Syntax: %s %s", pConsole->m_pCommand->m_pName, pConsole->m_pCommand->m_pParams);
+						TextRender()->TextEx(&Info.m_Cursor, aBuf, -1);
+					}
 				}
 			}
 		}
-		gfx_text_color(1,1,1,1);
+		TextRender()->TextColor(1,1,1,1);
 
-		// render log
-		y -= row_height;
-		char *entry = console->backlog.Last();
-		while (y > 0.0f && entry)
+		//	render log (actual page, wrap lines)
+		char *pEntry = pConsole->m_Backlog.Last();
+		for(int Page = 0, Lines = 0; Page <= pConsole->m_BacklogActPage; ++Page, Lines = 0)
 		{
-			gfx_text(0, x, y, font_size, entry, -1);
-			y -= row_height;
+			//	next page when lines reach the top
+			while(y - Lines * RowHeight > RowHeight && pEntry)
+			{
+				Lines += TextRender()->TextLineCount(0, FontSize, pEntry, Screen.w-10);
+				//	just render output from actual backlog page (render bottom up)
+				if(Page == pConsole->m_BacklogActPage)
+				{
+					TextRender()->SetCursor(&Cursor, 0, y - Lines * RowHeight, FontSize, TEXTFLAG_RENDER);
+					Cursor.m_LineWidth = Screen.w-10;
+					TextRender()->TextEx(&Cursor, pEntry, -1);
+				}
+				pEntry = pConsole->m_Backlog.Prev(pEntry);
+			}
 
-			entry = console->backlog.Prev(entry);
+			//	actual backlog page number is too high, render last available page (current checked one, render top down)
+			if(!pEntry && Page < pConsole->m_BacklogActPage)
+			{
+				pConsole->m_BacklogActPage = Page;
+				pEntry = pConsole->m_Backlog.First();
+				while(Lines > 0 && pEntry)
+				{
+					TextRender()->SetCursor(&Cursor, 0, y - Lines * RowHeight, FontSize, TEXTFLAG_RENDER);
+					Cursor.m_LineWidth = Screen.w-10;
+					Cursor.m_LineCount = 1;
+					TextRender()->TextEx(&Cursor, pEntry, -1);
+					Lines -= Cursor.m_LineCount;
+					pEntry = pConsole->m_Backlog.Next(pEntry);
+				}
+				break;
+			}
 		}
 	}	
 }
 
-void CONSOLE::on_message(int msgtype, void *rawmsg)
+void CGameConsole::OnMessage(int MsgType, void *pRawMsg)
 {
 }
 
-bool CONSOLE::on_input(INPUT_EVENT e)
+bool CGameConsole::OnInput(IInput::CEvent Event)
 {
-	if(console_state == CONSOLE_CLOSED)
+	if(m_ConsoleState == CONSOLE_CLOSED)
 		return false;
-	if(e.key >= KEY_F1 && e.key <= KEY_F15)
+	if(Event.m_Key >= KEY_F1 && Event.m_Key <= KEY_F15)
 		return false;
 
-	if(e.key == KEY_ESCAPE && (e.flags&INPFLAG_PRESS))
-		toggle(console_type);
+	if(Event.m_Key == KEY_ESCAPE && (Event.m_Flags&IInput::FLAG_PRESS))
+		Toggle(m_ConsoleType);
 	else
-		current_console()->on_input(e);
+		CurrentConsole()->OnInput(Event);
 		
 	return true;
 }
 
-void CONSOLE::toggle(int type)
+void CGameConsole::Toggle(int Type)
 {
-	if(console_type != type && (console_state == CONSOLE_OPEN || console_state == CONSOLE_OPENING))
+	if(m_ConsoleType != Type && (m_ConsoleState == CONSOLE_OPEN || m_ConsoleState == CONSOLE_OPENING))
 	{
 		// don't toggle console, just switch what console to use
 	}
 	else
 	{	
-		if (console_state == CONSOLE_CLOSED || console_state == CONSOLE_OPEN)
+		if (m_ConsoleState == CONSOLE_CLOSED || m_ConsoleState == CONSOLE_OPEN)
 		{
-			state_change_end = time_now()+state_change_duration;
+			m_StateChangeEnd = TimeNow()+m_StateChangeDuration;
 		}
 		else
 		{
-			float progress = state_change_end-time_now();
-			float reversed_progress = state_change_duration-progress;
+			float Progress = m_StateChangeEnd-TimeNow();
+			float ReversedProgress = m_StateChangeDuration-Progress;
 
-			state_change_end = time_now()+reversed_progress;
+			m_StateChangeEnd = TimeNow()+ReversedProgress;
 		}
 
-		if (console_state == CONSOLE_CLOSED || console_state == CONSOLE_CLOSING)
+		if (m_ConsoleState == CONSOLE_CLOSED || m_ConsoleState == CONSOLE_CLOSING)
 		{
-			inp_mouse_mode_absolute();
-			console_state = CONSOLE_OPENING;
+			Input()->MouseModeAbsolute();
+			m_pClient->m_pMenus->UseMouseButtons(false);
+			m_ConsoleState = CONSOLE_OPENING;
 		}
 		else
 		{
-			inp_mouse_mode_relative();
-			console_state = CONSOLE_CLOSING;
+			Input()->MouseModeRelative();
+			m_pClient->m_pMenus->UseMouseButtons(true);
+			m_ConsoleState = CONSOLE_CLOSING;
 		}
 	}
 
-	console_type = type;
+	m_ConsoleType = Type;
 }
 
-void CONSOLE::con_toggle_local_console(void *result, void *user_data)
+void CGameConsole::ConToggleLocalConsole(IConsole::IResult *pResult, void *pUserData)
 {
-	((CONSOLE *)user_data)->toggle(0);
+	((CGameConsole *)pUserData)->Toggle(0);
 }
 
-void CONSOLE::con_toggle_remote_console(void *result, void *user_data)
+void CGameConsole::ConToggleRemoteConsole(IConsole::IResult *pResult, void *pUserData)
 {
-	((CONSOLE *)user_data)->toggle(1);
+	((CGameConsole *)pUserData)->Toggle(1);
 }
 
-void CONSOLE::client_console_print_callback(const char *str, void *user_data)
+void CGameConsole::ClientConsolePrintCallback(const char *pStr, void *pUserData)
 {
-	((CONSOLE *)user_data)->local_console.print_line(str);
+	((CGameConsole *)pUserData)->m_LocalConsole.PrintLine(pStr);
 }
 
-void CONSOLE::print_line(int type, const char *line)
+void CGameConsole::PrintLine(int Type, const char *pLine)
 {
-	if(type == 0)
-		local_console.print_line(line);
-	else if(type == 1)
-		remote_console.print_line(line);
+	if(Type == 0)
+		m_LocalConsole.PrintLine(pLine);
+	else if(Type == 1)
+		m_RemoteConsole.PrintLine(pLine);
 }
 
-void CONSOLE::on_console_init()
+void CGameConsole::OnConsoleInit()
 {
+	m_pConsole = Kernel()->RequestInterface<IConsole>();
+	
 	//
-	console_register_print_callback(client_console_print_callback, this);
+	Console()->RegisterPrintCallback(ClientConsolePrintCallback, this);
 	
-	MACRO_REGISTER_COMMAND("toggle_local_console", "", CFGFLAG_CLIENT, con_toggle_local_console, this, "Toggle local console");
-	MACRO_REGISTER_COMMAND("toggle_remote_console", "", CFGFLAG_CLIENT, con_toggle_remote_console, this, "Toggle remote console");
+	Console()->Register("toggle_local_console", "", CFGFLAG_CLIENT, ConToggleLocalConsole, this, "Toggle local console");
+	Console()->Register("toggle_remote_console", "", CFGFLAG_CLIENT, ConToggleRemoteConsole, this, "Toggle remote console");
 }
 
 /*
diff --git a/src/game/client/components/console.h b/src/game/client/components/console.h
new file mode 100644
index 00000000..b88c6349
--- /dev/null
+++ b/src/game/client/components/console.h
@@ -0,0 +1,72 @@
+#ifndef GAME_CLIENT_COMPONENTS_CONSOLE_H
+#define GAME_CLIENT_COMPONENTS_CONSOLE_H
+#include <engine/shared/ringbuffer.h>
+#include <game/client/component.h>
+#include <game/client/lineinput.h>
+
+class CGameConsole : public CComponent
+{
+	class CInstance
+	{
+	public:
+		TStaticRingBuffer<char, 64*1024, CRingBufferBase::FLAG_RECYCLE> m_Backlog;
+		TStaticRingBuffer<char, 64*1024, CRingBufferBase::FLAG_RECYCLE> m_History;
+		char *m_pHistoryEntry;
+
+		CLineInput m_Input;
+		int m_Type;
+		int m_CompletionEnumerationCount;
+		int m_BacklogActPage;
+		
+	public:
+		CGameConsole *m_pGameConsole;
+		
+		char m_aCompletionBuffer[128];
+		int m_CompletionChosen;
+		int m_CompletionFlagmask;
+		
+		IConsole::CCommandInfo *m_pCommand;
+
+		CInstance(CGameConsole *pGameConsole, int t);
+
+		void ExecuteLine(const char *pLine);
+		
+		void OnInput(IInput::CEvent Event);
+		void PrintLine(const char *pLine);
+		
+		const char *GetString() const { return m_Input.GetString(); }
+		static void PossibleCommandsCompleteCallback(const char *pStr, void *pUser);
+	};
+	
+	class IConsole *m_pConsole;
+	
+	CInstance m_LocalConsole;
+	CInstance m_RemoteConsole;
+	
+	CInstance *CurrentConsole();
+	float TimeNow();
+	
+	int m_ConsoleType;
+	int m_ConsoleState;
+	float m_StateChangeEnd;
+	float m_StateChangeDuration;
+
+	void Toggle(int Type);
+
+	static void PossibleCommandsRenderCallback(const char *pStr, void *pUser);
+	static void ClientConsolePrintCallback(const char *pStr, void *pUserData);
+	static void ConToggleLocalConsole(IConsole::IResult *pResult, void *pUserData);
+	static void ConToggleRemoteConsole(IConsole::IResult *pResult, void *pUserData);
+	
+public:
+	CGameConsole();
+
+	void PrintLine(int Type, const char *pLine);
+
+	virtual void OnConsoleInit();
+	virtual void OnReset();
+	virtual void OnRender();
+	virtual void OnMessage(int MsgType, void *pRawMsg);
+	virtual bool OnInput(IInput::CEvent Events);
+};
+#endif
diff --git a/src/game/client/components/console.hpp b/src/game/client/components/console.hpp
deleted file mode 100644
index 78da98b8..00000000
--- a/src/game/client/components/console.hpp
+++ /dev/null
@@ -1,68 +0,0 @@
-#include <engine/e_client_interface.h>
-#include <engine/e_ringbuffer.h>
-#include <game/client/component.hpp>
-#include <game/client/lineinput.hpp>
-
-class CONSOLE : public COMPONENT
-{
-	class INSTANCE
-	{
-	public:
-		TStaticRingBuffer<char, 64*1024, CRingBufferBase::FLAG_RECYCLE> backlog;
-		TStaticRingBuffer<char, 64*1024, CRingBufferBase::FLAG_RECYCLE> history;
-		char *history_entry;
-
-		LINEINPUT input;
-		
-		int type;
-		int completion_enumeration_count;
-		
-	public:
-		char completion_buffer[128];
-		int completion_chosen;
-		int completion_flagmask;
-		
-		COMMAND *command;
-
-		INSTANCE(int t);
-
-		void execute_line(const char *line);
-		
-		void on_input(INPUT_EVENT e);
-		void print_line(const char *line);
-		
-		const char *get_string() const { return input.get_string(); }
-
-		static void possible_commands_complete_callback(const char *str, void *user);
-	};
-	
-	INSTANCE local_console;
-	INSTANCE remote_console;
-	
-	INSTANCE *current_console();
-	float time_now();
-	
-	int console_type;
-	int console_state;
-	float state_change_end;
-	float state_change_duration;
-
-
-	void toggle(int type);
-
-	static void possible_commands_render_callback(const char *str, void *user);
-	static void client_console_print_callback(const char *str, void *user_data);
-	static void con_toggle_local_console(void *result, void *user_data);
-	static void con_toggle_remote_console(void *result, void *user_data);
-	
-public:
-	CONSOLE();
-
-	void print_line(int type, const char *line);
-
-	virtual void on_console_init();
-	virtual void on_reset();
-	virtual void on_render();
-	virtual void on_message(int msgtype, void *rawmsg);
-	virtual bool on_input(INPUT_EVENT e);
-};
diff --git a/src/game/client/components/controls.cpp b/src/game/client/components/controls.cpp
index b48fb198..714f8b0c 100644
--- a/src/game/client/components/controls.cpp
+++ b/src/game/client/components/controls.cpp
@@ -1,210 +1,215 @@
-#include <engine/e_client_interface.h>
-#include <base/math.hpp>
-#include <game/collision.hpp>
-#include <game/client/gameclient.hpp>
-#include <game/client/component.hpp>
-#include <game/client/components/chat.hpp>
-#include <game/client/components/menus.hpp>
+#include <base/math.h>
 
-#include "controls.hpp"
+#include <engine/shared/config.h>
 
-CONTROLS::CONTROLS()
+#include <game/collision.h>
+#include <game/client/gameclient.h>
+#include <game/client/component.h>
+#include <game/client/components/chat.h>
+#include <game/client/components/menus.h>
+
+#include "controls.h"
+
+CControls::CControls()
 {
 }
 
-static void con_key_input_state(void *result, void *user_data)
+static void ConKeyInputState(IConsole::IResult *pResult, void *pUserData)
 {
-	((int *)user_data)[0] = console_arg_int(result, 0);
+	((int *)pUserData)[0] = pResult->GetInteger(0);
 }
 
-static void con_key_input_counter(void *result, void *user_data)
+static void ConKeyInputCounter(IConsole::IResult *pResult, void *pUserData)
 {
-	int *v = (int *)user_data;
-	if(((*v)&1) != console_arg_int(result, 0))
+	int *v = (int *)pUserData;
+	if(((*v)&1) != pResult->GetInteger(0))
 		(*v)++;
 	*v &= INPUT_STATE_MASK;
 }
 
-struct INPUTSET
+struct CInputSet
 {
-	CONTROLS *controls;
-	int *variable;
-	int value;
+	CControls *m_pControls;
+	int *m_pVariable;
+	int m_Value;
 };
 
-static void con_key_input_set(void *result, void *user_data)
+static void ConKeyInputSet(IConsole::IResult *pResult, void *pUserData)
 {
-	INPUTSET *set = (INPUTSET *)user_data;
-	if(console_arg_int(result, 0))
-		*set->variable = set->value;
+	CInputSet *pSet = (CInputSet *)pUserData;
+	if(pResult->GetInteger(0))
+		*pSet->m_pVariable = pSet->m_Value;
 }
 
-static void con_key_input_nextprev_weapon(void *result, void *user_data)
+static void ConKeyInputNextPrevWeapon(IConsole::IResult *pResult, void *pUserData)
 {
-	INPUTSET *set = (INPUTSET *)user_data;
-	con_key_input_counter(result, set->variable);
-	set->controls->input_data.wanted_weapon = 0;
+	CInputSet *pSet = (CInputSet *)pUserData;
+	ConKeyInputCounter(pResult, pSet->m_pVariable);
+	pSet->m_pControls->m_InputData.m_WantedWeapon = 0;
 }
 
-void CONTROLS::on_console_init()
+void CControls::OnConsoleInit()
 {
 	// game commands
-	MACRO_REGISTER_COMMAND("+left", "", CFGFLAG_CLIENT, con_key_input_state, &input_direction_left, "Move left");
-	MACRO_REGISTER_COMMAND("+right", "", CFGFLAG_CLIENT, con_key_input_state, &input_direction_right, "Move right");
-	MACRO_REGISTER_COMMAND("+jump", "", CFGFLAG_CLIENT, con_key_input_state, &input_data.jump, "Jump");
-	MACRO_REGISTER_COMMAND("+hook", "", CFGFLAG_CLIENT, con_key_input_state, &input_data.hook, "Hook");
-	MACRO_REGISTER_COMMAND("+fire", "", CFGFLAG_CLIENT, con_key_input_counter, &input_data.fire, "Fire");
-
-	{ static INPUTSET set = {this, &input_data.wanted_weapon, 1};  MACRO_REGISTER_COMMAND("+weapon1", "", CFGFLAG_CLIENT, con_key_input_set, (void *)&set, "Switch to hammer"); }
-	{ static INPUTSET set = {this, &input_data.wanted_weapon, 2};  MACRO_REGISTER_COMMAND("+weapon2", "", CFGFLAG_CLIENT, con_key_input_set, (void *)&set, "Switch to gun"); }
-	{ static INPUTSET set = {this, &input_data.wanted_weapon, 3};  MACRO_REGISTER_COMMAND("+weapon3", "", CFGFLAG_CLIENT, con_key_input_set, (void *)&set, "Switch to shotgun"); }
-	{ static INPUTSET set = {this, &input_data.wanted_weapon, 4};  MACRO_REGISTER_COMMAND("+weapon4", "", CFGFLAG_CLIENT, con_key_input_set, (void *)&set, "Switch to grenade"); }
-	{ static INPUTSET set = {this, &input_data.wanted_weapon, 5};  MACRO_REGISTER_COMMAND("+weapon5", "", CFGFLAG_CLIENT, con_key_input_set, (void *)&set, "Switch to rifle"); }
-
-	{ static INPUTSET set = {this, &input_data.next_weapon, 0};  MACRO_REGISTER_COMMAND("+nextweapon", "", CFGFLAG_CLIENT, con_key_input_nextprev_weapon, (void *)&set, "Switch to next weapon"); }
-	{ static INPUTSET set = {this, &input_data.prev_weapon, 0};  MACRO_REGISTER_COMMAND("+prevweapon", "", CFGFLAG_CLIENT, con_key_input_nextprev_weapon, (void *)&set, "Switch to previous weapon"); }
+	Console()->Register("+left", "", CFGFLAG_CLIENT, ConKeyInputState, &m_InputDirectionLeft, "Move left");
+	Console()->Register("+right", "", CFGFLAG_CLIENT, ConKeyInputState, &m_InputDirectionRight, "Move right");
+	Console()->Register("+jump", "", CFGFLAG_CLIENT, ConKeyInputState, &m_InputData.m_Jump, "Jump");
+	Console()->Register("+hook", "", CFGFLAG_CLIENT, ConKeyInputState, &m_InputData.m_Hook, "Hook");
+	Console()->Register("+fire", "", CFGFLAG_CLIENT, ConKeyInputCounter, &m_InputData.m_Fire, "Fire");
+
+	{ static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 1};  Console()->Register("+weapon1", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to hammer"); }
+	{ static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 2};  Console()->Register("+weapon2", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to gun"); }
+	{ static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 3};  Console()->Register("+weapon3", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to shotgun"); }
+	{ static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 4};  Console()->Register("+weapon4", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to grenade"); }
+	{ static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 5};  Console()->Register("+weapon5", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to rifle"); }
+
+	{ static CInputSet s_Set = {this, &m_InputData.m_NextWeapon, 0};  Console()->Register("+nextweapon", "", CFGFLAG_CLIENT, ConKeyInputNextPrevWeapon, (void *)&s_Set, "Switch to next weapon"); }
+	{ static CInputSet s_Set = {this, &m_InputData.m_PrevWeapon, 0};  Console()->Register("+prevweapon", "", CFGFLAG_CLIENT, ConKeyInputNextPrevWeapon, (void *)&s_Set, "Switch to previous weapon"); }
 }
 
-void CONTROLS::on_message(int msg, void *rawmsg)
+void CControls::OnMessage(int Msg, void *pRawMsg)
 {
-    if(msg == NETMSGTYPE_SV_WEAPONPICKUP)
+    if(Msg == NETMSGTYPE_SV_WEAPONPICKUP)
     {
-    	NETMSG_SV_WEAPONPICKUP *msg = (NETMSG_SV_WEAPONPICKUP *)rawmsg;
-        if(config.cl_autoswitch_weapons)
-        	input_data.wanted_weapon = msg->weapon+1;
+    	CNetMsg_Sv_WeaponPickup *pMsg = (CNetMsg_Sv_WeaponPickup *)pRawMsg;
+        if(g_Config.m_ClAutoswitchWeapons)
+        	m_InputData.m_WantedWeapon = pMsg->m_Weapon+1;
     }
 }
 
-int CONTROLS::snapinput(int *data)
+int CControls::SnapInput(int *pData)
 {
-	static NETOBJ_PLAYER_INPUT last_data = {0};
-	static int64 last_send_time = 0;
-	bool send = false;
+	static CNetObj_PlayerInput LastData = {0};
+	static int64 LastSendTime = 0;
+	bool Send = false;
 	
 	// update player state
-	if(gameclient.chat->is_active())
-		input_data.player_state = PLAYERSTATE_CHATTING;
-	else if(gameclient.menus->is_active())
-		input_data.player_state = PLAYERSTATE_IN_MENU;
+	if(m_pClient->m_pChat->IsActive())
+		m_InputData.m_PlayerState = PLAYERSTATE_CHATTING;
+	else if(m_pClient->m_pMenus->IsActive())
+		m_InputData.m_PlayerState = PLAYERSTATE_IN_MENU;
 	else
-		input_data.player_state = PLAYERSTATE_PLAYING;
+		m_InputData.m_PlayerState = PLAYERSTATE_PLAYING;
 	
-	if(last_data.player_state != input_data.player_state)
-		send = true;
+	if(LastData.m_PlayerState != m_InputData.m_PlayerState)
+		Send = true;
 		
-	last_data.player_state = input_data.player_state;
+	LastData.m_PlayerState = m_InputData.m_PlayerState;
 	
 	// we freeze the input if chat or menu is activated
-	if(input_data.player_state != PLAYERSTATE_PLAYING)
+	if(m_InputData.m_PlayerState != PLAYERSTATE_PLAYING)
 	{
-		last_data.direction = 0;
-		last_data.hook = 0;
-		last_data.jump = 0;
-		input_data = last_data;
+		LastData.m_Direction = 0;
+		LastData.m_Hook = 0;
+		LastData.m_Jump = 0;
+		m_InputData = LastData;
 		
-		input_direction_left = 0;
-		input_direction_right = 0;
+		m_InputDirectionLeft = 0;
+		m_InputDirectionRight = 0;
 			
-		mem_copy(data, &input_data, sizeof(input_data));
+		mem_copy(pData, &m_InputData, sizeof(m_InputData));
 
 		// send once a second just to be sure
-		if(time_get() > last_send_time + time_freq())
-			send = true;
+		if(time_get() > LastSendTime + time_freq())
+			Send = true;
 	}
 	else
 	{
 		
-		input_data.target_x = (int)mouse_pos.x;
-		input_data.target_y = (int)mouse_pos.y;
-		if(!input_data.target_x && !input_data.target_y)
-			input_data.target_y = 1;
+		m_InputData.m_TargetX = (int)m_MousePos.x;
+		m_InputData.m_TargetY = (int)m_MousePos.y;
+		if(!m_InputData.m_TargetX && !m_InputData.m_TargetY)
+		{
+			m_InputData.m_TargetX = 1;
+			m_MousePos.x = 1;
+		}
 			
 		// set direction
-		input_data.direction = 0;
-		if(input_direction_left && !input_direction_right)
-			input_data.direction = -1;
-		if(!input_direction_left && input_direction_right)
-			input_data.direction = 1;
+		m_InputData.m_Direction = 0;
+		if(m_InputDirectionLeft && !m_InputDirectionRight)
+			m_InputData.m_Direction = -1;
+		if(!m_InputDirectionLeft && m_InputDirectionRight)
+			m_InputData.m_Direction = 1;
 
 		// stress testing
-		if(config.dbg_stress)
+		if(g_Config.m_DbgStress)
 		{
-			float t = client_localtime();
-			mem_zero(&input_data, sizeof(input_data));
-
-			input_data.direction = ((int)t/2)&1;
-			input_data.jump = ((int)t);
-			input_data.fire = ((int)(t*10));
-			input_data.hook = ((int)(t*2))&1;
-			input_data.wanted_weapon = ((int)t)%NUM_WEAPONS;
-			input_data.target_x = (int)(sinf(t*3)*100.0f);
-			input_data.target_y = (int)(cosf(t*3)*100.0f);
+			float t = Client()->LocalTime();
+			mem_zero(&m_InputData, sizeof(m_InputData));
+
+			m_InputData.m_Direction = ((int)t/2)&1;
+			m_InputData.m_Jump = ((int)t);
+			m_InputData.m_Fire = ((int)(t*10));
+			m_InputData.m_Hook = ((int)(t*2))&1;
+			m_InputData.m_WantedWeapon = ((int)t)%NUM_WEAPONS;
+			m_InputData.m_TargetX = (int)(sinf(t*3)*100.0f);
+			m_InputData.m_TargetY = (int)(cosf(t*3)*100.0f);
 		}
 
 		// check if we need to send input
-		if(input_data.direction != last_data.direction) send = true;
-		else if(input_data.jump != last_data.jump) send = true;
-		else if(input_data.fire != last_data.fire) send = true;
-		else if(input_data.hook != last_data.hook) send = true;
-		else if(input_data.player_state != last_data.player_state) send = true;
-		else if(input_data.wanted_weapon != last_data.wanted_weapon) send = true;
-		else if(input_data.next_weapon != last_data.next_weapon) send = true;
-		else if(input_data.prev_weapon != last_data.prev_weapon) send = true;
+		if(m_InputData.m_Direction != LastData.m_Direction) Send = true;
+		else if(m_InputData.m_Jump != LastData.m_Jump) Send = true;
+		else if(m_InputData.m_Fire != LastData.m_Fire) Send = true;
+		else if(m_InputData.m_Hook != LastData.m_Hook) Send = true;
+		else if(m_InputData.m_PlayerState != LastData.m_PlayerState) Send = true;
+		else if(m_InputData.m_WantedWeapon != LastData.m_WantedWeapon) Send = true;
+		else if(m_InputData.m_NextWeapon != LastData.m_NextWeapon) Send = true;
+		else if(m_InputData.m_PrevWeapon != LastData.m_PrevWeapon) Send = true;
 
 		// send at at least 10hz
-		if(time_get() > last_send_time + time_freq()/25)
-			send = true;
+		if(time_get() > LastSendTime + time_freq()/25)
+			Send = true;
 	}
 	
 	// copy and return size	
-	last_data = input_data;
+	LastData = m_InputData;
 	
-	if(!send)
+	if(!Send)
 		return 0;
 		
-	last_send_time = time_get();
-	mem_copy(data, &input_data, sizeof(input_data));
-	return sizeof(input_data);	
+	LastSendTime = time_get();
+	mem_copy(pData, &m_InputData, sizeof(m_InputData));
+	return sizeof(m_InputData);	
 }
 
-void CONTROLS::on_render()
+void CControls::OnRender()
 {
 	// update target pos
-	if(gameclient.snap.gameobj && !(gameclient.snap.gameobj->paused || gameclient.snap.spectate))
-		target_pos = gameclient.local_character_pos + mouse_pos;
+	if(m_pClient->m_Snap.m_pGameobj && !(m_pClient->m_Snap.m_pGameobj->m_Paused || m_pClient->m_Snap.m_Spectate))
+		m_TargetPos = m_pClient->m_LocalCharacterPos + m_MousePos;
 }
 
-bool CONTROLS::on_mousemove(float x, float y)
+bool CControls::OnMouseMove(float x, float y)
 {
-	if(gameclient.snap.gameobj && gameclient.snap.gameobj->paused)
+	if(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_Paused)
 		return false;
-	mouse_pos += vec2(x, y); // TODO: ugly
+	m_MousePos += vec2(x, y); // TODO: ugly
 
 	//
-	float camera_max_distance = 200.0f;
-	float follow_factor = config.cl_mouse_followfactor/100.0f;
-	float deadzone = config.cl_mouse_deadzone;
-	float mouse_max = min(camera_max_distance/follow_factor + deadzone, (float)config.cl_mouse_max_distance);
+	float CameraMaxDistance = 200.0f;
+	float FollowFactor = g_Config.m_ClMouseFollowfactor/100.0f;
+	float DeadZone = g_Config.m_ClMouseDeadzone;
+	float MouseMax = min(CameraMaxDistance/FollowFactor + DeadZone, (float)g_Config.m_ClMouseMaxDistance);
 	
 	//vec2 camera_offset(0, 0);
 
-	if(gameclient.snap.spectate)
+	if(m_pClient->m_Snap.m_Spectate)
 	{
-		if(mouse_pos.x < 200.0f) mouse_pos.x = 200.0f;
-		if(mouse_pos.y < 200.0f) mouse_pos.y = 200.0f;
-		if(mouse_pos.x > col_width()*32-200.0f) mouse_pos.x = col_width()*32-200.0f;
-		if(mouse_pos.y > col_height()*32-200.0f) mouse_pos.y = col_height()*32-200.0f;
+		if(m_MousePos.x < 200.0f) m_MousePos.x = 200.0f;
+		if(m_MousePos.y < 200.0f) m_MousePos.y = 200.0f;
+		if(m_MousePos.x > Collision()->GetWidth()*32-200.0f) m_MousePos.x = Collision()->GetWidth()*32-200.0f;
+		if(m_MousePos.y > Collision()->GetHeight()*32-200.0f) m_MousePos.y = Collision()->GetHeight()*32-200.0f;
 		
-		target_pos = mouse_pos;
+		m_TargetPos = m_MousePos;
 	}
 	else
 	{
-		float l = length(mouse_pos);
+		float l = length(m_MousePos);
 		
-		if(l > mouse_max)
+		if(l > MouseMax)
 		{
-			mouse_pos = normalize(mouse_pos)*mouse_max;
-			l = mouse_max;
+			m_MousePos = normalize(m_MousePos)*MouseMax;
+			l = MouseMax;
 		}
 		
 		//float offset_amount = max(l-deadzone, 0.0f) * follow_factor;
diff --git a/src/game/client/components/controls.h b/src/game/client/components/controls.h
new file mode 100644
index 00000000..7453d5d7
--- /dev/null
+++ b/src/game/client/components/controls.h
@@ -0,0 +1,25 @@
+#ifndef GAME_CLIENT_COMPONENTS_CONTROLS_H
+#define GAME_CLIENT_COMPONENTS_CONTROLS_H
+#include <base/vmath.h>
+#include <game/client/component.h>
+
+class CControls : public CComponent
+{	
+public:
+	vec2 m_MousePos;
+	vec2 m_TargetPos;
+
+	CNetObj_PlayerInput m_InputData;
+	int m_InputDirectionLeft;
+	int m_InputDirectionRight;
+
+	CControls();
+	
+	virtual void OnRender();
+	virtual void OnMessage(int MsgType, void *pRawMsg);
+	virtual bool OnMouseMove(float x, float y);
+	virtual void OnConsoleInit();
+	
+	int SnapInput(int *pData);
+};
+#endif
diff --git a/src/game/client/components/controls.hpp b/src/game/client/components/controls.hpp
deleted file mode 100644
index e33d24f5..00000000
--- a/src/game/client/components/controls.hpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <base/vmath.hpp>
-#include <game/client/component.hpp>
-
-class CONTROLS : public COMPONENT
-{	
-public:
-	vec2 mouse_pos;
-	vec2 target_pos;
-
-	NETOBJ_PLAYER_INPUT input_data;
-	int input_direction_left;
-	int input_direction_right;
-
-	CONTROLS();
-	
-	virtual void on_render();
-	virtual void on_message(int msg, void *rawmsg);
-	virtual bool on_mousemove(float x, float y);
-	virtual void on_console_init();
-	
-	int snapinput(int *data);
-};
diff --git a/src/game/client/components/damageind.cpp b/src/game/client/components/damageind.cpp
index 7f1991dc..8dfbf022 100644
--- a/src/game/client/components/damageind.cpp
+++ b/src/game/client/components/damageind.cpp
@@ -1,65 +1,64 @@
-#include <engine/e_client_interface.h>
-#include <engine/client/graphics.h>
-#include <game/generated/g_protocol.hpp>
-#include <game/generated/gc_data.hpp>
+#include <engine/graphics.h>
+#include <game/generated/protocol.h>
+#include <game/generated/client_data.h>
 
-#include <game/gamecore.hpp> // get_angle
-#include <game/client/ui.hpp>
-#include <game/client/render.hpp>
-#include "damageind.hpp"
+#include <game/gamecore.h> // get_angle
+#include <game/client/ui.h>
+#include <game/client/render.h>
+#include "damageind.h"
 
-DAMAGEIND::DAMAGEIND()
+CDamageInd::CDamageInd()
 {
-	lastupdate = 0;
-	num_items = 0;
+	m_Lastupdate = 0;
+	m_NumItems = 0;
 }
 
-DAMAGEIND::ITEM *DAMAGEIND::create_i()
+CDamageInd::CItem *CDamageInd::CreateI()
 {
-	if (num_items < MAX_ITEMS)
+	if (m_NumItems < MAX_ITEMS)
 	{
-		ITEM *p = &items[num_items];
-		num_items++;
+		CItem *p = &m_aItems[m_NumItems];
+		m_NumItems++;
 		return p;
 	}
 	return 0;
 }
 
-void DAMAGEIND::destroy_i(DAMAGEIND::ITEM *i)
+void CDamageInd::DestroyI(CDamageInd::CItem *i)
 {
-	num_items--;
-	*i = items[num_items];
+	m_NumItems--;
+	*i = m_aItems[m_NumItems];
 }
 
-void DAMAGEIND::create(vec2 pos, vec2 dir)
+void CDamageInd::Create(vec2 Pos, vec2 Dir)
 {
-	ITEM *i = create_i();
+	CItem *i = CreateI();
 	if (i)
 	{
-		i->pos = pos;
-		i->life = 0.75f;
-		i->dir = dir*-1;
-		i->startangle = (( (float)rand()/(float)RAND_MAX) - 1.0f) * 2.0f * pi;
+		i->m_Pos = Pos;
+		i->m_Life = 0.75f;
+		i->m_Dir = Dir*-1;
+		i->m_StartAngle = (( (float)rand()/(float)RAND_MAX) - 1.0f) * 2.0f * pi;
 	}
 }
 
-void DAMAGEIND::on_render()
+void CDamageInd::OnRender()
 {
-	Graphics()->TextureSet(data->images[IMAGE_GAME].id);
+	Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
 	Graphics()->QuadsBegin();
-	for(int i = 0; i < num_items;)
+	for(int i = 0; i < m_NumItems;)
 	{
-		vec2 pos = mix(items[i].pos+items[i].dir*75.0f, items[i].pos, clamp((items[i].life-0.60f)/0.15f, 0.0f, 1.0f));
+		vec2 Pos = mix(m_aItems[i].m_Pos+m_aItems[i].m_Dir*75.0f, m_aItems[i].m_Pos, clamp((m_aItems[i].m_Life-0.60f)/0.15f, 0.0f, 1.0f));
 
-		items[i].life -= client_frametime();
-		if(items[i].life < 0.0f)
-			destroy_i(&items[i]);
+		m_aItems[i].m_Life -= Client()->FrameTime();
+		if(m_aItems[i].m_Life < 0.0f)
+			DestroyI(&m_aItems[i]);
 		else
 		{
-			Graphics()->SetColor(1.0f,1.0f,1.0f, items[i].life/0.1f);
-			Graphics()->QuadsSetRotation(items[i].startangle + items[i].life * 2.0f);
-			RenderTools()->select_sprite(SPRITE_STAR1);
-			RenderTools()->draw_sprite(pos.x, pos.y, 48.0f);
+			Graphics()->SetColor(1.0f,1.0f,1.0f, m_aItems[i].m_Life/0.1f);
+			Graphics()->QuadsSetRotation(m_aItems[i].m_StartAngle + m_aItems[i].m_Life * 2.0f);
+			RenderTools()->SelectSprite(SPRITE_STAR1);
+			RenderTools()->DrawSprite(Pos.x, Pos.y, 48.0f);
 			i++;
 		}
 	}
diff --git a/src/game/client/components/damageind.h b/src/game/client/components/damageind.h
new file mode 100644
index 00000000..b6e0bb47
--- /dev/null
+++ b/src/game/client/components/damageind.h
@@ -0,0 +1,34 @@
+#ifndef GAME_CLIENT_COMPONENTS_DAMAGEIND_H
+#define GAME_CLIENT_COMPONENTS_DAMAGEIND_H
+#include <base/vmath.h>
+#include <game/client/component.h>
+
+class CDamageInd : public CComponent
+{
+	int64 m_Lastupdate;
+	struct CItem
+	{
+		vec2 m_Pos;
+		vec2 m_Dir;
+		float m_Life;
+		float m_StartAngle;
+	};
+
+	enum
+	{
+		MAX_ITEMS=64,
+	};
+
+	CItem m_aItems[MAX_ITEMS];
+	int m_NumItems;
+
+	CItem *CreateI();
+	void DestroyI(CItem *i);
+
+public:	
+	CDamageInd();
+
+	void Create(vec2 Pos, vec2 Dir);
+	virtual void OnRender();
+};
+#endif
diff --git a/src/game/client/components/damageind.hpp b/src/game/client/components/damageind.hpp
deleted file mode 100644
index c74af9ca..00000000
--- a/src/game/client/components/damageind.hpp
+++ /dev/null
@@ -1,31 +0,0 @@
-#include <base/vmath.hpp>
-#include <game/client/component.hpp>
-
-class DAMAGEIND : public COMPONENT
-{
-	int64 lastupdate;
-	struct ITEM
-	{
-		vec2 pos;
-		vec2 dir;
-		float life;
-		float startangle;
-	};
-
-	enum
-	{
-		MAX_ITEMS=64,
-	};
-
-	ITEM items[MAX_ITEMS];
-	int num_items;
-
-	ITEM *create_i();
-	void destroy_i(ITEM *i);
-
-public:	
-	DAMAGEIND();
-
-	void create(vec2 pos, vec2 dir);
-	virtual void on_render();
-};
diff --git a/src/game/client/components/debughud.cpp b/src/game/client/components/debughud.cpp
index c7cc559b..0fa004cb 100644
--- a/src/game/client/components/debughud.cpp
+++ b/src/game/client/components/debughud.cpp
@@ -1,27 +1,23 @@
-#include <memory.h> // memcmp
+#include <engine/shared/config.h>
+#include <engine/graphics.h>
+#include <engine/textrender.h>
 
-extern "C" {
-	#include <engine/e_config.h>
-}
-
-#include <engine/e_client_interface.h>
-#include <engine/client/graphics.h>
-#include <game/generated/g_protocol.hpp>
-#include <game/generated/gc_data.hpp>
+#include <game/generated/protocol.h>
+#include <game/generated/client_data.h>
 
-#include <game/layers.hpp>
+#include <game/layers.h>
 
-#include <game/client/gameclient.hpp>
-#include <game/client/animstate.hpp>
-#include <game/client/render.hpp>
+#include <game/client/gameclient.h>
+#include <game/client/animstate.h>
+#include <game/client/render.h>
 
-//#include "controls.hpp"
-//#include "camera.hpp"
-#include "debughud.hpp"
+//#include "controls.h"
+//#include "camera.h"
+#include "debughud.h"
 
-void DEBUGHUD::render_netcorrections()
+void CDebugHud::RenderNetCorrections()
 {
-	if(!config.debug || !gameclient.snap.local_character || !gameclient.snap.local_prev_character)
+	if(!g_Config.m_Debug || !m_pClient->m_Snap.m_pLocalCharacter || !m_pClient->m_Snap.m_pLocalPrevCharacter)
 		return;
 
 	Graphics()->MapScreen(0, 0, 300*Graphics()->ScreenAspect(), 300);
@@ -29,7 +25,8 @@ void DEBUGHUD::render_netcorrections()
 	/*float speed = distance(vec2(netobjects.local_prev_character->x, netobjects.local_prev_character->y),
 		vec2(netobjects.local_character->x, netobjects.local_character->y));*/
 
-	float velspeed = length(vec2(gameclient.snap.local_character->vx/256.0f, gameclient.snap.local_character->vy/256.0f))*50;
+/*
+	float velspeed = length(vec2(gameclient.snap.local_character->m_VelX/256.0f, gameclient.snap.local_character->m_VelY/256.0f))*50;
 	
 	float ramp = velocity_ramp(velspeed, gameclient.tuning.velramp_start, gameclient.tuning.velramp_range, gameclient.tuning.velramp_curvature);
 	
@@ -37,77 +34,79 @@ void DEBUGHUD::render_netcorrections()
 	str_format(buf, sizeof(buf), "%.0f\n%.0f\n%.2f\n%d %s\n%d %d",
 		velspeed, velspeed*ramp, ramp,
 		netobj_num_corrections(), netobj_corrected_on(),
-		gameclient.snap.local_character->x,
-		gameclient.snap.local_character->y
+		gameclient.snap.local_character->m_X,
+		gameclient.snap.local_character->m_Y
 	);
-	gfx_text(0, 150, 50, 12, buf, -1);
+	TextRender()->Text(0, 150, 50, 12, buf, -1);*/
 }
 
-void DEBUGHUD::render_tuning()
+void CDebugHud::RenderTuning()
 {
 	// render tuning debugging
-	if(!config.dbg_tuning)
+	if(!g_Config.m_DbgTuning)
 		return;
 		
-	TUNING_PARAMS standard_tuning;
+	CTuningParams StandardTuning;
 		
 	Graphics()->MapScreen(0, 0, 300*Graphics()->ScreenAspect(), 300);
 	
 	float y = 50.0f;
-	int count = 0;
-	for(int i = 0; i < gameclient.tuning.num(); i++)
+	int Count = 0;
+	for(int i = 0; i < m_pClient->m_Tuning.Num(); i++)
 	{
-		char buf[128];
-		float current, standard;
-		gameclient.tuning.get(i, &current);
-		standard_tuning.get(i, &standard);
+		char aBuf[128];
+		float Current, Standard;
+		m_pClient->m_Tuning.Get(i, &Current);
+		StandardTuning.Get(i, &Standard);
 		
-		if(standard == current)
-			gfx_text_color(1,1,1,1.0f);
+		if(Standard == Current)
+			TextRender()->TextColor(1,1,1,1.0f);
 		else
-			gfx_text_color(1,0.25f,0.25f,1.0f);
+			TextRender()->TextColor(1,0.25f,0.25f,1.0f);
 
 		float w;
 		float x = 5.0f;
 		
-		str_format(buf, sizeof(buf), "%.2f", standard);
+		str_format(aBuf, sizeof(aBuf), "%.2f", Standard);
 		x += 20.0f;
-		w = gfx_text_width(0, 5, buf, -1);
-		gfx_text(0x0, x-w, y+count*6, 5, buf, -1);
+		w = TextRender()->TextWidth(0, 5, aBuf, -1);
+		TextRender()->Text(0x0, x-w, y+Count*6, 5, aBuf, -1);
 
-		str_format(buf, sizeof(buf), "%.2f", current);
+		str_format(aBuf, sizeof(aBuf), "%.2f", Current);
 		x += 20.0f;
-		w = gfx_text_width(0, 5, buf, -1);
-		gfx_text(0x0, x-w, y+count*6, 5, buf, -1);
+		w = TextRender()->TextWidth(0, 5, aBuf, -1);
+		TextRender()->Text(0x0, x-w, y+Count*6, 5, aBuf, -1);
 
 		x += 5.0f;
-		gfx_text(0x0, x, y+count*6, 5, gameclient.tuning.names[i], -1);
+		TextRender()->Text(0x0, x, y+Count*6, 5, m_pClient->m_Tuning.m_apNames[i], -1);
 		
-		count++;
+		Count++;
 	}
 	
-	y = y+count*6;
+	y = y+Count*6;
 	
 	Graphics()->TextureSet(-1);
 	Graphics()->BlendNormal();
 	Graphics()->LinesBegin();
-	float height = 50.0f;
+	float Height = 50.0f;
 	float pv = 1;
+	IGraphics::CLineItem Array[100];
 	for(int i = 0; i < 100; i++)
 	{
-		float speed = i/100.0f * 3000;
-		float ramp = velocity_ramp(speed, gameclient.tuning.velramp_start, gameclient.tuning.velramp_range, gameclient.tuning.velramp_curvature);
-		float rampedspeed = (speed * ramp)/1000.0f;
-		Graphics()->LinesDraw((i-1)*2, y+height-pv*height, i*2, y+height-rampedspeed*height);
+		float Speed = i/100.0f * 3000;
+		float Ramp = VelocityRamp(Speed, m_pClient->m_Tuning.m_VelrampStart, m_pClient->m_Tuning.m_VelrampRange, m_pClient->m_Tuning.m_VelrampCurvature);
+		float RampedSpeed = (Speed * Ramp)/1000.0f;
+		Array[i] = IGraphics::CLineItem((i-1)*2, y+Height-pv*Height, i*2, y+Height-RampedSpeed*Height);
 		//Graphics()->LinesDraw((i-1)*2, 200, i*2, 200);
-		pv = rampedspeed;
+		pv = RampedSpeed;
 	}
+	Graphics()->LinesDraw(Array, 100);
 	Graphics()->LinesEnd();
-	gfx_text_color(1,1,1,1);
+	TextRender()->TextColor(1,1,1,1);
 }
 
-void DEBUGHUD::on_render()
+void CDebugHud::OnRender()
 {
-	render_tuning();
-	render_netcorrections();
+	RenderTuning();
+	RenderNetCorrections();
 }
diff --git a/src/game/client/components/debughud.h b/src/game/client/components/debughud.h
new file mode 100644
index 00000000..ae1c17ef
--- /dev/null
+++ b/src/game/client/components/debughud.h
@@ -0,0 +1,13 @@
+#ifndef GAME_CLIENT_COMPONENTS_DEBUGHUD_H
+#define GAME_CLIENT_COMPONENTS_DEBUGHUD_H
+#include <game/client/component.h>
+
+class CDebugHud : public CComponent
+{	
+	void RenderNetCorrections();
+	void RenderTuning();
+public:
+	virtual void OnRender();
+};
+
+#endif
diff --git a/src/game/client/components/debughud.hpp b/src/game/client/components/debughud.hpp
deleted file mode 100644
index 473b2ce2..00000000
--- a/src/game/client/components/debughud.hpp
+++ /dev/null
@@ -1,10 +0,0 @@
-#include <game/client/component.hpp>
-
-class DEBUGHUD : public COMPONENT
-{	
-	void render_netcorrections();
-	void render_tuning();
-public:
-	virtual void on_render();
-};
-
diff --git a/src/game/client/components/effects.cpp b/src/game/client/components/effects.cpp
index c9c47a8d..91cea107 100644
--- a/src/game/client/components/effects.cpp
+++ b/src/game/client/components/effects.cpp
@@ -1,183 +1,181 @@
-#include <engine/e_client_interface.h>
-//#include <gc_client.hpp>
-#include <game/generated/gc_data.hpp>
+#include <game/generated/client_data.h>
 
-#include <game/client/components/particles.hpp>
-#include <game/client/components/skins.hpp>
-#include <game/client/components/flow.hpp>
-#include <game/client/components/damageind.hpp>
-#include <game/client/components/sounds.hpp>
-#include <game/client/gameclient.hpp>
+#include <game/client/components/particles.h>
+#include <game/client/components/skins.h>
+#include <game/client/components/flow.h>
+#include <game/client/components/damageind.h>
+#include <game/client/components/sounds.h>
+#include <game/client/gameclient.h>
 
-#include "effects.hpp"
+#include "effects.h"
 
-inline vec2 random_dir() { return normalize(vec2(frandom()-0.5f, frandom()-0.5f)); }
+inline vec2 RandomDir() { return normalize(vec2(frandom()-0.5f, frandom()-0.5f)); }
 
-EFFECTS::EFFECTS()
+CEffects::CEffects()
 {
-	add_50hz = false;
-	add_100hz = false;
+	m_Add50hz = false;
+	m_Add100hz = false;
 }
 
-void EFFECTS::air_jump(vec2 pos)
+void CEffects::AirJump(vec2 Pos)
 {
-	PARTICLE p;
-	p.set_default();
-	p.spr = SPRITE_PART_AIRJUMP;
-	p.pos = pos + vec2(-6.0f, 16.0f);
-	p.vel = vec2(0, -200);
-	p.life_span = 0.5f;
-	p.start_size = 48.0f;
-	p.end_size = 0;
-	p.rot = frandom()*pi*2;
-	p.rotspeed = pi*2;
-	p.gravity = 500;
-	p.friction = 0.7f;
-	p.flow_affected = 0.0f;
-	gameclient.particles->add(PARTICLES::GROUP_GENERAL, &p);
+	CParticle p;
+	p.SetDefault();
+	p.m_Spr = SPRITE_PART_AIRJUMP;
+	p.m_Pos = Pos + vec2(-6.0f, 16.0f);
+	p.m_Vel = vec2(0, -200);
+	p.m_LifeSpan = 0.5f;
+	p.m_StartSize = 48.0f;
+	p.m_EndSize = 0;
+	p.m_Rot = frandom()*pi*2;
+	p.m_Rotspeed = pi*2;
+	p.m_Gravity = 500;
+	p.m_Friction = 0.7f;
+	p.m_FlowAffected = 0.0f;
+	m_pClient->m_pParticles->Add(CParticles::GROUP_GENERAL, &p);
 
-	p.pos = pos + vec2(6.0f, 16.0f);
-	gameclient.particles->add(PARTICLES::GROUP_GENERAL, &p);
+	p.m_Pos = Pos + vec2(6.0f, 16.0f);
+	m_pClient->m_pParticles->Add(CParticles::GROUP_GENERAL, &p);
 	
-	gameclient.sounds->play(SOUNDS::CHN_WORLD, SOUND_PLAYER_AIRJUMP, 1.0f, pos);
+	m_pClient->m_pSounds->Play(CSounds::CHN_WORLD, SOUND_PLAYER_AIRJUMP, 1.0f, Pos);
 }
 
-void EFFECTS::damage_indicator(vec2 pos, vec2 dir)
+void CEffects::DamageIndicator(vec2 Pos, vec2 Dir)
 {
-	gameclient.damageind->create(pos, dir);
+	m_pClient->m_pDamageind->Create(Pos, Dir);
 }
 
-void EFFECTS::powerupshine(vec2 pos, vec2 size)
+void CEffects::PowerupShine(vec2 Pos, vec2 size)
 {
-	if(!add_50hz)
+	if(!m_Add50hz)
 		return;
 		
-	PARTICLE p;
-	p.set_default();
-	p.spr = SPRITE_PART_SLICE;
-	p.pos = pos + vec2((frandom()-0.5f)*size.x, (frandom()-0.5f)*size.y);
-	p.vel = vec2(0, 0);
-	p.life_span = 0.5f;
-	p.start_size = 16.0f;
-	p.end_size = 0;
-	p.rot = frandom()*pi*2;
-	p.rotspeed = pi*2;
-	p.gravity = 500;
-	p.friction = 0.9f;
-	p.flow_affected = 0.0f;
-	gameclient.particles->add(PARTICLES::GROUP_GENERAL, &p);
+	CParticle p;
+	p.SetDefault();
+	p.m_Spr = SPRITE_PART_SLICE;
+	p.m_Pos = Pos + vec2((frandom()-0.5f)*size.x, (frandom()-0.5f)*size.y);
+	p.m_Vel = vec2(0, 0);
+	p.m_LifeSpan = 0.5f;
+	p.m_StartSize = 16.0f;
+	p.m_EndSize = 0;
+	p.m_Rot = frandom()*pi*2;
+	p.m_Rotspeed = pi*2;
+	p.m_Gravity = 500;
+	p.m_Friction = 0.9f;
+	p.m_FlowAffected = 0.0f;
+	m_pClient->m_pParticles->Add(CParticles::GROUP_GENERAL, &p);
 }
 
-void EFFECTS::smoketrail(vec2 pos, vec2 vel)
+void CEffects::SmokeTrail(vec2 Pos, vec2 Vel)
 {
-	if(!add_50hz)
+	if(!m_Add50hz)
 		return;
 		
-	PARTICLE p;
-	p.set_default();
-	p.spr = SPRITE_PART_SMOKE;
-	p.pos = pos;
-	p.vel = vel + random_dir()*50.0f;
-	p.life_span = 0.5f + frandom()*0.5f;
-	p.start_size = 12.0f + frandom()*8;
-	p.end_size = 0;
-	p.friction = 0.7;
-	p.gravity = frandom()*-500.0f;
-	gameclient.particles->add(PARTICLES::GROUP_PROJECTILE_TRAIL, &p);
+	CParticle p;
+	p.SetDefault();
+	p.m_Spr = SPRITE_PART_SMOKE;
+	p.m_Pos = Pos;
+	p.m_Vel = Vel + RandomDir()*50.0f;
+	p.m_LifeSpan = 0.5f + frandom()*0.5f;
+	p.m_StartSize = 12.0f + frandom()*8;
+	p.m_EndSize = 0;
+	p.m_Friction = 0.7;
+	p.m_Gravity = frandom()*-500.0f;
+	m_pClient->m_pParticles->Add(CParticles::GROUP_PROJECTILE_TRAIL, &p);
 }
 
 
-void EFFECTS::skidtrail(vec2 pos, vec2 vel)
+void CEffects::SkidTrail(vec2 Pos, vec2 Vel)
 {
-	if(!add_100hz)
+	if(!m_Add100hz)
 		return;
 	
-	PARTICLE p;
-	p.set_default();
-	p.spr = SPRITE_PART_SMOKE;
-	p.pos = pos;
-	p.vel = vel + random_dir()*50.0f;
-	p.life_span = 0.5f + frandom()*0.5f;
-	p.start_size = 24.0f + frandom()*12;
-	p.end_size = 0;
-	p.friction = 0.7f;
-	p.gravity = frandom()*-500.0f;
-	p.color = vec4(0.75f,0.75f,0.75f,1.0f);
-	gameclient.particles->add(PARTICLES::GROUP_GENERAL, &p);	
+	CParticle p;
+	p.SetDefault();
+	p.m_Spr = SPRITE_PART_SMOKE;
+	p.m_Pos = Pos;
+	p.m_Vel = Vel + RandomDir()*50.0f;
+	p.m_LifeSpan = 0.5f + frandom()*0.5f;
+	p.m_StartSize = 24.0f + frandom()*12;
+	p.m_EndSize = 0;
+	p.m_Friction = 0.7f;
+	p.m_Gravity = frandom()*-500.0f;
+	p.m_Color = vec4(0.75f,0.75f,0.75f,1.0f);
+	m_pClient->m_pParticles->Add(CParticles::GROUP_GENERAL, &p);	
 }
 
-void EFFECTS::bullettrail(vec2 pos)
+void CEffects::BulletTrail(vec2 Pos)
 {
-	if(!add_100hz)
+	if(!m_Add100hz)
 		return;
 		
-	PARTICLE p;
-	p.set_default();
-	p.spr = SPRITE_PART_BALL;
-	p.pos = pos;
-	p.life_span = 0.25f + frandom()*0.25f;
-	p.start_size = 8.0f;
-	p.end_size = 0;
-	p.friction = 0.7f;
-	gameclient.particles->add(PARTICLES::GROUP_PROJECTILE_TRAIL, &p);
+	CParticle p;
+	p.SetDefault();
+	p.m_Spr = SPRITE_PART_BALL;
+	p.m_Pos = Pos;
+	p.m_LifeSpan = 0.25f + frandom()*0.25f;
+	p.m_StartSize = 8.0f;
+	p.m_EndSize = 0;
+	p.m_Friction = 0.7f;
+	m_pClient->m_pParticles->Add(CParticles::GROUP_PROJECTILE_TRAIL, &p);
 }
 
-void EFFECTS::playerspawn(vec2 pos)
+void CEffects::PlayerSpawn(vec2 Pos)
 {
 	for(int i = 0; i < 32; i++)
 	{
-		PARTICLE p;
-		p.set_default();
-		p.spr = SPRITE_PART_SHELL;
-		p.pos = pos;
-		p.vel = random_dir() * (pow(frandom(), 3)*600.0f);
-		p.life_span = 0.3f + frandom()*0.3f;
-		p.start_size = 64.0f + frandom()*32;
-		p.end_size = 0;
-		p.rot = frandom()*pi*2;
-		p.rotspeed = frandom();
-		p.gravity = frandom()*-400.0f;
-		p.friction = 0.7f;
-		p.color = vec4(0xb5/255.0f, 0x50/255.0f, 0xcb/255.0f, 1.0f);
-		gameclient.particles->add(PARTICLES::GROUP_GENERAL, &p);
+		CParticle p;
+		p.SetDefault();
+		p.m_Spr = SPRITE_PART_SHELL;
+		p.m_Pos = Pos;
+		p.m_Vel = RandomDir() * (powf(frandom(), 3)*600.0f);
+		p.m_LifeSpan = 0.3f + frandom()*0.3f;
+		p.m_StartSize = 64.0f + frandom()*32;
+		p.m_EndSize = 0;
+		p.m_Rot = frandom()*pi*2;
+		p.m_Rotspeed = frandom();
+		p.m_Gravity = frandom()*-400.0f;
+		p.m_Friction = 0.7f;
+		p.m_Color = vec4(0xb5/255.0f, 0x50/255.0f, 0xcb/255.0f, 1.0f);
+		m_pClient->m_pParticles->Add(CParticles::GROUP_GENERAL, &p);
 		
 	}
-	gameclient.sounds->play(SOUNDS::CHN_WORLD, SOUND_PLAYER_SPAWN, 1.0f, pos);
+	m_pClient->m_pSounds->Play(CSounds::CHN_WORLD, SOUND_PLAYER_SPAWN, 1.0f, Pos);
 }
 
-void EFFECTS::playerdeath(vec2 pos, int cid)
+void CEffects::PlayerDeath(vec2 Pos, int Cid)
 {
-	vec3 blood_color(1.0f,1.0f,1.0f);
+	vec3 BloodColor(1.0f,1.0f,1.0f);
 
-	if(cid >= 0)	
+	if(Cid >= 0)	
 	{
-		const SKINS::SKIN *s = gameclient.skins->get(gameclient.clients[cid].skin_id);
+		const CSkins::CSkin *s = m_pClient->m_pSkins->Get(m_pClient->m_aClients[Cid].m_SkinId);
 		if(s)
-			blood_color = s->blood_color;
+			BloodColor = s->m_BloodColor;
 	}
 	
 	for(int i = 0; i < 64; i++)
 	{
-		PARTICLE p;
-		p.set_default();
-		p.spr = SPRITE_PART_SPLAT01 + (rand()%3);
-		p.pos = pos;
-		p.vel = random_dir() * ((frandom()+0.1f)*900.0f);
-		p.life_span = 0.3f + frandom()*0.3f;
-		p.start_size = 24.0f + frandom()*16;
-		p.end_size = 0;
-		p.rot = frandom()*pi*2;
-		p.rotspeed = (frandom()-0.5f) * pi;
-		p.gravity = 800.0f;
-		p.friction = 0.8f;
-		vec3 c = blood_color * (0.75f + frandom()*0.25f);
-		p.color = vec4(c.r, c.g, c.b, 0.75f);
-		gameclient.particles->add(PARTICLES::GROUP_GENERAL, &p);
+		CParticle p;
+		p.SetDefault();
+		p.m_Spr = SPRITE_PART_SPLAT01 + (rand()%3);
+		p.m_Pos = Pos;
+		p.m_Vel = RandomDir() * ((frandom()+0.1f)*900.0f);
+		p.m_LifeSpan = 0.3f + frandom()*0.3f;
+		p.m_StartSize = 24.0f + frandom()*16;
+		p.m_EndSize = 0;
+		p.m_Rot = frandom()*pi*2;
+		p.m_Rotspeed = (frandom()-0.5f) * pi;
+		p.m_Gravity = 800.0f;
+		p.m_Friction = 0.8f;
+		vec3 c = BloodColor * (0.75f + frandom()*0.25f);
+		p.m_Color = vec4(c.r, c.g, c.b, 0.75f);
+		m_pClient->m_pParticles->Add(CParticles::GROUP_GENERAL, &p);
 	}
 }
 
 
-void EFFECTS::explosion(vec2 pos)
+void CEffects::Explosion(vec2 Pos)
 {
 	// add to flow
 	for(int y = -8; y <= 8; y++)
@@ -187,75 +185,75 @@ void EFFECTS::explosion(vec2 pos)
 				continue;
 			
 			float a = 1 - (length(vec2(x,y)) / length(vec2(8,8)));
-			gameclient.flow->add(pos+vec2(x,y)*16, normalize(vec2(x,y))*5000.0f*a, 10.0f);
+			m_pClient->m_pFlow->Add(Pos+vec2(x,y)*16, normalize(vec2(x,y))*5000.0f*a, 10.0f);
 		}
 		
 	// add the explosion
-	PARTICLE p;
-	p.set_default();
-	p.spr = SPRITE_PART_EXPL01;
-	p.pos = pos;
-	p.life_span = 0.4f;
-	p.start_size = 150.0f;
-	p.end_size = 0;
-	p.rot = frandom()*pi*2;
-	gameclient.particles->add(PARTICLES::GROUP_EXPLOSIONS, &p);
+	CParticle p;
+	p.SetDefault();
+	p.m_Spr = SPRITE_PART_EXPL01;
+	p.m_Pos = Pos;
+	p.m_LifeSpan = 0.4f;
+	p.m_StartSize = 150.0f;
+	p.m_EndSize = 0;
+	p.m_Rot = frandom()*pi*2;
+	m_pClient->m_pParticles->Add(CParticles::GROUP_EXPLOSIONS, &p);
 	
 	// add the smoke
 	for(int i = 0; i < 24; i++)
 	{
-		PARTICLE p;
-		p.set_default();
-		p.spr = SPRITE_PART_SMOKE;
-		p.pos = pos;
-		p.vel = random_dir() * ((1.0f + frandom()*0.2f) * 1000.0f);
-		p.life_span = 0.5f + frandom()*0.4f;
-		p.start_size = 32.0f + frandom()*8;
-		p.end_size = 0;
-		p.gravity = frandom()*-800.0f;
-		p.friction = 0.4f;
-		p.color = mix(vec4(0.75f,0.75f,0.75f,1.0f), vec4(0.5f,0.5f,0.5f,1.0f), frandom());
-		gameclient.particles->add(PARTICLES::GROUP_GENERAL, &p);
+		CParticle p;
+		p.SetDefault();
+		p.m_Spr = SPRITE_PART_SMOKE;
+		p.m_Pos = Pos;
+		p.m_Vel = RandomDir() * ((1.0f + frandom()*0.2f) * 1000.0f);
+		p.m_LifeSpan = 0.5f + frandom()*0.4f;
+		p.m_StartSize = 32.0f + frandom()*8;
+		p.m_EndSize = 0;
+		p.m_Gravity = frandom()*-800.0f;
+		p.m_Friction = 0.4f;
+		p.m_Color = mix(vec4(0.75f,0.75f,0.75f,1.0f), vec4(0.5f,0.5f,0.5f,1.0f), frandom());
+		m_pClient->m_pParticles->Add(CParticles::GROUP_GENERAL, &p);
 	}
 }
 
 
-void EFFECTS::hammerhit(vec2 pos)
+void CEffects::HammerHit(vec2 Pos)
 {
 	// add the explosion
-	PARTICLE p;
-	p.set_default();
-	p.spr = SPRITE_PART_EXPL01;
-	p.pos = pos;
-	p.life_span = 0.4f;
-	p.start_size = 150.0f;
-	p.end_size = 0;
-	p.rot = frandom()*pi*2;
-	gameclient.particles->add(PARTICLES::GROUP_EXPLOSIONS, &p);	
-	gameclient.sounds->play(SOUNDS::CHN_WORLD, SOUND_HAMMER_HIT, 1.0f, pos);
+	CParticle p;
+	p.SetDefault();
+	p.m_Spr = SPRITE_PART_EXPL01;
+	p.m_Pos = Pos;
+	p.m_LifeSpan = 0.4f;
+	p.m_StartSize = 150.0f;
+	p.m_EndSize = 0;
+	p.m_Rot = frandom()*pi*2;
+	m_pClient->m_pParticles->Add(CParticles::GROUP_EXPLOSIONS, &p);	
+	m_pClient->m_pSounds->Play(CSounds::CHN_WORLD, SOUND_HAMMER_HIT, 1.0f, Pos);
 }
 
-void EFFECTS::on_render()
+void CEffects::OnRender()
 {
-	static int64 last_update_100hz = 0;
-	static int64 last_update_50hz = 0;
+	static int64 LastUpdate100hz = 0;
+	static int64 LastUpdate50hz = 0;
 
-	if(time_get()-last_update_100hz > time_freq()/100)
+	if(time_get()-LastUpdate100hz > time_freq()/100)
 	{
-		add_100hz = true;
-		last_update_100hz = time_get();
+		m_Add100hz = true;
+		LastUpdate100hz = time_get();
 	}
 	else
-		add_100hz = false;
+		m_Add100hz = false;
 
-	if(time_get()-last_update_50hz > time_freq()/100)
+	if(time_get()-LastUpdate50hz > time_freq()/100)
 	{
-		add_50hz = true;
-		last_update_50hz = time_get();
+		m_Add50hz = true;
+		LastUpdate50hz = time_get();
 	}
 	else
-		add_50hz = false;
+		m_Add50hz = false;
 		
-	if(add_50hz)
-		gameclient.flow->update();
+	if(m_Add50hz)
+		m_pClient->m_pFlow->Update();
 }
diff --git a/src/game/client/components/effects.h b/src/game/client/components/effects.h
new file mode 100644
index 00000000..e8345500
--- /dev/null
+++ b/src/game/client/components/effects.h
@@ -0,0 +1,27 @@
+#ifndef GAME_CLIENT_COMPONENTS_EFFECTS_H
+#define GAME_CLIENT_COMPONENTS_EFFECTS_H
+#include <game/client/component.h>
+
+class CEffects : public CComponent
+{	
+	bool m_Add50hz;
+	bool m_Add100hz;
+public:
+	CEffects();
+
+	virtual void OnRender();
+
+	void BulletTrail(vec2 Pos);
+	void SmokeTrail(vec2 Pos, vec2 Vel);
+	void SkidTrail(vec2 Pos, vec2 Vel);
+	void Explosion(vec2 Pos);
+	void HammerHit(vec2 Pos);
+	void AirJump(vec2 Pos);
+	void DamageIndicator(vec2 Pos, vec2 Dir);
+	void PlayerSpawn(vec2 Pos);
+	void PlayerDeath(vec2 Pos, int ClientId);
+	void PowerupShine(vec2 Pos, vec2 Size);
+
+	void Update();
+};
+#endif
diff --git a/src/game/client/components/effects.hpp b/src/game/client/components/effects.hpp
deleted file mode 100644
index 8574bf60..00000000
--- a/src/game/client/components/effects.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include <game/client/component.hpp>
-
-class EFFECTS : public COMPONENT
-{	
-	bool add_50hz;
-	bool add_100hz;
-public:
-	EFFECTS();
-
-	virtual void on_render();
-
-	void bullettrail(vec2 pos);
-	void smoketrail(vec2 pos, vec2 vel);
-	void skidtrail(vec2 pos, vec2 vel);
-	void explosion(vec2 pos);
-	void hammerhit(vec2 pos);
-	void air_jump(vec2 pos);
-	void damage_indicator(vec2 pos, vec2 dir);
-	void playerspawn(vec2 pos);
-	void playerdeath(vec2 pos, int cid);
-	void powerupshine(vec2 pos, vec2 size);
-
-	void update();
-};
diff --git a/src/game/client/components/emoticon.cpp b/src/game/client/components/emoticon.cpp
index 8001a306..6d03f88d 100644
--- a/src/game/client/components/emoticon.cpp
+++ b/src/game/client/components/emoticon.cpp
@@ -1,157 +1,161 @@
-#include <engine/e_client_interface.h>
-#include <engine/client/graphics.h>
-#include <game/generated/g_protocol.hpp>
-#include <game/generated/gc_data.hpp>
-
-#include <game/gamecore.hpp> // get_angle
-#include <game/client/gameclient.hpp>
-#include <game/client/ui.hpp>
-#include <game/client/render.hpp>
-#include "emoticon.hpp"
-
-EMOTICON::EMOTICON()
+#include <engine/graphics.h>
+#include <engine/shared/config.h>
+#include <game/generated/protocol.h>
+#include <game/generated/client_data.h>
+
+#include <game/gamecore.h> // get_angle
+#include <game/client/gameclient.h>
+#include <game/client/ui.h>
+#include <game/client/render.h>
+#include "emoticon.h"
+
+CEmoticon::CEmoticon()
 {
-	on_reset();
+	OnReset();
 }
 
-void EMOTICON::con_key_emoticon(void *result, void *user_data)
+void CEmoticon::ConKeyEmoticon(IConsole::IResult *pResult, void *pUserData)
 {
-	((EMOTICON *)user_data)->active = console_arg_int(result, 0) != 0;
+	((CEmoticon *)pUserData)->m_Active = pResult->GetInteger(0) != 0;
 }
 
-void EMOTICON::con_emote(void *result, void *user_data)
+void CEmoticon::ConEmote(IConsole::IResult *pResult, void *pUserData)
 {
-	((EMOTICON *)user_data)->emote(console_arg_int(result, 0));
+	((CEmoticon *)pUserData)->Emote(pResult->GetInteger(0));
 }
 
-void EMOTICON::on_console_init()
+void CEmoticon::OnConsoleInit()
 {
-	MACRO_REGISTER_COMMAND("+emote", "", CFGFLAG_CLIENT, con_key_emoticon, this, "Open emote selector");
-	MACRO_REGISTER_COMMAND("emote", "i", CFGFLAG_CLIENT, con_emote, this, "Use emote");
+	Console()->Register("+emote", "", CFGFLAG_CLIENT, ConKeyEmoticon, this, "Open emote selector");
+	Console()->Register("emote", "i", CFGFLAG_CLIENT, ConEmote, this, "Use emote");
 }
 
-void EMOTICON::on_reset()
+void CEmoticon::OnReset()
 {
-	was_active = false;
-	active = false;
-	selected_emote = -1;
+	m_WasActive = false;
+	m_Active = false;
+	m_SelectedEmote = -1;
 }
 
-void EMOTICON::on_message(int msgtype, void *rawmsg)
+void CEmoticon::OnMessage(int MsgType, void *pRawMsg)
 {
-	if(msgtype == NETMSGTYPE_SV_EMOTICON)
-	{
-		NETMSG_SV_EMOTICON *msg = (NETMSG_SV_EMOTICON *)rawmsg;
-		gameclient.clients[msg->cid].emoticon = msg->emoticon;
-		gameclient.clients[msg->cid].emoticon_start = client_tick();
-	}	
 }
 
-bool EMOTICON::on_mousemove(float x, float y)
+bool CEmoticon::OnMouseMove(float x, float y)
 {
-	if(!active)
+	if(!m_Active)
 		return false;
 	
-	selector_mouse += vec2(x,y);
+	m_SelectorMouse += vec2(x,y);
 	return true;
 }
 
-void EMOTICON::draw_circle(float x, float y, float r, int segments)
+void CEmoticon::DrawCircle(float x, float y, float r, int Segments)
 {
-	float f_segments = (float)segments;
-	for(int i = 0; i < segments; i+=2)
+	IGraphics::CFreeformItem Array[32];
+	int NumItems = 0;
+	float FSegments = (float)Segments;
+	for(int i = 0; i < Segments; i+=2)
 	{
-		float a1 = i/f_segments * 2*pi;
-		float a2 = (i+1)/f_segments * 2*pi;
-		float a3 = (i+2)/f_segments * 2*pi;
-		float ca1 = cosf(a1);
-		float ca2 = cosf(a2);
-		float ca3 = cosf(a3);
-		float sa1 = sinf(a1);
-		float sa2 = sinf(a2);
-		float sa3 = sinf(a3);
-
-		client->Graphics()->QuadsDrawFreeform(
+		float a1 = i/FSegments * 2*pi;
+		float a2 = (i+1)/FSegments * 2*pi;
+		float a3 = (i+2)/FSegments * 2*pi;
+		float Ca1 = cosf(a1);
+		float Ca2 = cosf(a2);
+		float Ca3 = cosf(a3);
+		float Sa1 = sinf(a1);
+		float Sa2 = sinf(a2);
+		float Sa3 = sinf(a3);
+
+		Array[NumItems++] = IGraphics::CFreeformItem(
 			x, y,
-			x+ca1*r, y+sa1*r,
-			x+ca3*r, y+sa3*r,
-			x+ca2*r, y+sa2*r);
+			x+Ca1*r, y+Sa1*r,
+			x+Ca3*r, y+Sa3*r,
+			x+Ca2*r, y+Sa2*r);
+		if(NumItems == 32)
+		{
+			m_pClient->Graphics()->QuadsDrawFreeform(Array, 32);
+			NumItems = 0;
+		}
 	}
+	if(NumItems)
+		m_pClient->Graphics()->QuadsDrawFreeform(Array, NumItems);
 }
 
 	
-void EMOTICON::on_render()
+void CEmoticon::OnRender()
 {
-	if(!active)
+	if(!m_Active)
 	{
-		if(was_active && selected_emote != -1)
-			emote(selected_emote);
-		was_active = false;
+		if(m_WasActive && m_SelectedEmote != -1)
+			Emote(m_SelectedEmote);
+		m_WasActive = false;
 		return;
 	}
 	
-	was_active = true;
+	m_WasActive = true;
 	
 	int x, y;
-	inp_mouse_relative(&x, &y);
+	Input()->MouseRelative(&x, &y);
 
-	selector_mouse.x += x;
-	selector_mouse.y += y;
+	m_SelectorMouse.x += x;
+	m_SelectorMouse.y += y;
 
-	if (length(selector_mouse) > 140)
-		selector_mouse = normalize(selector_mouse) * 140;
+	if (length(m_SelectorMouse) > 140)
+		m_SelectorMouse = normalize(m_SelectorMouse) * 140;
 
-	float selected_angle = get_angle(selector_mouse) + 2*pi/24;
-	if (selected_angle < 0)
-		selected_angle += 2*pi;
+	float SelectedAngle = GetAngle(m_SelectorMouse) + 2*pi/24;
+	if (SelectedAngle < 0)
+		SelectedAngle += 2*pi;
 
-	if (length(selector_mouse) > 100)
-		selected_emote = (int)(selected_angle / (2*pi) * 12.0f);
+	if (length(m_SelectorMouse) > 100)
+		m_SelectedEmote = (int)(SelectedAngle / (2*pi) * 12.0f);
 
-    CUIRect screen = *UI()->Screen();
+    CUIRect Screen = *UI()->Screen();
 
-	Graphics()->MapScreen(screen.x, screen.y, screen.w, screen.h);
+	Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);
 
 	Graphics()->BlendNormal();
 
 	Graphics()->TextureSet(-1);
 	Graphics()->QuadsBegin();
 	Graphics()->SetColor(0,0,0,0.3f);
-	draw_circle(screen.w/2, screen.h/2, 160, 64);
+	DrawCircle(Screen.w/2, Screen.h/2, 160, 64);
 	Graphics()->QuadsEnd();
 
-	Graphics()->TextureSet(data->images[IMAGE_EMOTICONS].id);
+	Graphics()->TextureSet(g_pData->m_aImages[IMAGE_EMOTICONS].m_Id);
 	Graphics()->QuadsBegin();
 
 	for (int i = 0; i < 12; i++)
 	{
-		float angle = 2*pi*i/12.0;
-		if (angle > pi)
-			angle -= 2*pi;
+		float Angle = 2*pi*i/12.0;
+		if (Angle > pi)
+			Angle -= 2*pi;
 
-		bool selected = selected_emote == i;
+		bool Selected = m_SelectedEmote == i;
 
-		float size = selected ? 96 : 64;
+		float Size = Selected ? 96 : 64;
 
-		float nudge_x = 120 * cos(angle);
-		float nudge_y = 120 * sin(angle);
-		RenderTools()->select_sprite(SPRITE_OOP + i);
-		Graphics()->QuadsDraw(screen.w/2 + nudge_x, screen.h/2 + nudge_y, size, size);
+		float NudgeX = 120 * cosf(Angle);
+		float NudgeY = 120 * sinf(Angle);
+		RenderTools()->SelectSprite(SPRITE_OOP + i);
+		IGraphics::CQuadItem QuadItem(Screen.w/2 + NudgeX, Screen.h/2 + NudgeY, Size, Size);
+		Graphics()->QuadsDraw(&QuadItem, 1);
 	}
 
 	Graphics()->QuadsEnd();
 
-    Graphics()->TextureSet(data->images[IMAGE_CURSOR].id);
+    Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CURSOR].m_Id);
     Graphics()->QuadsBegin();
     Graphics()->SetColor(1,1,1,1);
-    Graphics()->QuadsDrawTL(selector_mouse.x+screen.w/2,selector_mouse.y+screen.h/2,24,24);
+	IGraphics::CQuadItem QuadItem(m_SelectorMouse.x+Screen.w/2,m_SelectorMouse.y+Screen.h/2,24,24);
+	Graphics()->QuadsDrawTL(&QuadItem, 1);
     Graphics()->QuadsEnd();
 }
 
-void EMOTICON::emote(int emoticon)
+void CEmoticon::Emote(int Emoticon)
 {
-	NETMSG_CL_EMOTICON msg;
-	msg.emoticon = emoticon;
-	msg.pack(MSGFLAG_VITAL);
-	client_send_msg();
+	CNetMsg_Cl_Emoticon Msg;
+	Msg.m_Emoticon = Emoticon;
+	Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
 }
diff --git a/src/game/client/components/emoticon.h b/src/game/client/components/emoticon.h
new file mode 100644
index 00000000..e10b57da
--- /dev/null
+++ b/src/game/client/components/emoticon.h
@@ -0,0 +1,31 @@
+#ifndef GAME_CLIENT_COMPONENTS_EMOTICON_H
+#define GAME_CLIENT_COMPONENTS_EMOTICON_H
+#include <base/vmath.h>
+#include <game/client/component.h>
+
+class CEmoticon : public CComponent
+{
+	void DrawCircle(float x, float y, float r, int Segments);
+	
+	bool m_WasActive;
+	bool m_Active;
+	
+	vec2 m_SelectorMouse;
+	int m_SelectedEmote;
+
+	static void ConKeyEmoticon(IConsole::IResult *pResult, void *pUserData);
+	static void ConEmote(IConsole::IResult *pResult, void *pUserData);
+	
+public:
+	CEmoticon();
+	
+	virtual void OnReset();
+	virtual void OnConsoleInit();
+	virtual void OnRender();
+	virtual void OnMessage(int MsgType, void *pRawMsg);
+	virtual bool OnMouseMove(float x, float y);
+
+	void Emote(int Emoticon);
+};
+
+#endif
diff --git a/src/game/client/components/emoticon.hpp b/src/game/client/components/emoticon.hpp
deleted file mode 100644
index 446b4b00..00000000
--- a/src/game/client/components/emoticon.hpp
+++ /dev/null
@@ -1,28 +0,0 @@
-#include <base/vmath.hpp>
-#include <game/client/component.hpp>
-
-class EMOTICON : public COMPONENT
-{
-	void draw_circle(float x, float y, float r, int segments);
-	
-	bool was_active;
-	bool active;
-	
-	vec2 selector_mouse;
-	int selected_emote;
-
-	static void con_key_emoticon(void *result, void *user_data);
-	static void con_emote(void *result, void *user_data);
-	
-public:
-	EMOTICON();
-	
-	virtual void on_reset();
-	virtual void on_console_init();
-	virtual void on_render();
-	virtual void on_message(int msgtype, void *rawmsg);
-	virtual bool on_mousemove(float x, float y);
-
-	void emote(int emoticon);
-};
-
diff --git a/src/game/client/components/flow.cpp b/src/game/client/components/flow.cpp
index 9ecd4b5c..d2ba704c 100644
--- a/src/game/client/components/flow.cpp
+++ b/src/game/client/components/flow.cpp
@@ -1,85 +1,94 @@
-#include <engine/client/graphics.h>
-#include <game/mapitems.hpp>
-#include <game/layers.hpp>
-#include "flow.hpp"
+#include <engine/graphics.h>
+#include <game/mapitems.h>
+#include <game/layers.h>
+#include "flow.h"
 
-FLOW::FLOW()
+CFlow::CFlow()
 {
-	cells = 0;
-	height = 0;
-	width = 0;
-	spacing = 16;
+	m_pCells = 0;
+	m_Height = 0;
+	m_Width = 0;
+	m_Spacing = 16;
 }
 	
-void FLOW::dbg_render()
+void CFlow::DbgRender()
 {
-	if(!cells)
+	if(!m_pCells)
 		return;
 
+	IGraphics::CLineItem Array[1024];
+	int NumItems = 0;
 	Graphics()->TextureSet(-1);
 	Graphics()->LinesBegin();
-	for(int y = 0; y < height; y++)
-		for(int x = 0; x < width; x++)
+	for(int y = 0; y < m_Height; y++)
+		for(int x = 0; x < m_Width; x++)
 		{
-			vec2 pos(x*spacing, y*spacing);
-			vec2 vel = cells[y*width+x].vel * 0.01f;
-			Graphics()->LinesDraw(pos.x, pos.y, pos.x+vel.x, pos.y+vel.y);
+			vec2 Pos(x*m_Spacing, y*m_Spacing);
+			vec2 Vel = m_pCells[y*m_Width+x].m_Vel * 0.01f;
+			Array[NumItems++] = IGraphics::CLineItem(Pos.x, Pos.y, Pos.x+Vel.x, Pos.y+Vel.y);
+			if(NumItems == 1024)
+			{
+				Graphics()->LinesDraw(Array, 1024);
+				NumItems = 0;
+			}
 		}
-		
+	
+	if(NumItems)
+		Graphics()->LinesDraw(Array, NumItems);
 	Graphics()->LinesEnd();
 }
 
-void FLOW::init()
+void CFlow::Init()
 {
-	if(cells)
+	if(m_pCells)
 	{
-		mem_free(cells);
-		cells = 0;
+		mem_free(m_pCells);
+		m_pCells = 0;
 	}
 	
-	MAPITEM_LAYER_TILEMAP *tilemap = layers_game_layer();
-	width = tilemap->width*32/spacing;
-	height = tilemap->height*32/spacing;
+	CMapItemLayerTilemap *pTilemap = Layers()->GameLayer();
+	m_Width = pTilemap->m_Width*32/m_Spacing;
+	m_Height = pTilemap->m_Height*32/m_Spacing;
 
 	// allocate and clear	
-	cells = (CELL *)mem_alloc(sizeof(CELL)*width*height, 1);
-	for(int y = 0; y < height; y++)
-		for(int x = 0; x < width; x++)
-			cells[y*width+x].vel = vec2(0.0f, 0.0f);
+	m_pCells = (CCell *)mem_alloc(sizeof(CCell)*m_Width*m_Height, 1);
+	for(int y = 0; y < m_Height; y++)
+		for(int x = 0; x < m_Width; x++)
+			m_pCells[y*m_Width+x].m_Vel = vec2(0.0f, 0.0f);
 }
 
-void FLOW::update()
+void CFlow::Update()
 {
-	if(!cells)
+	if(!m_pCells)
 		return;
 		
-	for(int y = 0; y < height; y++)
-		for(int x = 0; x < width; x++)
-			cells[y*width+x].vel *= 0.85f;
+	for(int y = 0; y < m_Height; y++)
+		for(int x = 0; x < m_Width; x++)
+			m_pCells[y*m_Width+x].m_Vel *= 0.85f;
 }
 
-vec2 FLOW::get(vec2 pos)
+vec2 CFlow::Get(vec2 Pos)
 {
-	if(!cells)
+	if(!m_pCells)
 		return vec2(0,0);
 	
-	int x = (int)(pos.x / spacing);
-	int y = (int)(pos.y / spacing);
-	if(x < 0 || y < 0 || x >= width || y >= height)
+	int x = (int)(Pos.x / m_Spacing);
+	int y = (int)(Pos.y / m_Spacing);
+	if(x < 0 || y < 0 || x >= m_Width || y >= m_Height)
 		return vec2(0,0);
 	
-	return cells[y*width+x].vel;	
+	return m_pCells[y*m_Width+x].m_Vel;	
 }
 
-void FLOW::add(vec2 pos, vec2 vel, float size)
+void CFlow::Add(vec2 Pos, vec2 Vel, float Size)
 {
-	if(!cells)
+	if(!m_pCells)
 		return;
 		
-	int x = (int)(pos.x / spacing);
-	int y = (int)(pos.y / spacing);
-	if(x < 0 || y < 0 || x >= width || y >= height)
+	int x = (int)(Pos.x / m_Spacing);
+	int y = (int)(Pos.y / m_Spacing);
+	if(x < 0 || y < 0 || x >= m_Width || y >= m_Height)
 		return;
 	
-	cells[y*width+x].vel += vel;
+	m_pCells[y*m_Width+x].m_Vel += Vel;
 }
diff --git a/src/game/client/components/flow.h b/src/game/client/components/flow.h
new file mode 100644
index 00000000..e8134797
--- /dev/null
+++ b/src/game/client/components/flow.h
@@ -0,0 +1,28 @@
+#ifndef GAME_CLIENT_COMPONENTS_FLOW_H
+#define GAME_CLIENT_COMPONENTS_FLOW_H
+#include <base/vmath.h>
+#include <game/client/component.h>
+
+class CFlow : public CComponent
+{
+	struct CCell
+	{
+		vec2 m_Vel;
+	};
+
+	CCell *m_pCells;
+	int m_Height;
+	int m_Width;
+	int m_Spacing;
+	
+	void DbgRender();
+	void Init();
+public:
+	CFlow();
+	
+	vec2 Get(vec2 Pos);
+	void Add(vec2 Pos, vec2 Vel, float Size);
+	void Update();
+};
+
+#endif
diff --git a/src/game/client/components/flow.hpp b/src/game/client/components/flow.hpp
deleted file mode 100644
index 351b1f69..00000000
--- a/src/game/client/components/flow.hpp
+++ /dev/null
@@ -1,25 +0,0 @@
-#include <base/vmath.hpp>
-#include <game/client/component.hpp>
-
-class FLOW : public COMPONENT
-{
-	struct CELL
-	{
-		vec2 vel;
-	};
-
-	CELL *cells;
-	int height;
-	int width;
-	int spacing;
-	
-	void dbg_render();
-	void init();
-public:
-	FLOW();
-	
-	vec2 get(vec2 pos);
-	void add(vec2 pos, vec2 vel, float size);
-	void update();
-};
-
diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp
index 837322fb..f4a24384 100644
--- a/src/game/client/components/hud.cpp
+++ b/src/game/client/components/hud.cpp
@@ -1,32 +1,31 @@
-#include <memory.h> // memcmp
-
-#include <engine/e_client_interface.h>
-#include <engine/client/graphics.h>
-#include <game/generated/g_protocol.hpp>
-#include <game/generated/gc_data.hpp>
-
-#include <game/layers.hpp>
-
-#include <game/client/gameclient.hpp>
-#include <game/client/animstate.hpp>
-#include <game/client/render.hpp>
-
-#include "controls.hpp"
-#include "camera.hpp"
-#include "hud.hpp"
-#include "voting.hpp"
-#include "binds.hpp"
-
-HUD::HUD()
+#include <engine/graphics.h>
+#include <engine/textrender.h>
+#include <engine/shared/config.h>
+
+#include <game/generated/protocol.h>
+#include <game/generated/client_data.h>
+#include <game/layers.h>
+#include <game/client/gameclient.h>
+#include <game/client/animstate.h>
+#include <game/client/render.h>
+
+#include "controls.h"
+#include "camera.h"
+#include "hud.h"
+#include "voting.h"
+#include "binds.h"
+
+CHud::CHud()
 {
-	
+	// won't work if zero
+	m_AverageFPS = 1.0f;
 }
 	
-void HUD::on_reset()
+void CHud::OnReset()
 {
 }
 
-void HUD::render_goals()
+void CHud::RenderGoals()
 {
 	// TODO: split this up into these:
 	// render_gametimer
@@ -34,41 +33,41 @@ void HUD::render_goals()
 	// render_scorehud
 	// render_warmuptimer
 	
-	int gameflags = gameclient.snap.gameobj->flags;
+	int GameFlags = m_pClient->m_Snap.m_pGameobj->m_Flags;
 	
-	float whole = 300*Graphics()->ScreenAspect();
-	float half = whole/2.0f;
+	float Whole = 300*Graphics()->ScreenAspect();
+	float Half = Whole/2.0f;
 
 
 	Graphics()->MapScreen(0,0,300*Graphics()->ScreenAspect(),300);
-	if(!gameclient.snap.gameobj->sudden_death)
+	if(!m_pClient->m_Snap.m_pGameobj->m_SuddenDeath)
 	{
-		char buf[32];
-		int time = 0;
-		if(gameclient.snap.gameobj->time_limit)
+		char Buf[32];
+		int Time = 0;
+		if(m_pClient->m_Snap.m_pGameobj->m_TimeLimit)
 		{
-			time = gameclient.snap.gameobj->time_limit*60 - ((client_tick()-gameclient.snap.gameobj->round_start_tick)/client_tickspeed());
+			Time = m_pClient->m_Snap.m_pGameobj->m_TimeLimit*60 - ((Client()->GameTick()-m_pClient->m_Snap.m_pGameobj->m_RoundStartTick)/Client()->GameTickSpeed());
 
-			if(gameclient.snap.gameobj->game_over)
-				time  = 0;
+			if(m_pClient->m_Snap.m_pGameobj->m_GameOver)
+				Time  = 0;
 		}
 		else
-			time = (client_tick()-gameclient.snap.gameobj->round_start_tick)/client_tickspeed();
+			Time = (Client()->GameTick()-m_pClient->m_Snap.m_pGameobj->m_RoundStartTick)/Client()->GameTickSpeed();
 
-		str_format(buf, sizeof(buf), "%d:%02d", time /60, time %60);
-		float w = gfx_text_width(0, 16, buf, -1);
-		gfx_text(0, half-w/2, 2, 16, buf, -1);
+		str_format(Buf, sizeof(Buf), "%d:%02d", Time /60, Time %60);
+		float w = TextRender()->TextWidth(0, 16, Buf, -1);
+		TextRender()->Text(0, Half-w/2, 2, 16, Buf, -1);
 	}
 
-	if(gameclient.snap.gameobj->sudden_death)
+	if(m_pClient->m_Snap.m_pGameobj->m_SuddenDeath)
 	{
-		const char *text = "Sudden Death";
-		float w = gfx_text_width(0, 16, text, -1);
-		gfx_text(0, half-w/2, 2, 16, text, -1);
+		const char *pText = "Sudden Death";
+		float w = TextRender()->TextWidth(0, 16, pText, -1);
+		TextRender()->Text(0, Half-w/2, 2, 16, pText, -1);
 	}
 
 	// render small score hud
-	if(!(gameclient.snap.gameobj && gameclient.snap.gameobj->game_over) && (gameflags&GAMEFLAG_TEAMS))
+	if(!(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver) && (GameFlags&GAMEFLAG_TEAMS))
 	{
 		for(int t = 0; t < 2; t++)
 		{
@@ -79,166 +78,171 @@ void HUD::render_goals()
 				Graphics()->SetColor(1,0,0,0.25f);
 			else
 				Graphics()->SetColor(0,0,1,0.25f);
-			RenderTools()->draw_round_rect(whole-40, 300-40-15+t*20, 50, 18, 5.0f);
+			RenderTools()->DrawRoundRect(Whole-45, 300-40-15+t*20, 50, 18, 5.0f);
 			Graphics()->QuadsEnd();
 
-			char buf[32];
-			str_format(buf, sizeof(buf), "%d", t?gameclient.snap.gameobj->teamscore_blue:gameclient.snap.gameobj->teamscore_red);
-			float w = gfx_text_width(0, 14, buf, -1);
+			char Buf[32];
+			str_format(Buf, sizeof(Buf), "%d", t?m_pClient->m_Snap.m_pGameobj->m_TeamscoreBlue : m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed);
+			float w = TextRender()->TextWidth(0, 14, Buf, -1);
 			
-			if(gameflags&GAMEFLAG_FLAGS)
+			if(GameFlags&GAMEFLAG_FLAGS)
 			{
-				gfx_text(0, whole-20-w/2+5, 300-40-15+t*20, 14, buf, -1);
-				if(gameclient.snap.flags[t])
+				TextRender()->Text(0, Whole-20-w/2+5, 300-40-15+t*20, 14, Buf, -1);
+				if(m_pClient->m_Snap.m_paFlags[t])
 				{
-					if(gameclient.snap.flags[t]->carried_by == -2 || (gameclient.snap.flags[t]->carried_by == -1 && ((client_tick()/10)&1)))
+					if(m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy == -2 || (m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy == -1 && ((Client()->GameTick()/10)&1)))
 					{
 						Graphics()->BlendNormal();
-						Graphics()->TextureSet(data->images[IMAGE_GAME].id);
+						Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
 						Graphics()->QuadsBegin();
 
-						if(t == 0) RenderTools()->select_sprite(SPRITE_FLAG_RED);
-						else RenderTools()->select_sprite(SPRITE_FLAG_BLUE);
+						if(t == 0) RenderTools()->SelectSprite(SPRITE_FLAG_RED);
+						else RenderTools()->SelectSprite(SPRITE_FLAG_BLUE);
 						
-						float size = 16;					
-						Graphics()->QuadsDrawTL(whole-40+5, 300-40-15+t*20+1, size/2, size);
+						float Size = 16;					
+						IGraphics::CQuadItem QuadItem(Whole-40+2, 300-40-15+t*20+1, Size/2, Size);
+						Graphics()->QuadsDrawTL(&QuadItem, 1);
 						Graphics()->QuadsEnd();
 					}
-					else if(gameclient.snap.flags[t]->carried_by >= 0)
+					else if(m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy >= 0)
 					{
-						int id = gameclient.snap.flags[t]->carried_by%MAX_CLIENTS;
-						const char *name = gameclient.clients[id].name;
-						float w = gfx_text_width(0, 10, name, -1);
-						gfx_text(0, whole-40-5-w, 300-40-15+t*20+2, 10, name, -1);
-						TEE_RENDER_INFO info = gameclient.clients[id].render_info;
-						info.size = 18.0f;
+						int Id = m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy%MAX_CLIENTS;
+						const char *pName = m_pClient->m_aClients[Id].m_aName;
+						float w = TextRender()->TextWidth(0, 10, pName, -1);
+						TextRender()->Text(0, Whole-40-7-w, 300-40-15+t*20+2, 10, pName, -1);
+						CTeeRenderInfo Info = m_pClient->m_aClients[Id].m_RenderInfo;
+						Info.m_Size = 18.0f;
 						
-						RenderTools()->RenderTee(ANIMSTATE::get_idle(), &info, EMOTE_NORMAL, vec2(1,0),
-							vec2(whole-40+10, 300-40-15+9+t*20+1));
+						RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1,0),
+							vec2(Whole-40+5, 300-40-15+9+t*20+1));
 					}
 				}
 			}
 			else
-				gfx_text(0, whole-20-w/2, 300-40-15+t*20, 14, buf, -1);
+				TextRender()->Text(0, Whole-20-w/2, 300-40-15+t*20, 14, Buf, -1);
 		}
 	}
 
 	// render warmup timer
-	if(gameclient.snap.gameobj->warmup)
+	if(m_pClient->m_Snap.m_pGameobj->m_Warmup)
 	{
-		char buf[256];
-		float w = gfx_text_width(0, 24, "Warmup", -1);
-		gfx_text(0, 150*Graphics()->ScreenAspect()+-w/2, 50, 24, "Warmup", -1);
+		char Buf[256];
+		float w = TextRender()->TextWidth(0, 24, "Warmup", -1);
+		TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 50, 24, "Warmup", -1);
 
-		int seconds = gameclient.snap.gameobj->warmup/SERVER_TICK_SPEED;
-		if(seconds < 5)
-			str_format(buf, sizeof(buf), "%d.%d", seconds, (gameclient.snap.gameobj->warmup*10/SERVER_TICK_SPEED)%10);
+		int Seconds = m_pClient->m_Snap.m_pGameobj->m_Warmup/SERVER_TICK_SPEED;
+		if(Seconds < 5)
+			str_format(Buf, sizeof(Buf), "%d.%d", Seconds, (m_pClient->m_Snap.m_pGameobj->m_Warmup*10/SERVER_TICK_SPEED)%10);
 		else
-			str_format(buf, sizeof(buf), "%d", seconds);
-		w = gfx_text_width(0, 24, buf, -1);
-		gfx_text(0, 150*Graphics()->ScreenAspect()+-w/2, 75, 24, buf, -1);
+			str_format(Buf, sizeof(Buf), "%d", Seconds);
+		w = TextRender()->TextWidth(0, 24, Buf, -1);
+		TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 75, 24, Buf, -1);
 	}	
 }
 
-void HUD::mapscreen_to_group(float center_x, float center_y, MAPITEM_GROUP *group)
+void CHud::MapscreenToGroup(float CenterX, float CenterY, CMapItemGroup *pGroup)
 {
-	float points[4];
-	RenderTools()->mapscreen_to_world(center_x, center_y, group->parallax_x/100.0f, group->parallax_y/100.0f,
-		group->offset_x, group->offset_y, Graphics()->ScreenAspect(), 1.0f, points);
-	Graphics()->MapScreen(points[0], points[1], points[2], points[3]);
+	float Points[4];
+	RenderTools()->MapscreenToWorld(CenterX, CenterY, pGroup->m_ParallaxX/100.0f, pGroup->m_ParallaxY/100.0f,
+		pGroup->m_OffsetX, pGroup->m_OffsetY, Graphics()->ScreenAspect(), 1.0f, Points);
+	Graphics()->MapScreen(Points[0], Points[1], Points[2], Points[3]);
 }
 
-void HUD::render_fps()
+void CHud::RenderFps()
 {
-	if(config.cl_showfps)
+	if(g_Config.m_ClShowfps)
 	{
-		char buf[512];
-		str_format(buf, sizeof(buf), "%d", (int)(1.0f/client_frametime()));
-		gfx_text(0, width-10-gfx_text_width(0,12,buf,-1), 5, 12, buf, -1);
+		// calculate avg. fps
+		float FPS = 1.0f / Client()->FrameTime();
+		m_AverageFPS = (m_AverageFPS*(1.0f-(1.0f/m_AverageFPS))) + (FPS*(1.0f/m_AverageFPS));
+		char Buf[512];
+		str_format(Buf, sizeof(Buf), "%d", (int)m_AverageFPS);
+		TextRender()->Text(0, m_Width-10-TextRender()->TextWidth(0,12,Buf,-1), 5, 12, Buf, -1);
 	}
 }
 
-void HUD::render_connectionwarning()
+void CHud::RenderConnectionWarning()
 {
-	if(client_connection_problems())
+	if(Client()->ConnectionProblems())
 	{
-		const char *text = "Connection Problems...";
-		float w = gfx_text_width(0, 24, text, -1);
-		gfx_text(0, 150*Graphics()->ScreenAspect()-w/2, 50, 24, text, -1);
+		const char *pText = "Connection Problems...";
+		float w = TextRender()->TextWidth(0, 24, pText, -1);
+		TextRender()->Text(0, 150*Graphics()->ScreenAspect()-w/2, 50, 24, pText, -1);
 	}
 }
 
-void HUD::render_teambalancewarning()
+void CHud::RenderTeambalanceWarning()
 {
 	// render prompt about team-balance
-	bool flash = time_get()/(time_freq()/2)%2 == 0;
-	if (gameclient.snap.gameobj && (gameclient.snap.gameobj->flags&GAMEFLAG_TEAMS) != 0)
+	bool Flash = time_get()/(time_freq()/2)%2 == 0;
+	if (m_pClient->m_Snap.m_pGameobj && (m_pClient->m_Snap.m_pGameobj->m_Flags&GAMEFLAG_TEAMS) != 0)
 	{	
-		if (config.cl_warning_teambalance && abs(gameclient.snap.team_size[0]-gameclient.snap.team_size[1]) >= 2)
+		int TeamDiff = m_pClient->m_Snap.m_aTeamSize[0]-m_pClient->m_Snap.m_aTeamSize[1];
+		if (g_Config.m_ClWarningTeambalance && (TeamDiff >= 2 || TeamDiff <= -2))
 		{
-			const char *text = "Please balance teams!";
-			if(flash)
-				gfx_text_color(1,1,0.5f,1);
+			const char *pText = "Please balance teams!";
+			if(Flash)
+				TextRender()->TextColor(1,1,0.5f,1);
 			else
-				gfx_text_color(0.7f,0.7f,0.2f,1.0f);
-			gfx_text(0x0, 5, 50, 6, text, -1);
-			gfx_text_color(1,1,1,1);
+				TextRender()->TextColor(0.7f,0.7f,0.2f,1.0f);
+			TextRender()->Text(0x0, 5, 50, 6, pText, -1);
+			TextRender()->TextColor(1,1,1,1);
 		}
 	}
 }
 
 
-void HUD::render_voting()
+void CHud::RenderVoting()
 {
-	if(!gameclient.voting->is_voting())
+	if(!m_pClient->m_pVoting->IsVoting())
 		return;
 	
 	Graphics()->TextureSet(-1);
 	Graphics()->QuadsBegin();
 	Graphics()->SetColor(0,0,0,0.40f);
-	RenderTools()->draw_round_rect(-10, 60-2, 100+10+4+5, 28, 5.0f);
+	RenderTools()->DrawRoundRect(-10, 60-2, 100+10+4+5, 28, 5.0f);
 	Graphics()->QuadsEnd();
 
-	gfx_text_color(1,1,1,1);
+	TextRender()->TextColor(1,1,1,1);
 
-	char buf[512];
-	gfx_text(0x0, 5, 60, 6, gameclient.voting->vote_description(), -1);
+	char Buf[512];
+	TextRender()->Text(0x0, 5, 60, 6, m_pClient->m_pVoting->VoteDescription(), -1);
 
-	str_format(buf, sizeof(buf), "%ds left", gameclient.voting->seconds_left());
-	float tw = gfx_text_width(0x0, 6, buf, -1);
-	gfx_text(0x0, 5+100-tw, 60, 6, buf, -1);
+	str_format(Buf, sizeof(Buf), "%ds left", m_pClient->m_pVoting->SecondsLeft());
+	float tw = TextRender()->TextWidth(0x0, 6, Buf, -1);
+	TextRender()->Text(0x0, 5+100-tw, 60, 6, Buf, -1);
 	
 
-	CUIRect base = {5, 70, 100, 4};
-	gameclient.voting->render_bars(base, false);
+	CUIRect Base = {5, 70, 100, 4};
+	m_pClient->m_pVoting->RenderBars(Base, false);
 	
-	const char *yes_key = gameclient.binds->get_key("vote yes");
-	const char *no_key = gameclient.binds->get_key("vote no");
-	str_format(buf, sizeof(buf), "%s - Vote Yes", yes_key);
-	base.y += base.h+1;
-	UI()->DoLabel(&base, buf, 6.0f, -1);
-
-	str_format(buf, sizeof(buf), "Vote No - %s", no_key);
-	UI()->DoLabel(&base, buf, 6.0f, 1);
+	const char *pYesKey = m_pClient->m_pBinds->GetKey("vote yes");
+	const char *pNoKey = m_pClient->m_pBinds->GetKey("vote no");
+	str_format(Buf, sizeof(Buf), "%s - Vote Yes", pYesKey);
+	Base.y += Base.h+1;
+	UI()->DoLabel(&Base, Buf, 6.0f, -1);
+
+	str_format(Buf, sizeof(Buf), "Vote No - %s", pNoKey);
+	UI()->DoLabel(&Base, Buf, 6.0f, 1);
 }
 
-void HUD::render_cursor()
+void CHud::RenderCursor()
 {
-	if(!gameclient.snap.local_character)
+	if(!m_pClient->m_Snap.m_pLocalCharacter)
 		return;
 		
-	mapscreen_to_group(gameclient.camera->center.x, gameclient.camera->center.y, layers_game_group());
-	Graphics()->TextureSet(data->images[IMAGE_GAME].id);
+	MapscreenToGroup(m_pClient->m_pCamera->m_Center.x, m_pClient->m_pCamera->m_Center.y, Layers()->GameGroup());
+	Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
 	Graphics()->QuadsBegin();
 
 	// render cursor
-	RenderTools()->select_sprite(data->weapons.id[gameclient.snap.local_character->weapon%NUM_WEAPONS].sprite_cursor);
-	float cursorsize = 64;
-	RenderTools()->draw_sprite(gameclient.controls->target_pos.x, gameclient.controls->target_pos.y, cursorsize);
+	RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[m_pClient->m_Snap.m_pLocalCharacter->m_Weapon%NUM_WEAPONS].m_pSpriteCursor);
+	float CursorSize = 64;
+	RenderTools()->DrawSprite(m_pClient->m_pControls->m_TargetPos.x, m_pClient->m_pControls->m_TargetPos.y, CursorSize);
 	Graphics()->QuadsEnd();
 }
 
-void HUD::render_healthandammo()
+void CHud::RenderHealthAndAmmo()
 {
 	//mapscreen_to_group(gacenter_x, center_y, layers_game_group());
 
@@ -248,61 +252,69 @@ void HUD::render_healthandammo()
 	// render ammo count
 	// render gui stuff
 
-	Graphics()->TextureSet(data->images[IMAGE_GAME].id);
-	Graphics()->MapScreen(0,0,width,300);
+	Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
+	Graphics()->MapScreen(0,0,m_Width,300);
 	
 	Graphics()->QuadsBegin();
 	
 	// if weaponstage is active, put a "glow" around the stage ammo
-	RenderTools()->select_sprite(data->weapons.id[gameclient.snap.local_character->weapon%NUM_WEAPONS].sprite_proj);
-	for (int i = 0; i < min(gameclient.snap.local_character->ammocount, 10); i++)
-		Graphics()->QuadsDrawTL(x+i*12,y+24,10,10);
-
+	RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[m_pClient->m_Snap.m_pLocalCharacter->m_Weapon%NUM_WEAPONS].m_pSpriteProj);
+	IGraphics::CQuadItem Array[10];
+	int i;
+	for (i = 0; i < min(m_pClient->m_Snap.m_pLocalCharacter->m_AmmoCount, 10); i++)
+		Array[i] = IGraphics::CQuadItem(x+i*12,y+24,10,10);
+	Graphics()->QuadsDrawTL(Array, i);
 	Graphics()->QuadsEnd();
 
 	Graphics()->QuadsBegin();
 	int h = 0;
 
 	// render health
-	RenderTools()->select_sprite(SPRITE_HEALTH_FULL);
-	for(; h < gameclient.snap.local_character->health; h++)
-		Graphics()->QuadsDrawTL(x+h*12,y,10,10);
+	RenderTools()->SelectSprite(SPRITE_HEALTH_FULL);
+	for(; h < min(m_pClient->m_Snap.m_pLocalCharacter->m_Health, 10); h++)
+		Array[h] = IGraphics::CQuadItem(x+h*12,y,10,10);
+	Graphics()->QuadsDrawTL(Array, h);
 
-	RenderTools()->select_sprite(SPRITE_HEALTH_EMPTY);
+	i = 0;
+	RenderTools()->SelectSprite(SPRITE_HEALTH_EMPTY);
 	for(; h < 10; h++)
-		Graphics()->QuadsDrawTL(x+h*12,y,10,10);
+		Array[i++] = IGraphics::CQuadItem(x+h*12,y,10,10);
+	Graphics()->QuadsDrawTL(Array, i);
 
 	// render armor meter
 	h = 0;
-	RenderTools()->select_sprite(SPRITE_ARMOR_FULL);
-	for(; h < gameclient.snap.local_character->armor; h++)
-		Graphics()->QuadsDrawTL(x+h*12,y+12,10,10);
+	RenderTools()->SelectSprite(SPRITE_ARMOR_FULL);
+	for(; h < min(m_pClient->m_Snap.m_pLocalCharacter->m_Armor, 10); h++)
+		Array[h] = IGraphics::CQuadItem(x+h*12,y+12,10,10);
+	Graphics()->QuadsDrawTL(Array, h);
 
-	RenderTools()->select_sprite(SPRITE_ARMOR_EMPTY);
+	i = 0;
+	RenderTools()->SelectSprite(SPRITE_ARMOR_EMPTY);
 	for(; h < 10; h++)
-		Graphics()->QuadsDrawTL(x+h*12,y+12,10,10);
+		Array[i++] = IGraphics::CQuadItem(x+h*12,y+12,10,10);
+	Graphics()->QuadsDrawTL(Array, i);
 	Graphics()->QuadsEnd();
 }
 
-void HUD::on_render()
+void CHud::OnRender()
 {
-	if(!gameclient.snap.gameobj)
+	if(!m_pClient->m_Snap.m_pGameobj)
 		return;
 		
-	width = 300*Graphics()->ScreenAspect();
+	m_Width = 300*Graphics()->ScreenAspect();
 
-	bool spectate = false;
-	if(gameclient.snap.local_info && gameclient.snap.local_info->team == -1)
-		spectate = true;
+	bool Spectate = false;
+	if(m_pClient->m_Snap.m_pLocalInfo && m_pClient->m_Snap.m_pLocalInfo->m_Team == -1)
+		Spectate = true;
 	
-	if(gameclient.snap.local_character && !spectate && !(gameclient.snap.gameobj && gameclient.snap.gameobj->game_over))
-		render_healthandammo();
-
-	render_goals();
-	render_fps();
-	if(client_state() != CLIENTSTATE_DEMOPLAYBACK)
-		render_connectionwarning();
-	render_teambalancewarning();
-	render_voting();
-	render_cursor();
+	if(m_pClient->m_Snap.m_pLocalCharacter && !Spectate && !(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver))
+		RenderHealthAndAmmo();
+
+	RenderGoals();
+	RenderFps();
+	if(Client()->State() != IClient::STATE_DEMOPLAYBACK)
+		RenderConnectionWarning();
+	RenderTeambalanceWarning();
+	RenderVoting();
+	RenderCursor();
 }
diff --git a/src/game/client/components/hud.h b/src/game/client/components/hud.h
new file mode 100644
index 00000000..43f0e3a8
--- /dev/null
+++ b/src/game/client/components/hud.h
@@ -0,0 +1,27 @@
+#ifndef GAME_CLIENT_COMPONENTS_HUD_H
+#define GAME_CLIENT_COMPONENTS_HUD_H
+#include <game/client/component.h>
+
+class CHud : public CComponent
+{	
+	float m_Width;
+	float m_AverageFPS;
+	
+	void RenderCursor();
+	
+	void RenderFps();
+	void RenderConnectionWarning();
+	void RenderTeambalanceWarning();
+	void RenderVoting();
+	void RenderHealthAndAmmo();
+	void RenderGoals();
+	
+	void MapscreenToGroup(float CenterX, float CenterY, struct CMapItemGroup *PGroup);
+public:
+	CHud();
+	
+	virtual void OnReset();
+	virtual void OnRender();
+};
+
+#endif
diff --git a/src/game/client/components/hud.hpp b/src/game/client/components/hud.hpp
deleted file mode 100644
index 92ff0122..00000000
--- a/src/game/client/components/hud.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include <game/client/component.hpp>
-
-class HUD : public COMPONENT
-{	
-	float width;
-	
-	void render_cursor();
-	
-	void render_fps();
-	void render_connectionwarning();
-	void render_teambalancewarning();
-	void render_voting();
-	void render_healthandammo();
-	void render_goals();
-	
-	
-	void mapscreen_to_group(float center_x, float center_y, struct MAPITEM_GROUP *group);
-public:
-	HUD();
-	
-	virtual void on_reset();
-	virtual void on_render();
-};
-
diff --git a/src/game/client/components/items.cpp b/src/game/client/components/items.cpp
index 3c9e1b79..70479e53 100644
--- a/src/game/client/components/items.cpp
+++ b/src/game/client/components/items.cpp
@@ -1,94 +1,94 @@
-#include <engine/e_client_interface.h>
-#include <engine/client/graphics.h>
-#include <game/generated/g_protocol.hpp>
-#include <game/generated/gc_data.hpp>
+#include <engine/graphics.h>
+#include <game/generated/protocol.h>
+#include <game/generated/client_data.h>
 
-#include <game/gamecore.hpp> // get_angle
-#include <game/client/gameclient.hpp>
-#include <game/client/ui.hpp>
-#include <game/client/render.hpp>
+#include <game/gamecore.h> // get_angle
+#include <game/client/gameclient.h>
+#include <game/client/ui.h>
+#include <game/client/render.h>
 
-#include <game/client/components/flow.hpp>
-#include <game/client/components/effects.hpp>
+#include <game/client/components/flow.h>
+#include <game/client/components/effects.h>
 
-#include "items.hpp"
+#include "items.h"
 
-void ITEMS::render_projectile(const NETOBJ_PROJECTILE *current, int itemid)
+void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemId)
 {
 
 	// get positions
-	float curvature = 0;
-	float speed = 0;
-	if(current->type == WEAPON_GRENADE)
+	float Curvature = 0;
+	float Speed = 0;
+	if(pCurrent->m_Type == WEAPON_GRENADE)
 	{
-		curvature = gameclient.tuning.grenade_curvature;
-		speed = gameclient.tuning.grenade_speed;
+		Curvature = m_pClient->m_Tuning.m_GrenadeCurvature;
+		Speed = m_pClient->m_Tuning.m_GrenadeSpeed;
 	}
-	else if(current->type == WEAPON_SHOTGUN)
+	else if(pCurrent->m_Type == WEAPON_SHOTGUN)
 	{
-		curvature = gameclient.tuning.shotgun_curvature;
-		speed = gameclient.tuning.shotgun_speed;
+		Curvature = m_pClient->m_Tuning.m_ShotgunCurvature;
+		Speed = m_pClient->m_Tuning.m_ShotgunSpeed;
 	}
-	else if(current->type == WEAPON_GUN)
+	else if(pCurrent->m_Type == WEAPON_GUN)
 	{
-		curvature = gameclient.tuning.gun_curvature;
-		speed = gameclient.tuning.gun_speed;
+		Curvature = m_pClient->m_Tuning.m_GunCurvature;
+		Speed = m_pClient->m_Tuning.m_GunSpeed;
 	}
 
-	float ct = (client_prevtick()-current->start_tick)/(float)SERVER_TICK_SPEED + client_ticktime();
-	if(ct < 0)
+	float Ct = (Client()->PrevGameTick()-pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED + Client()->GameTickTime();
+	if(Ct < 0)
 		return; // projectile havn't been shot yet
 		
-	vec2 startpos(current->x, current->y);
-	vec2 startvel(current->vx/100.0f, current->vy/100.0f);
-	vec2 pos = calc_pos(startpos, startvel, curvature, speed, ct);
-	vec2 prevpos = calc_pos(startpos, startvel, curvature, speed, ct-0.001f);
+	vec2 StartPos(pCurrent->m_X, pCurrent->m_Y);
+	vec2 StartVel(pCurrent->m_VelX/100.0f, pCurrent->m_VelY/100.0f);
+	vec2 Pos = CalcPos(StartPos, StartVel, Curvature, Speed, Ct);
+	vec2 PrevPos = CalcPos(StartPos, StartVel, Curvature, Speed, Ct-0.001f);
 
 
-	Graphics()->TextureSet(data->images[IMAGE_GAME].id);
+	Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
 	Graphics()->QuadsBegin();
 	
-	RenderTools()->select_sprite(data->weapons.id[clamp(current->type, 0, NUM_WEAPONS-1)].sprite_proj);
-	vec2 vel = pos-prevpos;
-	//vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), client_intratick());
+	RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[clamp(pCurrent->m_Type, 0, NUM_WEAPONS-1)].m_pSpriteProj);
+	vec2 Vel = Pos-PrevPos;
+	//vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), Client()->IntraGameTick());
 	
 
 	// add particle for this projectile
-	if(current->type == WEAPON_GRENADE)
+	if(pCurrent->m_Type == WEAPON_GRENADE)
 	{
-		gameclient.effects->smoketrail(pos, vel*-1);
-		gameclient.flow->add(pos, vel*1000*client_frametime(), 10.0f);
-		Graphics()->QuadsSetRotation(client_localtime()*pi*2*2 + itemid);
+		m_pClient->m_pEffects->SmokeTrail(Pos, Vel*-1);
+		m_pClient->m_pFlow->Add(Pos, Vel*1000*Client()->FrameTime(), 10.0f);
+		Graphics()->QuadsSetRotation(Client()->LocalTime()*pi*2*2 + ItemId);
 	}
 	else
 	{
-		gameclient.effects->bullettrail(pos);
-		gameclient.flow->add(pos, vel*1000*client_frametime(), 10.0f);
+		m_pClient->m_pEffects->BulletTrail(Pos);
+		m_pClient->m_pFlow->Add(Pos, Vel*1000*Client()->FrameTime(), 10.0f);
 
-		if(length(vel) > 0.00001f)
-			Graphics()->QuadsSetRotation(get_angle(vel));
+		if(length(Vel) > 0.00001f)
+			Graphics()->QuadsSetRotation(GetAngle(Vel));
 		else
 			Graphics()->QuadsSetRotation(0);
 
 	}
 
-	Graphics()->QuadsDraw(pos.x, pos.y, 32, 32);
+	IGraphics::CQuadItem QuadItem(Pos.x, Pos.y, 32, 32);
+	Graphics()->QuadsDraw(&QuadItem, 1);
 	Graphics()->QuadsSetRotation(0);
 	Graphics()->QuadsEnd();
 }
 
-void ITEMS::render_pickup(const NETOBJ_PICKUP *prev, const NETOBJ_PICKUP *current)
+void CItems::RenderPickup(const CNetObj_Pickup *pPrev, const CNetObj_Pickup *pCurrent)
 {
-	Graphics()->TextureSet(data->images[IMAGE_GAME].id);
+	Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
 	Graphics()->QuadsBegin();
-	vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), client_intratick());
-	float angle = 0.0f;
-	float size = 64.0f;
-	if (current->type == POWERUP_WEAPON)
+	vec2 Pos = mix(vec2(pPrev->m_X, pPrev->m_Y), vec2(pCurrent->m_X, pCurrent->m_Y), Client()->IntraGameTick());
+	float Angle = 0.0f;
+	float Size = 64.0f;
+	if (pCurrent->m_Type == POWERUP_WEAPON)
 	{
-		angle = 0; //-pi/6;//-0.25f * pi * 2.0f;
-		RenderTools()->select_sprite(data->weapons.id[clamp(current->subtype, 0, NUM_WEAPONS-1)].sprite_body);
-		size = data->weapons.id[clamp(current->subtype, 0, NUM_WEAPONS-1)].visual_size;
+		Angle = 0; //-pi/6;//-0.25f * pi * 2.0f;
+		RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[clamp(pCurrent->m_Subtype, 0, NUM_WEAPONS-1)].m_pSpriteBody);
+		Size = g_pData->m_Weapons.m_aId[clamp(pCurrent->m_Subtype, 0, NUM_WEAPONS-1)].m_VisualSize;
 	}
 	else
 	{
@@ -98,69 +98,70 @@ void ITEMS::render_pickup(const NETOBJ_PICKUP *prev, const NETOBJ_PICKUP *curren
 			SPRITE_PICKUP_WEAPON,
 			SPRITE_PICKUP_NINJA
 			};
-		RenderTools()->select_sprite(c[current->type]);
+		RenderTools()->SelectSprite(c[pCurrent->m_Type]);
 
-		if(c[current->type] == SPRITE_PICKUP_NINJA)
+		if(c[pCurrent->m_Type] == SPRITE_PICKUP_NINJA)
 		{
-			gameclient.effects->powerupshine(pos, vec2(96,18));
-			size *= 2.0f;
-			pos.x += 10.0f;
+			m_pClient->m_pEffects->PowerupShine(Pos, vec2(96,18));
+			Size *= 2.0f;
+			Pos.x += 10.0f;
 		}
 	}
 
-	Graphics()->QuadsSetRotation(angle);
+	Graphics()->QuadsSetRotation(Angle);
 
-	float offset = pos.y/32.0f + pos.x/32.0f;
-	pos.x += cosf(client_localtime()*2.0f+offset)*2.5f;
-	pos.y += sinf(client_localtime()*2.0f+offset)*2.5f;
-	RenderTools()->draw_sprite(pos.x, pos.y, size);
+	float Offset = Pos.y/32.0f + Pos.x/32.0f;
+	Pos.x += cosf(Client()->LocalTime()*2.0f+Offset)*2.5f;
+	Pos.y += sinf(Client()->LocalTime()*2.0f+Offset)*2.5f;
+	RenderTools()->DrawSprite(Pos.x, Pos.y, Size);
 	Graphics()->QuadsEnd();
 }
 
-void ITEMS::render_flag(const NETOBJ_FLAG *prev, const NETOBJ_FLAG *current)
+void CItems::RenderFlag(const CNetObj_Flag *pPrev, const CNetObj_Flag *pCurrent)
 {
-	float angle = 0.0f;
-	float size = 42.0f;
+	float Angle = 0.0f;
+	float Size = 42.0f;
 
 	Graphics()->BlendNormal();
-	Graphics()->TextureSet(data->images[IMAGE_GAME].id);
+	Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
 	Graphics()->QuadsBegin();
 
-	if(current->team == 0) // red team
-		RenderTools()->select_sprite(SPRITE_FLAG_RED);
+	if(pCurrent->m_Team == 0) // red team
+		RenderTools()->SelectSprite(SPRITE_FLAG_RED);
 	else
-		RenderTools()->select_sprite(SPRITE_FLAG_BLUE);
+		RenderTools()->SelectSprite(SPRITE_FLAG_BLUE);
 
-	Graphics()->QuadsSetRotation(angle);
+	Graphics()->QuadsSetRotation(Angle);
 
-	vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), client_intratick());
+	vec2 Pos = mix(vec2(pPrev->m_X, pPrev->m_Y), vec2(pCurrent->m_X, pCurrent->m_Y), Client()->IntraGameTick());
 	
 	// make sure that the flag isn't interpolated between capture and return
-	if(prev->carried_by != current->carried_by)
-		pos = vec2(current->x, current->y);
+	if(pPrev->m_CarriedBy != pCurrent->m_CarriedBy)
+		Pos = vec2(pCurrent->m_X, pCurrent->m_Y);
 
 	// make sure to use predicted position if we are the carrier
-	if(gameclient.snap.local_info && current->carried_by == gameclient.snap.local_info->cid)
-		pos = gameclient.local_character_pos;
+	if(m_pClient->m_Snap.m_pLocalInfo && pCurrent->m_CarriedBy == m_pClient->m_Snap.m_pLocalInfo->m_ClientId)
+		Pos = m_pClient->m_LocalCharacterPos;
 
-	Graphics()->QuadsDraw(pos.x, pos.y-size*0.75f, size, size*2);
+	IGraphics::CQuadItem QuadItem(Pos.x, Pos.y-Size*0.75f, Size, Size*2);
+	Graphics()->QuadsDraw(&QuadItem, 1);
 	Graphics()->QuadsEnd();
 }
 
 
-void ITEMS::render_laser(const struct NETOBJ_LASER *current)
+void CItems::RenderLaser(const struct CNetObj_Laser *pCurrent)
 {
-	vec2 pos = vec2(current->x, current->y);
-	vec2 from = vec2(current->from_x, current->from_y);
-	vec2 dir = normalize(pos-from);
+	vec2 Pos = vec2(pCurrent->m_X, pCurrent->m_Y);
+	vec2 From = vec2(pCurrent->m_FromX, pCurrent->m_FromY);
+	vec2 Dir = normalize(Pos-From);
 
-	float ticks = client_tick() + client_intratick() - current->start_tick;
-	float ms = (ticks/50.0f) * 1000.0f;
-	float a =  ms / gameclient.tuning.laser_bounce_delay;
+	float Ticks = Client()->GameTick() + Client()->IntraGameTick() - pCurrent->m_StartTick;
+	float Ms = (Ticks/50.0f) * 1000.0f;
+	float a =  Ms / m_pClient->m_Tuning.m_LaserBounceDelay;
 	a = clamp(a, 0.0f, 1.0f);
-	float ia = 1-a;
+	float Ia = 1-a;
 	
-	vec2 out, border;
+	vec2 Out, Border;
 	
 	Graphics()->BlendNormal();
 	Graphics()->TextureSet(-1);
@@ -170,77 +171,87 @@ void ITEMS::render_laser(const struct NETOBJ_LASER *current)
 	//vec4 outer_color(0.65f,0.85f,1.0f,1.0f);
 
 	// do outline
-	vec4 outer_color(0.075f,0.075f,0.25f,1.0f);
-	Graphics()->SetColor(outer_color.r,outer_color.g,outer_color.b,1.0f);
-	out = vec2(dir.y, -dir.x) * (7.0f*ia);
+	vec4 OuterColor(0.075f, 0.075f, 0.25f, 1.0f);
+	Graphics()->SetColor(OuterColor.r, OuterColor.g, OuterColor.b, 1.0f);
+	Out = vec2(Dir.y, -Dir.x) * (7.0f*Ia);
 
-	Graphics()->QuadsDrawFreeform(
-			from.x-out.x, from.y-out.y,
-			from.x+out.x, from.y+out.y,
-			pos.x-out.x, pos.y-out.y,
-			pos.x+out.x, pos.y+out.y
-		);
+	IGraphics::CFreeformItem Freeform(
+			From.x-Out.x, From.y-Out.y,
+			From.x+Out.x, From.y+Out.y,
+			Pos.x-Out.x, Pos.y-Out.y,
+			Pos.x+Out.x, Pos.y+Out.y);
+	Graphics()->QuadsDrawFreeform(&Freeform, 1);
 
 	// do inner	
-	vec4 inner_color(0.5f,0.5f,1.0f,1.0f);
-	out = vec2(dir.y, -dir.x) * (5.0f*ia);
-	Graphics()->SetColor(inner_color.r, inner_color.g, inner_color.b, 1.0f); // center
+	vec4 InnerColor(0.5f, 0.5f, 1.0f, 1.0f);
+	Out = vec2(Dir.y, -Dir.x) * (5.0f*Ia);
+	Graphics()->SetColor(InnerColor.r, InnerColor.g, InnerColor.b, 1.0f); // center
 	
-	Graphics()->QuadsDrawFreeform(
-			from.x-out.x, from.y-out.y,
-			from.x+out.x, from.y+out.y,
-			pos.x-out.x, pos.y-out.y,
-			pos.x+out.x, pos.y+out.y
-		);
+	Freeform = IGraphics::CFreeformItem(
+			From.x-Out.x, From.y-Out.y,
+			From.x+Out.x, From.y+Out.y,
+			Pos.x-Out.x, Pos.y-Out.y,
+			Pos.x+Out.x, Pos.y+Out.y);
+	Graphics()->QuadsDrawFreeform(&Freeform, 1);
 		
 	Graphics()->QuadsEnd();
 	
 	// render head
 	{
 		Graphics()->BlendNormal();
-		Graphics()->TextureSet(data->images[IMAGE_PARTICLES].id);
+		Graphics()->TextureSet(g_pData->m_aImages[IMAGE_PARTICLES].m_Id);
 		Graphics()->QuadsBegin();
 
-		int sprites[] = {SPRITE_PART_SPLAT01, SPRITE_PART_SPLAT02, SPRITE_PART_SPLAT03};
-		RenderTools()->select_sprite(sprites[client_tick()%3]);
-		Graphics()->QuadsSetRotation(client_tick());
-		Graphics()->SetColor(outer_color.r,outer_color.g,outer_color.b,1.0f);
-		Graphics()->QuadsDraw(pos.x, pos.y, 24,24);
-		Graphics()->SetColor(inner_color.r, inner_color.g, inner_color.b, 1.0f);
-		Graphics()->QuadsDraw(pos.x, pos.y, 20,20);
+		int Sprites[] = {SPRITE_PART_SPLAT01, SPRITE_PART_SPLAT02, SPRITE_PART_SPLAT03};
+		RenderTools()->SelectSprite(Sprites[Client()->GameTick()%3]);
+		Graphics()->QuadsSetRotation(Client()->GameTick());
+		Graphics()->SetColor(OuterColor.r, OuterColor.g, OuterColor.b, 1.0f);
+		IGraphics::CQuadItem QuadItem(Pos.x, Pos.y, 24, 24);
+		Graphics()->QuadsDraw(&QuadItem, 1);
+		Graphics()->SetColor(InnerColor.r, InnerColor.g, InnerColor.b, 1.0f);
+		QuadItem = IGraphics::CQuadItem(Pos.x, Pos.y, 20, 20);
+		Graphics()->QuadsDraw(&QuadItem, 1);
 		Graphics()->QuadsEnd();
 	}
 	
 	Graphics()->BlendNormal();	
 }
 
-void ITEMS::on_render()
+void CItems::OnRender()
 {
-	int num = snap_num_items(SNAP_CURRENT);
-	for(int i = 0; i < num; i++)
+	int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT);
+	for(int i = 0; i < Num; i++)
 	{
-		SNAP_ITEM item;
-		const void *data = snap_get_item(SNAP_CURRENT, i, &item);
+		IClient::CSnapItem Item;
+		const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item);
 
-		if(item.type == NETOBJTYPE_PROJECTILE)
+		if(Item.m_Type == NETOBJTYPE_PROJECTILE)
 		{
-			render_projectile((const NETOBJ_PROJECTILE *)data, item.id);
+			RenderProjectile((const CNetObj_Projectile *)pData, Item.m_Id);
 		}
-		else if(item.type == NETOBJTYPE_PICKUP)
+		else if(Item.m_Type == NETOBJTYPE_PICKUP)
 		{
-			const void *prev = snap_find_item(SNAP_PREV, item.type, item.id);
-			if(prev)
-				render_pickup((const NETOBJ_PICKUP *)prev, (const NETOBJ_PICKUP *)data);
+			const void *pPrev = Client()->SnapFindItem(IClient::SNAP_PREV, Item.m_Type, Item.m_Id);
+			if(pPrev)
+				RenderPickup((const CNetObj_Pickup *)pPrev, (const CNetObj_Pickup *)pData);
 		}
-		else if(item.type == NETOBJTYPE_LASER)
+		else if(Item.m_Type == NETOBJTYPE_LASER)
 		{
-			render_laser((const NETOBJ_LASER *)data);
+			RenderLaser((const CNetObj_Laser *)pData);
 		}
-		else if(item.type == NETOBJTYPE_FLAG)
+	}
+
+	// render flag
+	for(int i = 0; i < Num; i++)
+	{
+		IClient::CSnapItem Item;
+		const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item);
+
+		if(Item.m_Type == NETOBJTYPE_FLAG)
 		{
-			const void *prev = snap_find_item(SNAP_PREV, item.type, item.id);
-			if (prev)
-				render_flag((const NETOBJ_FLAG *)prev, (const NETOBJ_FLAG *)data);
+			const void *pPrev = Client()->SnapFindItem(IClient::SNAP_PREV, Item.m_Type, Item.m_Id);
+			if (pPrev)
+				RenderFlag((const CNetObj_Flag *)pPrev, (const CNetObj_Flag *)pData);
 		}
 	}
 
@@ -248,7 +259,7 @@ void ITEMS::on_render()
 	/*
 	for(int i = 0; i < extraproj_num; i++)
 	{
-		if(extraproj_projectiles[i].start_tick < client_tick())
+		if(extraproj_projectiles[i].start_tick < Client()->GameTick())
 		{
 			extraproj_projectiles[i] = extraproj_projectiles[extraproj_num-1];
 			extraproj_num--;
diff --git a/src/game/client/components/items.h b/src/game/client/components/items.h
new file mode 100644
index 00000000..e4525546
--- /dev/null
+++ b/src/game/client/components/items.h
@@ -0,0 +1,16 @@
+#ifndef GAME_CLIENT_COMPONENTS_ITEMS_H
+#define GAME_CLIENT_COMPONENTS_ITEMS_H
+#include <game/client/component.h>
+
+class CItems : public CComponent
+{	
+	void RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemId);
+	void RenderPickup(const CNetObj_Pickup *pPrev, const CNetObj_Pickup *pCurrent);
+	void RenderFlag(const CNetObj_Flag *pPrev, const CNetObj_Flag *pCurrent);
+	void RenderLaser(const struct CNetObj_Laser *pCurrent);
+	
+public:
+	virtual void OnRender();
+};
+
+#endif
diff --git a/src/game/client/components/items.hpp b/src/game/client/components/items.hpp
deleted file mode 100644
index 2f33c8c4..00000000
--- a/src/game/client/components/items.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <game/client/component.hpp>
-
-class ITEMS : public COMPONENT
-{	
-	void render_projectile(const NETOBJ_PROJECTILE *current, int itemid);
-	void render_pickup(const NETOBJ_PICKUP *prev, const NETOBJ_PICKUP *current);
-	void render_flag(const NETOBJ_FLAG *prev, const NETOBJ_FLAG *current);
-	void render_laser(const struct NETOBJ_LASER *current);
-	
-public:
-	virtual void on_render();
-};
-
diff --git a/src/game/client/components/killmessages.cpp b/src/game/client/components/killmessages.cpp
index e6232b7d..d18dd965 100644
--- a/src/game/client/components/killmessages.cpp
+++ b/src/game/client/components/killmessages.cpp
@@ -1,127 +1,129 @@
-#include <engine/e_client_interface.h>
-#include <engine/client/graphics.h>
-#include <game/generated/g_protocol.hpp>
-#include <game/generated/gc_data.hpp>
+#include <engine/graphics.h>
+#include <engine/textrender.h>
+#include <game/generated/protocol.h>
+#include <game/generated/client_data.h>
 
-#include <game/client/gameclient.hpp>
-#include <game/client/animstate.hpp>
-#include "killmessages.hpp"
+#include <game/client/gameclient.h>
+#include <game/client/animstate.h>
+#include "killmessages.h"
 
-void KILLMESSAGES::on_reset()
+void CKillMessages::OnReset()
 {
-	killmsg_current = 0;
-	for(int i = 0; i < killmsg_max; i++)
-		killmsgs[i].tick = -100000;
+	m_KillmsgCurrent = 0;
+	for(int i = 0; i < MAX_KILLMSGS; i++)
+		m_aKillmsgs[i].m_Tick = -100000;
 }
 
-void KILLMESSAGES::on_message(int msgtype, void *rawmsg)
+void CKillMessages::OnMessage(int MsgType, void *pRawMsg)
 {
-	if(msgtype == NETMSGTYPE_SV_KILLMSG)
+	if(MsgType == NETMSGTYPE_SV_KILLMSG)
 	{
-		NETMSG_SV_KILLMSG *msg = (NETMSG_SV_KILLMSG *)rawmsg;
+		CNetMsg_Sv_KillMsg *pMsg = (CNetMsg_Sv_KillMsg *)pRawMsg;
 		
 		// unpack messages
-		KILLMSG kill;
-		kill.killer = msg->killer;
-		kill.victim = msg->victim;
-		kill.weapon = msg->weapon;
-		kill.mode_special = msg->mode_special;
-		kill.tick = client_tick();
+		CKillMsg Kill;
+		Kill.m_Killer = pMsg->m_Killer;
+		Kill.m_Victim = pMsg->m_Victim;
+		Kill.m_Weapon = pMsg->m_Weapon;
+		Kill.m_ModeSpecial = pMsg->m_ModeSpecial;
+		Kill.m_Tick = Client()->GameTick();
 
 		// add the message
-		killmsg_current = (killmsg_current+1)%killmsg_max;
-		killmsgs[killmsg_current] = kill;		
+		m_KillmsgCurrent = (m_KillmsgCurrent+1)%MAX_KILLMSGS;
+		m_aKillmsgs[m_KillmsgCurrent] = Kill;
 	}
 }
 
-void KILLMESSAGES::on_render()
+void CKillMessages::OnRender()
 {
-	float width = 400*3.0f*Graphics()->ScreenAspect();
-	float height = 400*3.0f;
+	float Width = 400*3.0f*Graphics()->ScreenAspect();
+	float Height = 400*3.0f;
 
-	Graphics()->MapScreen(0, 0, width*1.5f, height*1.5f);
-	float startx = width*1.5f-10.0f;
+	Graphics()->MapScreen(0, 0, Width*1.5f, Height*1.5f);
+	float StartX = Width*1.5f-10.0f;
 	float y = 20.0f;
 
-	for(int i = 0; i < killmsg_max; i++)
+	for(int i = 0; i < MAX_KILLMSGS; i++)
 	{
 
-		int r = (killmsg_current+i+1)%killmsg_max;
-		if(client_tick() > killmsgs[r].tick+50*10)
+		int r = (m_KillmsgCurrent+i+1)%MAX_KILLMSGS;
+		if(Client()->GameTick() > m_aKillmsgs[r].m_Tick+50*10)
 			continue;
 
-		float font_size = 36.0f;
-		float killername_w = gfx_text_width(0, font_size, gameclient.clients[killmsgs[r].killer].name, -1);
-		float victimname_w = gfx_text_width(0, font_size, gameclient.clients[killmsgs[r].victim].name, -1);
+		float FontSize = 36.0f;
+		float KillerNameW = TextRender()->TextWidth(0, FontSize, m_pClient->m_aClients[m_aKillmsgs[r].m_Killer].m_aName, -1);
+		float VictimNameW = TextRender()->TextWidth(0, FontSize, m_pClient->m_aClients[m_aKillmsgs[r].m_Victim].m_aName, -1);
 
-		float x = startx;
+		float x = StartX;
 
 		// render victim name
-		x -= victimname_w;
-		gfx_text(0, x, y, font_size, gameclient.clients[killmsgs[r].victim].name, -1);
+		x -= VictimNameW;
+		TextRender()->Text(0, x, y, FontSize, m_pClient->m_aClients[m_aKillmsgs[r].m_Victim].m_aName, -1);
 
 		// render victim tee
 		x -= 24.0f;
 		
-		if(gameclient.snap.gameobj && gameclient.snap.gameobj->flags&GAMEFLAG_FLAGS)
+		if(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_Flags&GAMEFLAG_FLAGS)
 		{
-			if(killmsgs[r].mode_special&1)
+			if(m_aKillmsgs[r].m_ModeSpecial&1)
 			{
 				Graphics()->BlendNormal();
-				Graphics()->TextureSet(data->images[IMAGE_GAME].id);
+				Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
 				Graphics()->QuadsBegin();
 
-				if(gameclient.clients[killmsgs[r].victim].team == 0) RenderTools()->select_sprite(SPRITE_FLAG_BLUE);
-				else RenderTools()->select_sprite(SPRITE_FLAG_RED);
+				if(m_pClient->m_aClients[m_aKillmsgs[r].m_Victim].m_Team == 0) RenderTools()->SelectSprite(SPRITE_FLAG_BLUE);
+				else RenderTools()->SelectSprite(SPRITE_FLAG_RED);
 				
-				float size = 56.0f;
-				Graphics()->QuadsDrawTL(x, y-16, size/2, size);
+				float Size = 56.0f;
+				IGraphics::CQuadItem QuadItem(x, y-16, Size/2, Size);
+				Graphics()->QuadsDrawTL(&QuadItem, 1);
 				Graphics()->QuadsEnd();					
 			}
 		}
 		
-		RenderTools()->RenderTee(ANIMSTATE::get_idle(), &gameclient.clients[killmsgs[r].victim].render_info, EMOTE_PAIN, vec2(-1,0), vec2(x, y+28));
+		RenderTools()->RenderTee(CAnimState::GetIdle(), &m_pClient->m_aClients[m_aKillmsgs[r].m_Victim].m_RenderInfo, EMOTE_PAIN, vec2(-1,0), vec2(x, y+28));
 		x -= 32.0f;
 		
 		// render weapon
 		x -= 44.0f;
-		if (killmsgs[r].weapon >= 0)
+		if (m_aKillmsgs[r].m_Weapon >= 0)
 		{
-			Graphics()->TextureSet(data->images[IMAGE_GAME].id);
+			Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
 			Graphics()->QuadsBegin();
-			RenderTools()->select_sprite(data->weapons.id[killmsgs[r].weapon].sprite_body);
-			RenderTools()->draw_sprite(x, y+28, 96);
+			RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[m_aKillmsgs[r].m_Weapon].m_pSpriteBody);
+			RenderTools()->DrawSprite(x, y+28, 96);
 			Graphics()->QuadsEnd();
 		}
 		x -= 52.0f;
 
-		if(killmsgs[r].victim != killmsgs[r].killer)
+		if(m_aKillmsgs[r].m_Victim != m_aKillmsgs[r].m_Killer)
 		{
-			if(gameclient.snap.gameobj && gameclient.snap.gameobj->flags&GAMEFLAG_FLAGS)
+			if(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_Flags&GAMEFLAG_FLAGS)
 			{
-				if(killmsgs[r].mode_special&2)
+				if(m_aKillmsgs[r].m_ModeSpecial&2)
 				{
 					Graphics()->BlendNormal();
-					Graphics()->TextureSet(data->images[IMAGE_GAME].id);
+					Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
 					Graphics()->QuadsBegin();
 
-					if(gameclient.clients[killmsgs[r].killer].team == 0) RenderTools()->select_sprite(SPRITE_FLAG_BLUE, SPRITE_FLAG_FLIP_X);
-					else RenderTools()->select_sprite(SPRITE_FLAG_RED, SPRITE_FLAG_FLIP_X);
+					if(m_pClient->m_aClients[m_aKillmsgs[r].m_Killer].m_Team == 0) RenderTools()->SelectSprite(SPRITE_FLAG_BLUE, SPRITE_FLAG_FLIP_X);
+					else RenderTools()->SelectSprite(SPRITE_FLAG_RED, SPRITE_FLAG_FLIP_X);
 					
-					float size = 56.0f;
-					Graphics()->QuadsDrawTL(x-56, y-16, size/2, size);
+					float Size = 56.0f;
+					IGraphics::CQuadItem QuadItem(x-56, y-16, Size/2, Size);
+					Graphics()->QuadsDrawTL(&QuadItem, 1);
 					Graphics()->QuadsEnd();				
 				}
 			}				
 			
 			// render killer tee
 			x -= 24.0f;
-			RenderTools()->RenderTee(ANIMSTATE::get_idle(), &gameclient.clients[killmsgs[r].killer].render_info, EMOTE_ANGRY, vec2(1,0), vec2(x, y+28));
+			RenderTools()->RenderTee(CAnimState::GetIdle(), &m_pClient->m_aClients[m_aKillmsgs[r].m_Killer].m_RenderInfo, EMOTE_ANGRY, vec2(1,0), vec2(x, y+28));
 			x -= 32.0f;
 
 			// render killer name
-			x -= killername_w;
-			gfx_text(0, x, y, font_size, gameclient.clients[killmsgs[r].killer].name, -1);
+			x -= KillerNameW;
+			TextRender()->Text(0, x, y, FontSize, m_pClient->m_aClients[m_aKillmsgs[r].m_Killer].m_aName, -1);
 		}
 
 		y += 44;
diff --git a/src/game/client/components/killmessages.h b/src/game/client/components/killmessages.h
new file mode 100644
index 00000000..720b10ae
--- /dev/null
+++ b/src/game/client/components/killmessages.h
@@ -0,0 +1,31 @@
+#ifndef GAME_CLIENT_COMPONENTS_KILLMESSAGES_H
+#define GAME_CLIENT_COMPONENTS_KILLMESSAGES_H
+#include <game/client/component.h>
+
+class CKillMessages : public CComponent
+{
+public:
+	// kill messages
+	struct CKillMsg
+	{
+		int m_Weapon;
+		int m_Victim;
+		int m_Killer;
+		int m_ModeSpecial; // for CTF, if the guy is carrying a flag for example
+		int m_Tick;
+	};
+	
+	enum
+	{
+		MAX_KILLMSGS = 5,
+	};
+
+	CKillMsg m_aKillmsgs[MAX_KILLMSGS];
+	int m_KillmsgCurrent;
+
+	virtual void OnReset();
+	virtual void OnRender();
+	virtual void OnMessage(int MsgType, void *pRawMsg);
+};
+
+#endif
diff --git a/src/game/client/components/killmessages.hpp b/src/game/client/components/killmessages.hpp
deleted file mode 100644
index f29e0bdf..00000000
--- a/src/game/client/components/killmessages.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include <game/client/component.hpp>
-
-class KILLMESSAGES : public COMPONENT
-{
-public:
-	// kill messages
-	struct KILLMSG
-	{
-		int weapon;
-		int victim;
-		int killer;
-		int mode_special; // for CTF, if the guy is carrying a flag for example
-		int tick;
-	};
-
-	static const int killmsg_max = 5;
-	KILLMSG killmsgs[killmsg_max];
-	int killmsg_current;
-
-	virtual void on_reset();
-	virtual void on_render();
-	virtual void on_message(int msgtype, void *rawmsg);
-};
-
diff --git a/src/game/client/components/mapimages.cpp b/src/game/client/components/mapimages.cpp
index 51194853..9be450d1 100644
--- a/src/game/client/components/mapimages.cpp
+++ b/src/game/client/components/mapimages.cpp
@@ -1,45 +1,48 @@
-#include <engine/client/graphics.h>
-#include <game/client/component.hpp>
-#include <game/mapitems.hpp>
+#include <engine/graphics.h>
+#include <engine/map.h>
+#include <game/client/component.h>
+#include <game/mapitems.h>
 
-#include "mapimages.hpp"
+#include "mapimages.h"
 
-MAPIMAGES::MAPIMAGES()
+CMapImages::CMapImages()
 {
-	count = 0;
+	m_Count = 0;
 }
 
-void MAPIMAGES::on_mapload()
+void CMapImages::OnMapLoad()
 {
+	IMap *pMap = Kernel()->RequestInterface<IMap>();
+	
 	// unload all textures
-	for(int i = 0; i < count; i++)
+	for(int i = 0; i < m_Count; i++)
 	{
-		Graphics()->UnloadTexture(textures[i]);
-		textures[i] = -1;
+		Graphics()->UnloadTexture(m_aTextures[i]);
+		m_aTextures[i] = -1;
 	}
-	count = 0;
+	m_Count = 0;
 
-	int start;
-	map_get_type(MAPITEMTYPE_IMAGE, &start, &count);
+	int Start;
+	pMap->GetType(MAPITEMTYPE_IMAGE, &Start, &m_Count);
 	
 	// load new textures
-	for(int i = 0; i < count; i++)
+	for(int i = 0; i < m_Count; i++)
 	{
-		textures[i] = 0;
+		m_aTextures[i] = 0;
 		
-		MAPITEM_IMAGE *img = (MAPITEM_IMAGE *)map_get_item(start+i, 0, 0);
-		if(img->external)
+		CMapItemImage *pImg = (CMapItemImage *)pMap->GetItem(Start+i, 0, 0);
+		if(pImg->m_External)
 		{
-			char buf[256];
-			char *name = (char *)map_get_data(img->image_name);
-			str_format(buf, sizeof(buf), "mapres/%s.png", name);
-			textures[i] = Graphics()->LoadTexture(buf, IMG_AUTO, 0);
+			char Buf[256];
+			char *pName = (char *)pMap->GetData(pImg->m_ImageName);
+			str_format(Buf, sizeof(Buf), "mapres/%s.png", pName);
+			m_aTextures[i] = Graphics()->LoadTexture(Buf, CImageInfo::FORMAT_AUTO, 0);
 		}
 		else
 		{
-			void *data = map_get_data(img->image_data);
-			textures[i] = Graphics()->LoadTextureRaw(img->width, img->height, IMG_RGBA, data, IMG_RGBA, 0);
-			map_unload_data(img->image_data);
+			void *pData = pMap->GetData(pImg->m_ImageData);
+			m_aTextures[i] = Graphics()->LoadTextureRaw(pImg->m_Width, pImg->m_Height, CImageInfo::FORMAT_RGBA, pData, CImageInfo::FORMAT_RGBA, 0);
+			pMap->UnloadData(pImg->m_ImageData);
 		}
 	}
 }
diff --git a/src/game/client/components/mapimages.h b/src/game/client/components/mapimages.h
new file mode 100644
index 00000000..2ef5fc32
--- /dev/null
+++ b/src/game/client/components/mapimages.h
@@ -0,0 +1,18 @@
+#ifndef GAME_CLIENT_COMPONENTS_MAPIMAGES_H
+#define GAME_CLIENT_COMPONENTS_MAPIMAGES_H
+#include <game/client/component.h>
+
+class CMapImages : public CComponent
+{	
+	int m_aTextures[64];
+	int m_Count;
+public:
+	CMapImages();
+	
+	int Get(int Index) const { return m_aTextures[Index]; }
+	int Num() const { return m_Count; }
+
+	virtual void OnMapLoad();
+};
+
+#endif
diff --git a/src/game/client/components/mapimages.hpp b/src/game/client/components/mapimages.hpp
deleted file mode 100644
index cba46033..00000000
--- a/src/game/client/components/mapimages.hpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <game/client/component.hpp>
-
-class MAPIMAGES : public COMPONENT
-{	
-	int textures[64];
-	int count;
-public:
-	MAPIMAGES();
-	
-	int get(int index) const { return textures[index]; }
-	int num() const { return count; }
-
-	virtual void on_mapload();
-};
-
diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp
index 75f91521..202ea2da 100644
--- a/src/game/client/components/maplayers.cpp
+++ b/src/game/client/components/maplayers.cpp
@@ -1,167 +1,192 @@
-#include <engine/client/graphics.h>
+#include <stdio.h>
+#include <engine/graphics.h>
+#include <engine/keys.h> //temp
+#include <engine/shared/config.h>
 
-#include <game/layers.hpp>
-#include <game/client/gameclient.hpp>
-#include <game/client/component.hpp>
-#include <game/client/render.hpp>
+#include <game/layers.h>
+#include <game/client/gameclient.h>
+#include <game/client/component.h>
+#include <game/client/render.h>
 
-#include <game/client/components/camera.hpp>
-#include <game/client/components/mapimages.hpp>
+#include <game/client/components/camera.h>
+#include <game/client/components/mapimages.h>
 
 
-#include "maplayers.hpp"
+#include "maplayers.h"
 
-MAPLAYERS::MAPLAYERS(int t)
+CMapLayers::CMapLayers(int t)
 {
-	type = t;
+	m_Type = t;
+	m_pLayers = 0;
 }
 
+void CMapLayers::OnInit()
+{
+	m_pLayers = Layers();
+}
 
-void MAPLAYERS::mapscreen_to_group(float center_x, float center_y, MAPITEM_GROUP *group)
+
+void CMapLayers::MapScreenToGroup(float CenterX, float CenterY, CMapItemGroup *pGroup)
 {
-	float points[4];
-	RenderTools()->mapscreen_to_world(center_x, center_y, group->parallax_x/100.0f, group->parallax_y/100.0f,
-		group->offset_x, group->offset_y, Graphics()->ScreenAspect(), 1.0f, points);
-	Graphics()->MapScreen(points[0], points[1], points[2], points[3]);
+	float Points[4];
+	RenderTools()->MapscreenToWorld(CenterX, CenterY, pGroup->m_ParallaxX/100.0f, pGroup->m_ParallaxY/100.0f,
+		pGroup->m_OffsetX, pGroup->m_OffsetY, Graphics()->ScreenAspect(), 1.0f, Points);
+	Graphics()->MapScreen(Points[0], Points[1], Points[2], Points[3]);
 }
 
-void MAPLAYERS::envelope_eval(float time_offset, int env, float *channels, void *user)
+void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void *pUser)
 {
-	MAPLAYERS *pThis = (MAPLAYERS *)user;
-	channels[0] = 0;
-	channels[1] = 0;
-	channels[2] = 0;
-	channels[3] = 0;
+	CMapLayers *pThis = (CMapLayers *)pUser;
+	pChannels[0] = 0;
+	pChannels[1] = 0;
+	pChannels[2] = 0;
+	pChannels[3] = 0;
 
-	ENVPOINT *points;
+	CEnvPoint *pPoints;
 
 	{
-		int start, num;
-		map_get_type(MAPITEMTYPE_ENVPOINTS, &start, &num);
-		if(num)
-			points = (ENVPOINT *)map_get_item(start, 0, 0);
+		int Start, Num;
+		pThis->m_pLayers->Map()->GetType(MAPITEMTYPE_ENVPOINTS, &Start, &Num);
+		if(Num)
+			pPoints = (CEnvPoint *)pThis->m_pLayers->Map()->GetItem(Start, 0, 0);
 	}
 	
-	int start, num;
-	map_get_type(MAPITEMTYPE_ENVELOPE, &start, &num);
+	int Start, Num;
+	pThis->m_pLayers->Map()->GetType(MAPITEMTYPE_ENVELOPE, &Start, &Num);
 	
-	if(env >= num)
+	if(Env >= Num)
 		return;
 	
-	MAPITEM_ENVELOPE *item = (MAPITEM_ENVELOPE *)map_get_item(start+env, 0, 0);
-	pThis->RenderTools()->render_eval_envelope(points+item->start_point, item->num_points, 4, client_localtime()+time_offset, channels);
+	CMapItemEnvelope *pItem = (CMapItemEnvelope *)pThis->m_pLayers->Map()->GetItem(Start+Env, 0, 0);
+	pThis->RenderTools()->RenderEvalEnvelope(pPoints+pItem->m_StartPoint, pItem->m_NumPoints, 4, pThis->Client()->LocalTime()+TimeOffset, pChannels);
 }
 
-void MAPLAYERS::on_render()
+void CMapLayers::OnRender()
 {
-	if(client_state() != CLIENTSTATE_ONLINE && client_state() != CLIENTSTATE_DEMOPLAYBACK)
+	if(Client()->State() != IClient::STATE_ONLINE && Client()->State() != IClient::STATE_DEMOPLAYBACK)
 		return;
 	
-	CUIRect screen;
-	Graphics()->GetScreen(&screen.x, &screen.y, &screen.w, &screen.h);
+	CUIRect Screen;
+	Graphics()->GetScreen(&Screen.x, &Screen.y, &Screen.w, &Screen.h);
 	
-	vec2 center = gameclient.camera->center;
+	vec2 Center = m_pClient->m_pCamera->m_Center;
 	//float center_x = gameclient.camera->center.x;
 	//float center_y = gameclient.camera->center.y;
 	
-	bool passed_gamelayer = false;
+	bool PassedGameLayer = false;
 	
-	for(int g = 0; g < layers_num_groups(); g++)
+	for(int g = 0; g < m_pLayers->NumGroups(); g++)
 	{
-		MAPITEM_GROUP *group = layers_get_group(g);
+		CMapItemGroup *pGroup = m_pLayers->GetGroup(g);
 		
-		if(!config.gfx_noclip && group->version >= 2 && group->use_clipping)
+		if(!g_Config.m_GfxNoclip && pGroup->m_Version >= 2 && pGroup->m_UseClipping)
 		{
 			// set clipping
-			float points[4];
-			mapscreen_to_group(center.x, center.y, layers_game_group());
-			Graphics()->GetScreen(&points[0], &points[1], &points[2], &points[3]);
-			float x0 = (group->clip_x - points[0]) / (points[2]-points[0]);
-			float y0 = (group->clip_y - points[1]) / (points[3]-points[1]);
-			float x1 = ((group->clip_x+group->clip_w) - points[0]) / (points[2]-points[0]);
-			float y1 = ((group->clip_y+group->clip_h) - points[1]) / (points[3]-points[1]);
+			float Points[4];
+			MapScreenToGroup(Center.x, Center.y, m_pLayers->GameGroup());
+			Graphics()->GetScreen(&Points[0], &Points[1], &Points[2], &Points[3]);
+			float x0 = (pGroup->m_ClipX - Points[0]) / (Points[2]-Points[0]);
+			float y0 = (pGroup->m_ClipY - Points[1]) / (Points[3]-Points[1]);
+			float x1 = ((pGroup->m_ClipX+pGroup->m_ClipW) - Points[0]) / (Points[2]-Points[0]);
+			float y1 = ((pGroup->m_ClipY+pGroup->m_ClipH) - Points[1]) / (Points[3]-Points[1]);
 			
 			Graphics()->ClipEnable((int)(x0*Graphics()->ScreenWidth()), (int)(y0*Graphics()->ScreenHeight()),
 				(int)((x1-x0)*Graphics()->ScreenWidth()), (int)((y1-y0)*Graphics()->ScreenHeight()));
 		}		
 		
-		mapscreen_to_group(center.x, center.y, group);
+		MapScreenToGroup(Center.x, Center.y, pGroup);
 		
-		for(int l = 0; l < group->num_layers; l++)
+		for(int l = 0; l < pGroup->m_NumLayers; l++)
 		{
-			MAPITEM_LAYER *layer = layers_get_layer(group->start_layer+l);
-			bool render = false;
-			bool is_game_layer = false;
+			CMapItemLayer *pLayer = m_pLayers->GetLayer(pGroup->m_StartLayer+l);
+			bool Render = false;
+			bool IsGameLayer = false;
 			
-			if(layer == (MAPITEM_LAYER*)layers_game_layer())
+			if(pLayer == (CMapItemLayer*)m_pLayers->GameLayer())
 			{
-				is_game_layer = true;
-				passed_gamelayer = 1;
+				IsGameLayer = true;
+				PassedGameLayer = 1;
 			}
 			
 			// skip rendering if detail layers if not wanted
-			if(layer->flags&LAYERFLAG_DETAIL && !config.gfx_high_detail && !is_game_layer)
+			if(pLayer->m_Flags&LAYERFLAG_DETAIL && !g_Config.m_GfxHighDetail && !IsGameLayer)
 				continue;
 				
-			if(type == -1)
-				render = true;
-			else if(type == 0)
+			if(m_Type == -1)
+				Render = true;
+			else if(m_Type == 0)
 			{
-				if(passed_gamelayer)
+				if(PassedGameLayer)
 					return;
-				render = true;
+				Render = true;
 			}
 			else
 			{
-				if(passed_gamelayer && !is_game_layer)
-					render = true;
+				if(PassedGameLayer && !IsGameLayer)
+					Render = true;
 			}
 			
-			if(render && !is_game_layer)
+			if(pLayer->m_Type == LAYERTYPE_TILES && Input()->KeyPressed(KEY_KP0))
+			{
+				CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer;
+				CTile *pTiles = (CTile *)m_pLayers->Map()->GetData(pTMap->m_Data);
+				char buf[256];
+				str_format(buf, sizeof(buf), "%d%d_%dx%d", g, l, pTMap->m_Width, pTMap->m_Height);
+				FILE *f = fopen(buf, "w");
+				for(int y = 0; y < pTMap->m_Height; y++)
+				{
+					for(int x = 0; x < pTMap->m_Width; x++)
+						fprintf(f, "%d,", pTiles[y*pTMap->m_Width + x].m_Index);
+					fprintf(f, "\n");
+				}
+				fclose(f);
+			}			
+			
+			if(Render && !IsGameLayer)
 			{
 				//layershot_begin();
 				
-				if(layer->type == LAYERTYPE_TILES)
+				if(pLayer->m_Type == LAYERTYPE_TILES)
 				{
-					MAPITEM_LAYER_TILEMAP *tmap = (MAPITEM_LAYER_TILEMAP *)layer;
-					if(tmap->image == -1)
+					CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer;
+					if(pTMap->m_Image == -1)
 						Graphics()->TextureSet(-1);
 					else
-						Graphics()->TextureSet(gameclient.mapimages->get(tmap->image));
+						Graphics()->TextureSet(m_pClient->m_pMapimages->Get(pTMap->m_Image));
 						
-					TILE *tiles = (TILE *)map_get_data(tmap->data);
+					CTile *pTiles = (CTile *)m_pLayers->Map()->GetData(pTMap->m_Data);
 					Graphics()->BlendNone();
-					RenderTools()->render_tilemap(tiles, tmap->width, tmap->height, 32.0f, vec4(1,1,1,1), TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_OPAQUE);
+					RenderTools()->RenderTilemap(pTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, vec4(1,1,1,1), TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_OPAQUE);
 					Graphics()->BlendNormal();
-					RenderTools()->render_tilemap(tiles, tmap->width, tmap->height, 32.0f, vec4(1,1,1,1), TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_TRANSPARENT);
+					RenderTools()->RenderTilemap(pTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, vec4(1,1,1,1), TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_TRANSPARENT);
 				}
-				else if(layer->type == LAYERTYPE_QUADS)
+				else if(pLayer->m_Type == LAYERTYPE_QUADS)
 				{
-					MAPITEM_LAYER_QUADS *qlayer = (MAPITEM_LAYER_QUADS *)layer;
-					if(qlayer->image == -1)
+					CMapItemLayerQuads *pQLayer = (CMapItemLayerQuads *)pLayer;
+					if(pQLayer->m_Image == -1)
 						Graphics()->TextureSet(-1);
 					else
-						Graphics()->TextureSet(gameclient.mapimages->get(qlayer->image));
+						Graphics()->TextureSet(m_pClient->m_pMapimages->Get(pQLayer->m_Image));
 
-					QUAD *quads = (QUAD *)map_get_data_swapped(qlayer->data);
+					CQuad *pQuads = (CQuad *)m_pLayers->Map()->GetDataSwapped(pQLayer->m_Data);
 					
 					Graphics()->BlendNone();
-					RenderTools()->render_quads(quads, qlayer->num_quads, LAYERRENDERFLAG_OPAQUE, envelope_eval, this);
+					RenderTools()->RenderQuads(pQuads, pQLayer->m_NumQuads, LAYERRENDERFLAG_OPAQUE, EnvelopeEval, this);
 					Graphics()->BlendNormal();
-					RenderTools()->render_quads(quads, qlayer->num_quads, LAYERRENDERFLAG_TRANSPARENT, envelope_eval, this);
+					RenderTools()->RenderQuads(pQuads, pQLayer->m_NumQuads, LAYERRENDERFLAG_TRANSPARENT, EnvelopeEval, this);
 				}
 				
 				//layershot_end();	
 			}
 		}
-		if(!config.gfx_noclip)
+		if(!g_Config.m_GfxNoclip)
 			Graphics()->ClipDisable();
 	}
 	
-	if(!config.gfx_noclip)
+	if(!g_Config.m_GfxNoclip)
 		Graphics()->ClipDisable();
 	
 	// reset the screen like it was before
-	Graphics()->MapScreen(screen.x, screen.y, screen.w, screen.h);
+	Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);
 }
 
diff --git a/src/game/client/components/maplayers.h b/src/game/client/components/maplayers.h
new file mode 100644
index 00000000..9f70d9cb
--- /dev/null
+++ b/src/game/client/components/maplayers.h
@@ -0,0 +1,24 @@
+#ifndef GAME_CLIENT_COMPONENTS_MAPLAYERS_H
+#define GAME_CLIENT_COMPONENTS_MAPLAYERS_H
+#include <game/client/component.h>
+
+class CMapLayers : public CComponent
+{	
+	CLayers *m_pLayers;	// todo refactor: maybe remove it and access it through client*
+	int m_Type;
+
+	void MapScreenToGroup(float CenterX, float CenterY, CMapItemGroup *pGroup);
+	static void EnvelopeEval(float TimeOffset, int Env, float *pChannels, void *pUser);
+public:
+	enum
+	{
+		TYPE_BACKGROUND=0,
+		TYPE_FOREGROUND,
+	};
+
+	CMapLayers(int Type);
+	virtual void OnInit();
+	virtual void OnRender();
+};
+
+#endif
diff --git a/src/game/client/components/maplayers.hpp b/src/game/client/components/maplayers.hpp
deleted file mode 100644
index c8b154b2..00000000
--- a/src/game/client/components/maplayers.hpp
+++ /dev/null
@@ -1,19 +0,0 @@
-#include <game/client/component.hpp>
-
-class MAPLAYERS : public COMPONENT
-{	
-	int type;
-
-	void mapscreen_to_group(float center_x, float center_y, MAPITEM_GROUP *group);
-	static void envelope_eval(float time_offset, int env, float *channels, void *user);
-public:
-	enum
-	{
-		TYPE_BACKGROUND=0,
-		TYPE_FOREGROUND,
-	};
-
-	MAPLAYERS(int type);
-	virtual void on_render();
-};
-
diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp
index 5f1bbf42..76ee2e5e 100644
--- a/src/game/client/components/menus.cpp
+++ b/src/game/client/components/menus.cpp
@@ -1,45 +1,45 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <stdio.h>
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
 #include <math.h>
-#include <string.h>
-#include <stdlib.h>
 
 #include <base/system.h>
-#include <base/math.hpp>
-#include <base/vmath.hpp>
+#include <base/math.h>
+#include <base/vmath.h>
 
-#include "menus.hpp"
-#include "skins.hpp"
+#include "menus.h"
+#include "skins.h"
 
-#include <engine/e_client_interface.h>
-#include <engine/client/graphics.h>
+#include <engine/graphics.h>
+#include <engine/textrender.h>
+#include <engine/serverbrowser.h>
+#include <engine/keys.h>
+#include <engine/shared/config.h>
 
-#include <game/version.hpp>
-#include <game/generated/g_protocol.hpp>
+#include <game/version.h>
+#include <game/generated/protocol.h>
 
-#include <game/generated/gc_data.hpp>
-#include <game/client/gameclient.hpp>
-#include <game/client/lineinput.hpp>
-#include <game/localization.hpp>
+#include <game/generated/client_data.h>
+#include <game/client/gameclient.h>
+#include <game/client/lineinput.h>
+#include <game/localization.h>
 #include <mastersrv/mastersrv.h>
 
-vec4 MENUS::gui_color;
-vec4 MENUS::color_tabbar_inactive_outgame;
-vec4 MENUS::color_tabbar_active_outgame;
-vec4 MENUS::color_tabbar_inactive;
-vec4 MENUS::color_tabbar_active;
-vec4 MENUS::color_tabbar_inactive_ingame;
-vec4 MENUS::color_tabbar_active_ingame;
+vec4 CMenus::ms_GuiColor;
+vec4 CMenus::ms_ColorTabbarInactiveOutgame;
+vec4 CMenus::ms_ColorTabbarActiveOutgame;
+vec4 CMenus::ms_ColorTabbarInactive;
+vec4 CMenus::ms_ColorTabbarActive;
+vec4 CMenus::ms_ColorTabbarInactiveIngame;
+vec4 CMenus::ms_ColorTabbarActiveIngame;
 
 
-float MENUS::button_height = 25.0f;
-float MENUS::listheader_height = 17.0f;
-float MENUS::fontmod_height = 0.8f;
+float CMenus::ms_ButtonHeight = 25.0f;
+float CMenus::ms_ListheaderHeight = 17.0f;
+float CMenus::ms_FontmodHeight = 0.8f;
 
-INPUT_EVENT MENUS::inputevents[MAX_INPUTEVENTS];
-int MENUS::num_inputevents;
+IInput::CEvent CMenus::m_aInputEvents[MAX_INPUTEVENTS];
+int CMenus::m_NumInputEvents;
 
-inline float hue_to_rgb(float v1, float v2, float h)
+inline float HueToRgb(float v1, float v2, float h)
 {
    if(h < 0) h += 1;
    if(h > 1) h -= 1;
@@ -49,53 +49,54 @@ inline float hue_to_rgb(float v1, float v2, float h)
    return v1;
 }
 
-inline vec3 hsl_to_rgb(vec3 in)
+inline vec3 HslToRgb(vec3 In)
 {
 	float v1, v2;
-	vec3 out;
+	vec3 Out;
 
-	if(in.s == 0)
+	if(In.s == 0)
 	{
-		out.r = in.l;
-		out.g = in.l;
-		out.b = in.l;
+		Out.r = In.l;
+		Out.g = In.l;
+		Out.b = In.l;
 	}
 	else
 	{
-		if(in.l < 0.5f) 
-			v2 = in.l * (1 + in.s);
+		if(In.l < 0.5f) 
+			v2 = In.l * (1 + In.s);
 		else           
-			v2 = (in.l+in.s) - (in.s*in.l);
+			v2 = (In.l+In.s) - (In.s*In.l);
 
-		v1 = 2 * in.l - v2;
+		v1 = 2 * In.l - v2;
 
-		out.r = hue_to_rgb(v1, v2, in.h + (1.0f/3.0f));
-		out.g = hue_to_rgb(v1, v2, in.h);
-		out.b = hue_to_rgb(v1, v2, in.h - (1.0f/3.0f));
+		Out.r = HueToRgb(v1, v2, In.h + (1.0f/3.0f));
+		Out.g = HueToRgb(v1, v2, In.h);
+		Out.b = HueToRgb(v1, v2, In.h - (1.0f/3.0f));
 	} 
 
-	return out;
+	return Out;
 }
 
 
-MENUS::MENUS()
+CMenus::CMenus()
 {
-	popup = POPUP_NONE;
-	active_page = PAGE_INTERNET;
-	game_page = PAGE_GAME;
+	m_Popup = POPUP_NONE;
+	m_ActivePage = PAGE_INTERNET;
+	m_GamePage = PAGE_GAME;
 	
-	need_restart = false;
-	need_sendinfo = false;
-	menu_active = true;
+	m_NeedRestart = false;
+	m_NeedSendinfo = false;
+	m_MenuActive = true;
+	m_UseMouseButtons = true;
 	
-	escape_pressed = false;
-	enter_pressed = false;
-	num_inputevents = 0;
+	m_EscapePressed = false;
+	m_EnterPressed = false;
+	m_NumInputEvents = 0;
 	
-	last_input = time_get();
+	m_LastInput = time_get();
 }
 
-vec4 MENUS::button_color_mul(const void *pID)
+vec4 CMenus::ButtonColorMul(const void *pID)
 {
 	if(UI()->ActiveItem() == pID)
 		return vec4(1,1,1,0.5f);
@@ -104,69 +105,69 @@ vec4 MENUS::button_color_mul(const void *pID)
 	return vec4(1,1,1,1);
 }
 
-int MENUS::DoButton_BrowseIcon(int What, const CUIRect *pRect)
+int CMenus::DoButton_BrowseIcon(int What, const CUIRect *pRect)
 {
-	Graphics()->TextureSet(data->images[IMAGE_BROWSEICONS].id);
+	Graphics()->TextureSet(g_pData->m_aImages[IMAGE_BROWSEICONS].m_Id);
 	
 	Graphics()->QuadsBegin();
-	RenderTools()->select_sprite(What);
-	Graphics()->QuadsDrawTL(pRect->x, pRect->y, pRect->w, pRect->h);
+	RenderTools()->SelectSprite(What);
+	IGraphics::CQuadItem QuadItem(pRect->x, pRect->y, pRect->w, pRect->h);
+	Graphics()->QuadsDrawTL(&QuadItem, 1);
 	Graphics()->QuadsEnd();
 	
 	return 0;
 }
 
 
-int MENUS::DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
+int CMenus::DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
 {
-	RenderTools()->DrawUIRect(pRect, vec4(1,1,1,0.5f)*button_color_mul(pID), CUI::CORNER_ALL, 5.0f);
-	UI()->DoLabel(pRect, pText, pRect->h*fontmod_height, 0);
+	RenderTools()->DrawUIRect(pRect, vec4(1,1,1,0.5f)*ButtonColorMul(pID), CUI::CORNER_ALL, 5.0f);
+	UI()->DoLabel(pRect, pText, pRect->h*ms_FontmodHeight, 0);
 	return UI()->DoButtonLogic(pID, pText, Checked, pRect);
 }
 
-int MENUS::DoButton_KeySelect(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
+void CMenus::DoButton_KeySelect(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
 {
-	RenderTools()->DrawUIRect(pRect, vec4(1,1,1,0.5f)*button_color_mul(pID), CUI::CORNER_ALL, 5.0f);
-	UI()->DoLabel(pRect, pText, pRect->h*fontmod_height, 0);
-	return UI()->DoButtonLogic(pID, pText, Checked, pRect);
+	RenderTools()->DrawUIRect(pRect, vec4(1,1,1,0.5f)*ButtonColorMul(pID), CUI::CORNER_ALL, 5.0f);
+	UI()->DoLabel(pRect, pText, pRect->h*ms_FontmodHeight, 0);
 }
 
-int MENUS::DoButton_MenuTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners)
+int CMenus::DoButton_MenuTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners)
 {
 	vec4 ColorMod(1,1,1,1);
 	
 	if(Checked)
-		RenderTools()->DrawUIRect(pRect, color_tabbar_active, Corners, 10.0f);
+		RenderTools()->DrawUIRect(pRect, ms_ColorTabbarActive, Corners, 10.0f);
 	else
-		RenderTools()->DrawUIRect(pRect, color_tabbar_inactive, Corners, 10.0f);
-	UI()->DoLabel(pRect, pText, pRect->h*fontmod_height, 0);
+		RenderTools()->DrawUIRect(pRect, ms_ColorTabbarInactive, Corners, 10.0f);
+	UI()->DoLabel(pRect, pText, pRect->h*ms_FontmodHeight, 0);
 	
 	return UI()->DoButtonLogic(pID, pText, Checked, pRect);
 }
 
 
-int MENUS::DoButton_SettingsTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
+int CMenus::DoButton_SettingsTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
 {
 	if(Checked)
-		RenderTools()->DrawUIRect(pRect, color_tabbar_active, CUI::CORNER_R, 10.0f);
+		RenderTools()->DrawUIRect(pRect, ms_ColorTabbarActive, CUI::CORNER_R, 10.0f);
 	else
-		RenderTools()->DrawUIRect(pRect, color_tabbar_inactive, CUI::CORNER_R, 10.0f);
-	UI()->DoLabel(pRect, pText, pRect->h*fontmod_height, 0);
+		RenderTools()->DrawUIRect(pRect, ms_ColorTabbarInactive, CUI::CORNER_R, 10.0f);
+	UI()->DoLabel(pRect, pText, pRect->h*ms_FontmodHeight, 0);
 	return UI()->DoButtonLogic(pID, pText, Checked, pRect);
 }
 
-int MENUS::DoButton_GridHeader(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
-//void MENUS::ui_draw_grid_header(const void *id, const char *text, int checked, const CUIRect *r, const void *extra)
+int CMenus::DoButton_GridHeader(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
+//void CMenus::ui_draw_grid_header(const void *id, const char *text, int checked, const CUIRect *r, const void *extra)
 {
 	if(Checked)
 		RenderTools()->DrawUIRect(pRect, vec4(1,1,1,0.5f), CUI::CORNER_T, 5.0f);
 	CUIRect t;
 	pRect->VSplitLeft(5.0f, 0, &t);
-	UI()->DoLabel(&t, pText, pRect->h*fontmod_height, -1);
+	UI()->DoLabel(&t, pText, pRect->h*ms_FontmodHeight, -1);
 	return UI()->DoButtonLogic(pID, pText, Checked, pRect);
 }
 
-int MENUS::DoButton_ListRow(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
+int CMenus::DoButton_ListRow(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
 {
 	if(Checked)
 	{
@@ -174,12 +175,12 @@ int MENUS::DoButton_ListRow(const void *pID, const char *pText, int Checked, con
 		sr.Margin(1.5f, &sr);
 		RenderTools()->DrawUIRect(&sr, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 4.0f);
 	}
-	UI()->DoLabel(pRect, pText, pRect->h*fontmod_height, -1);
+	UI()->DoLabel(pRect, pText, pRect->h*ms_FontmodHeight, -1);
 	return UI()->DoButtonLogic(pID, pText, Checked, pRect);
 }
 
-int MENUS::DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect)
-//void MENUS::ui_draw_checkbox_common(const void *id, const char *text, const char *boxtext, const CUIRect *r, const void *extra)
+int CMenus::DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect)
+//void CMenus::ui_draw_checkbox_common(const void *id, const char *text, const char *boxtext, const CUIRect *r, const void *extra)
 {
 	CUIRect c = *pRect;
 	CUIRect t = *pRect;
@@ -189,57 +190,59 @@ int MENUS::DoButton_CheckBox_Common(const void *pID, const char *pText, const ch
 	t.VSplitLeft(5.0f, 0, &t);
 	
 	c.Margin(2.0f, &c);
-	RenderTools()->DrawUIRect(&c, vec4(1,1,1,0.25f)*button_color_mul(pID), CUI::CORNER_ALL, 3.0f);
+	RenderTools()->DrawUIRect(&c, vec4(1,1,1,0.25f)*ButtonColorMul(pID), CUI::CORNER_ALL, 3.0f);
 	c.y += 2;
-	UI()->DoLabel(&c, pBoxText, pRect->h*fontmod_height*0.6f, 0);
-	UI()->DoLabel(&t, pText, pRect->h*fontmod_height*0.8f, -1);
+	UI()->DoLabel(&c, pBoxText, pRect->h*ms_FontmodHeight*0.6f, 0);
+	UI()->DoLabel(&t, pText, pRect->h*ms_FontmodHeight*0.8f, -1);
 	return UI()->DoButtonLogic(pID, pText, 0, pRect);
 }
 
-int MENUS::DoButton_CheckBox(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
+int CMenus::DoButton_CheckBox(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
 {
 	return DoButton_CheckBox_Common(pID, pText, Checked?"X":"", pRect);
 }
 
 
-int MENUS::DoButton_CheckBox_Number(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
+int CMenus::DoButton_CheckBox_Number(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
 {
-	char buf[16];
-	str_format(buf, sizeof(buf), "%d", Checked);
-	return DoButton_CheckBox_Common(pID, pText, buf, pRect);
+	char aBuf[16];
+	str_format(aBuf, sizeof(aBuf), "%d", Checked);
+	return DoButton_CheckBox_Common(pID, pText, aBuf, pRect);
 }
 
-int MENUS::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, bool Hidden)
+int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, bool Hidden, int Corners)
 {
     int Inside = UI()->MouseInside(pRect);
-	int ReturnValue = 0;
-	static int AtIndex = 0;
+	bool ReturnValue = false;
+	static int s_AtIndex = 0;
 
 	if(UI()->LastActiveItem() == pID)
 	{
-		int Len = strlen(pStr);
+		int Len = str_length(pStr);
+		if(Len == 0)
+			s_AtIndex = 0;
 			
 		if(Inside && UI()->MouseButton(0))
 		{
-			int mx_rel = (int)(UI()->MouseX() - pRect->x);
+			int MxRel = (int)(UI()->MouseX() - pRect->x);
 
-			for (int i = 1; i <= Len; i++)
+			for(int i = 1; i <= Len; i++)
 			{
-				if (gfx_text_width(0, FontSize, pStr, i) + 10 > mx_rel)
+				if(TextRender()->TextWidth(0, FontSize, pStr, i) + 10 > MxRel)
 				{
-					AtIndex = i - 1;
+					s_AtIndex = i - 1;
 					break;
 				}
 
-				if (i == Len)
-					AtIndex = Len;
+				if(i == Len)
+					s_AtIndex = Len;
 			}
 		}
 
-		for(int i = 0; i < num_inputevents; i++)
+		for(int i = 0; i < m_NumInputEvents; i++)
 		{
-			Len = strlen(pStr);
-			LINEINPUT::manipulate(inputevents[i], pStr, StrSize, &Len, &AtIndex);
+			Len = str_length(pStr);
+			ReturnValue |= CLineInput::Manipulate(m_aInputEvents[i], pStr, StrSize, &Len, &s_AtIndex);
 		}
 	}
 
@@ -264,35 +267,41 @@ int MENUS::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSi
 		UI()->SetHotItem(pID);
 
 	CUIRect Textbox = *pRect;
-	RenderTools()->DrawUIRect(&Textbox, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 5.0f);
-	Textbox.VMargin(5.0f, &Textbox);
+	RenderTools()->DrawUIRect(&Textbox, vec4(1, 1, 1, 0.5f), Corners, 3.0f);
+	Textbox.VMargin(3.0f, &Textbox);
 	
 	const char *pDisplayStr = pStr;
 	char aStars[128];
 	
 	if(Hidden)
 	{
-		unsigned s = strlen(pStr);
+		unsigned s = str_length(pStr);
 		if(s >= sizeof(aStars))
 			s = sizeof(aStars)-1;
-		memset(aStars, '*', s);
+		for(unsigned int i = 0; i < s; ++i)
+			aStars[i] = '*';
 		aStars[s] = 0;
 		pDisplayStr = aStars;
 	}
 
 	UI()->DoLabel(&Textbox, pDisplayStr, FontSize, -1);
 	
-	if (UI()->LastActiveItem() == pID && !JustGotActive)
+	//TODO: make it blink
+	if(UI()->LastActiveItem() == pID && !JustGotActive)
 	{
-		float w = gfx_text_width(0, FontSize, pDisplayStr, AtIndex);
+		float w = TextRender()->TextWidth(0, FontSize, pDisplayStr, s_AtIndex);
+		Textbox = *pRect;
+		Textbox.VSplitLeft(2.0f, 0, &Textbox);
 		Textbox.x += w*UI()->Scale();
-		UI()->DoLabel(&Textbox, "_", FontSize, -1);
+		Textbox.y -= FontSize/10.f;
+		
+		UI()->DoLabel(&Textbox, "|", FontSize*1.1f, -1);
 	}
 
 	return ReturnValue;
 }
 
-float MENUS::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current)
+float CMenus::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current)
 {
 	CUIRect Handle;
 	static float OffsetY;
@@ -300,7 +309,7 @@ float MENUS::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current)
 
 	Handle.y += (pRect->h-Handle.h)*Current;
 
-	/* logic */
+	// logic
     float ReturnValue = Current;
     int Inside = UI()->MouseInside(&Handle);
 
@@ -309,10 +318,10 @@ float MENUS::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current)
 		if(!UI()->MouseButton(0))
 			UI()->SetActiveItem(0);
 		
-		float min = pRect->y;
-		float max = pRect->h-Handle.h;
-		float cur = UI()->MouseY()-OffsetY;
-		ReturnValue = (cur-min)/max;
+		float Min = pRect->y;
+		float Max = pRect->h-Handle.h;
+		float Cur = UI()->MouseY()-OffsetY;
+		ReturnValue = (Cur-Min)/Max;
 		if(ReturnValue < 0.0f) ReturnValue = 0.0f;
 		if(ReturnValue > 1.0f) ReturnValue = 1.0f;
 	}
@@ -341,14 +350,14 @@ float MENUS::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current)
 
 	Slider = Handle;
 	Slider.Margin(5.0f, &Slider);
-	RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f)*button_color_mul(pID), CUI::CORNER_ALL, 2.5f);
+	RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f)*ButtonColorMul(pID), CUI::CORNER_ALL, 2.5f);
 	
     return ReturnValue;
 }
 
 
 
-float MENUS::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current)
+float CMenus::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current)
 {
 	CUIRect Handle;
 	static float OffsetX;
@@ -356,7 +365,7 @@ float MENUS::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current)
 
 	Handle.x += (pRect->w-Handle.w)*Current;
 
-	/* logic */
+	// logic
     float ReturnValue = Current;
     int Inside = UI()->MouseInside(&Handle);
 
@@ -365,10 +374,10 @@ float MENUS::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current)
 		if(!UI()->MouseButton(0))
 			UI()->SetActiveItem(0);
 		
-		float min = pRect->x;
-		float max = pRect->w-Handle.w;
-		float cur = UI()->MouseX()-OffsetX;
-		ReturnValue = (cur-min)/max;
+		float Min = pRect->x;
+		float Max = pRect->w-Handle.w;
+		float Cur = UI()->MouseX()-OffsetX;
+		ReturnValue = (Cur-Min)/Max;
 		if(ReturnValue < 0.0f) ReturnValue = 0.0f;
 		if(ReturnValue > 1.0f) ReturnValue = 1.0f;
 	}
@@ -397,12 +406,12 @@ float MENUS::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current)
 
 	Slider = Handle;
 	Slider.Margin(5.0f, &Slider);
-	RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f)*button_color_mul(pID), CUI::CORNER_ALL, 2.5f);
+	RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f)*ButtonColorMul(pID), CUI::CORNER_ALL, 2.5f);
 	
     return ReturnValue;
 }
 
-int MENUS::DoKeyReader(void *pID, const CUIRect *pRect, int Key)
+int CMenus::DoKeyReader(void *pID, const CUIRect *pRect, int Key)
 {
 	// process
 	static void *pGrabbedID = 0;
@@ -415,10 +424,10 @@ int MENUS::DoKeyReader(void *pID, const CUIRect *pRect, int Key)
 
 	if(UI()->ActiveItem() == pID)
 	{
-		if(binder.got_key)
+		if(m_Binder.m_GotKey)
 		{
-			NewKey = binder.key.key;
-			binder.got_key = false;
+			NewKey = m_Binder.m_Key.m_Key;
+			m_Binder.m_GotKey = false;
 			UI()->SetActiveItem(0);
 			MouseReleased = false;
 			pGrabbedID = pID;
@@ -428,8 +437,8 @@ int MENUS::DoKeyReader(void *pID, const CUIRect *pRect, int Key)
 	{
 		if(UI()->MouseButton(0) && MouseReleased)
 		{
-			binder.take_key = true;
-			binder.got_key = false;
+			m_Binder.m_TakeKey = true;
+			m_Binder.m_GotKey = false;
 			UI()->SetActiveItem(pID);
 		}
 	}
@@ -445,185 +454,185 @@ int MENUS::DoKeyReader(void *pID, const CUIRect *pRect, int Key)
 		if(Key == 0)
 			DoButton_KeySelect(pID, "", 0, pRect);
 		else
-			DoButton_KeySelect(pID, inp_key_name(Key), 0, pRect);
+			DoButton_KeySelect(pID, Input()->KeyName(Key), 0, pRect);
 	}
 	return NewKey;
 }
 
 
-int MENUS::render_menubar(CUIRect r)
+int CMenus::RenderMenubar(CUIRect r)
 {
-	CUIRect box = r;
-	CUIRect button;
+	CUIRect Box = r;
+	CUIRect Button;
 	
-	int active_page = config.ui_page;
-	int new_page = -1;
+	m_ActivePage = g_Config.m_UiPage;
+	int NewPage = -1;
 	
-	if(client_state() != CLIENTSTATE_OFFLINE)
-		active_page = game_page;
+	if(Client()->State() != IClient::STATE_OFFLINE)
+		m_ActivePage = m_GamePage;
 	
-	if(client_state() == CLIENTSTATE_OFFLINE)
+	if(Client()->State() == IClient::STATE_OFFLINE)
 	{
-		/* offline menus */
+		// offline menus
 		if(0) // this is not done yet
 		{
-			box.VSplitLeft(90.0f, &button, &box);
-			static int news_button=0;
-			if (DoButton_MenuTab(&news_button, localize("News"), active_page==PAGE_NEWS, &button, 0))
-				new_page = PAGE_NEWS;
-			box.VSplitLeft(30.0f, 0, &box); 
+			Box.VSplitLeft(90.0f, &Button, &Box);
+			static int s_NewsButton=0;
+			if (DoButton_MenuTab(&s_NewsButton, Localize("News"), m_ActivePage==PAGE_NEWS, &Button, 0))
+				NewPage = PAGE_NEWS;
+			Box.VSplitLeft(30.0f, 0, &Box); 
 		}
 
-		box.VSplitLeft(100.0f, &button, &box);
-		static int internet_button=0;
-		if(DoButton_MenuTab(&internet_button, localize("Internet"), active_page==PAGE_INTERNET, &button, CUI::CORNER_TL))
+		Box.VSplitLeft(100.0f, &Button, &Box);
+		static int s_InternetButton=0;
+		if(DoButton_MenuTab(&s_InternetButton, Localize("Internet"), m_ActivePage==PAGE_INTERNET, &Button, CUI::CORNER_TL))
 		{
-			client_serverbrowse_refresh(BROWSETYPE_INTERNET);
-			new_page = PAGE_INTERNET;
+			ServerBrowser()->Refresh(IServerBrowser::TYPE_INTERNET);
+			NewPage = PAGE_INTERNET;
 		}
 
-		//box.VSplitLeft(4.0f, 0, &box);
-		box.VSplitLeft(80.0f, &button, &box);
-		static int lan_button=0;
-		if(DoButton_MenuTab(&lan_button, localize("LAN"), active_page==PAGE_LAN, &button, 0))
+		//Box.VSplitLeft(4.0f, 0, &Box);
+		Box.VSplitLeft(80.0f, &Button, &Box);
+		static int s_LanButton=0;
+		if(DoButton_MenuTab(&s_LanButton, Localize("LAN"), m_ActivePage==PAGE_LAN, &Button, 0))
 		{
-			client_serverbrowse_refresh(BROWSETYPE_LAN);
-			new_page = PAGE_LAN;
+			ServerBrowser()->Refresh(IServerBrowser::TYPE_LAN);
+			NewPage = PAGE_LAN;
 		}
 
 		//box.VSplitLeft(4.0f, 0, &box);
-		box.VSplitLeft(110.0f, &button, &box);
-		static int favorites_button=0;
-		if(DoButton_MenuTab(&favorites_button, localize("Favorites"), active_page==PAGE_FAVORITES, &button, CUI::CORNER_TR))
+		Box.VSplitLeft(110.0f, &Button, &Box);
+		static int s_FavoritesButton=0;
+		if(DoButton_MenuTab(&s_FavoritesButton, Localize("Favorites"), m_ActivePage==PAGE_FAVORITES, &Button, CUI::CORNER_TR))
 		{
-			client_serverbrowse_refresh(BROWSETYPE_FAVORITES);
-			new_page  = PAGE_FAVORITES;
+			ServerBrowser()->Refresh(IServerBrowser::TYPE_FAVORITES);
+			NewPage  = PAGE_FAVORITES;
 		}
 		
-		box.VSplitLeft(4.0f*5, 0, &box);
-		box.VSplitLeft(100.0f, &button, &box);
-		static int demos_button=0;
-		if(DoButton_MenuTab(&demos_button, localize("Demos"), active_page==PAGE_DEMOS, &button, 0))
+		Box.VSplitLeft(4.0f*5, 0, &Box);
+		Box.VSplitLeft(100.0f, &Button, &Box);
+		static int s_DemosButton=0;
+		if(DoButton_MenuTab(&s_DemosButton, Localize("Demos"), m_ActivePage==PAGE_DEMOS, &Button, CUI::CORNER_T))
 		{
-			demolist_populate();
-			new_page  = PAGE_DEMOS;
+			DemolistPopulate();
+			NewPage  = PAGE_DEMOS;
 		}		
 	}
 	else
 	{
-		/* online menus */
-		box.VSplitLeft(90.0f, &button, &box);
-		static int game_button=0;
-		if(DoButton_MenuTab(&game_button, localize("Game"), active_page==PAGE_GAME, &button, 0))
-			new_page = PAGE_GAME;
-
-		box.VSplitLeft(4.0f, 0, &box);
-		box.VSplitLeft(140.0f, &button, &box);
-		static int server_info_button=0;
-		if(DoButton_MenuTab(&server_info_button, localize("Server info"), active_page==PAGE_SERVER_INFO, &button, 0))
-			new_page = PAGE_SERVER_INFO;
-
-		box.VSplitLeft(4.0f, 0, &box);
-		box.VSplitLeft(140.0f, &button, &box);
-		static int callvote_button=0;
-		if(DoButton_MenuTab(&callvote_button, localize("Call vote"), active_page==PAGE_CALLVOTE, &button, 0))
-			new_page = PAGE_CALLVOTE;
+		// online menus
+		Box.VSplitLeft(90.0f, &Button, &Box);
+		static int s_GameButton=0;
+		if(DoButton_MenuTab(&s_GameButton, Localize("Game"), m_ActivePage==PAGE_GAME, &Button, CUI::CORNER_T))
+			NewPage = PAGE_GAME;
+
+		Box.VSplitLeft(4.0f, 0, &Box);
+		Box.VSplitLeft(140.0f, &Button, &Box);
+		static int s_ServerInfoButton=0;
+		if(DoButton_MenuTab(&s_ServerInfoButton, Localize("Server info"), m_ActivePage==PAGE_SERVER_INFO, &Button, CUI::CORNER_T))
+			NewPage = PAGE_SERVER_INFO;
+
+		Box.VSplitLeft(4.0f, 0, &Box);
+		Box.VSplitLeft(140.0f, &Button, &Box);
+		static int s_CallVoteButton=0;
+		if(DoButton_MenuTab(&s_CallVoteButton, Localize("Call vote"), m_ActivePage==PAGE_CALLVOTE, &Button, CUI::CORNER_T))
+			NewPage = PAGE_CALLVOTE;
 			
-		box.VSplitLeft(30.0f, 0, &box);
+		Box.VSplitLeft(30.0f, 0, &Box);
 	}
 		
 	/*
 	box.VSplitRight(110.0f, &box, &button);
 	static int system_button=0;
-	if (UI()->DoButton(&system_button, "System", config.ui_page==PAGE_SYSTEM, &button))
-		config.ui_page = PAGE_SYSTEM;
+	if (UI()->DoButton(&system_button, "System", g_Config.m_UiPage==PAGE_SYSTEM, &button))
+		g_Config.m_UiPage = PAGE_SYSTEM;
 		
 	box.VSplitRight(30.0f, &box, 0);
 	*/
 	
-	box.VSplitRight(90.0f, &box, &button);
-	static int quit_button=0;
-	if(DoButton_MenuTab(&quit_button, localize("Quit"), 0, &button, 0))
-		popup = POPUP_QUIT;
-
-	box.VSplitRight(10.0f, &box, &button);
-	box.VSplitRight(130.0f, &box, &button);
-	static int settings_button=0;
-	if(DoButton_MenuTab(&settings_button, localize("Settings"), active_page==PAGE_SETTINGS, &button, 0))
-		new_page = PAGE_SETTINGS;
+	Box.VSplitRight(90.0f, &Box, &Button);
+	static int s_QuitButton=0;
+	if(DoButton_MenuTab(&s_QuitButton, Localize("Quit"), 0, &Button, CUI::CORNER_T))
+		m_Popup = POPUP_QUIT;
+
+	Box.VSplitRight(10.0f, &Box, &Button);
+	Box.VSplitRight(130.0f, &Box, &Button);
+	static int s_SettingsButton=0;
+	if(DoButton_MenuTab(&s_SettingsButton, Localize("Settings"), m_ActivePage==PAGE_SETTINGS, &Button, CUI::CORNER_T))
+		NewPage = PAGE_SETTINGS;
 	
-	if(new_page != -1)
+	if(NewPage != -1)
 	{
-		if(client_state() == CLIENTSTATE_OFFLINE)
-			config.ui_page = new_page;
+		if(Client()->State() == IClient::STATE_OFFLINE)
+			g_Config.m_UiPage = NewPage;
 		else
-			game_page = new_page;
+			m_GamePage = NewPage;
 	}
 		
 	return 0;
 }
 
-void MENUS::render_loading(float percent)
+void CMenus::RenderLoading(float Percent)
 {
-	static int64 last_load_render = 0;
+	static int64 LastLoadRender = 0;
 
 	// make sure that we don't render for each little thing we load
 	// because that will slow down loading if we have vsync
-	if(time_get()-last_load_render < time_freq()/60)
+	if(time_get()-LastLoadRender < time_freq()/60)
 		return;
 		
-	last_load_render = time_get();
+	LastLoadRender = time_get();
 	
 	// need up date this here to get correct
-	vec3 rgb = hsl_to_rgb(vec3(config.ui_color_hue/255.0f, config.ui_color_sat/255.0f, config.ui_color_lht/255.0f));
-	gui_color = vec4(rgb.r, rgb.g, rgb.b, config.ui_color_alpha/255.0f);
+	vec3 Rgb = HslToRgb(vec3(g_Config.m_UiColorHue/255.0f, g_Config.m_UiColorSat/255.0f, g_Config.m_UiColorLht/255.0f));
+	ms_GuiColor = vec4(Rgb.r, Rgb.g, Rgb.b, g_Config.m_UiColorAlpha/255.0f);
 	
-    CUIRect screen = *UI()->Screen();
-	Graphics()->MapScreen(screen.x, screen.y, screen.w, screen.h);
+    CUIRect Screen = *UI()->Screen();
+	Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);
 	
-	render_background();
+	RenderBackground();
 
 	float tw;
 
 	float w = 700;
 	float h = 200;
-	float x = screen.w/2-w/2;
-	float y = screen.h/2-h/2;
+	float x = Screen.w/2-w/2;
+	float y = Screen.h/2-h/2;
 
 	Graphics()->BlendNormal();
 
 	Graphics()->TextureSet(-1);
 	Graphics()->QuadsBegin();
 	Graphics()->SetColor(0,0,0,0.50f);
-	RenderTools()->draw_round_rect(x, y, w, h, 40.0f);
+	RenderTools()->DrawRoundRect(x, y, w, h, 40.0f);
 	Graphics()->QuadsEnd();
 
 
-	const char *caption = localize("Loading");
+	const char *pCaption = Localize("Loading");
 
-	tw = gfx_text_width(0, 48.0f, caption, -1);
+	tw = TextRender()->TextWidth(0, 48.0f, pCaption, -1);
 	CUIRect r;
 	r.x = x;
 	r.y = y+20;
 	r.w = w;
 	r.h = h;
-	UI()->DoLabel(&r, caption, 48.0f, 0, -1);
+	UI()->DoLabel(&r, pCaption, 48.0f, 0, -1);
 
 	Graphics()->TextureSet(-1);
 	Graphics()->QuadsBegin();
 	Graphics()->SetColor(1,1,1,0.75f);
-	RenderTools()->draw_round_rect(x+40, y+h-75, (w-80)*percent, 25, 5.0f);
+	RenderTools()->DrawRoundRect(x+40, y+h-75, (w-80)*Percent, 25, 5.0f);
 	Graphics()->QuadsEnd();
 
-	gfx_swap();
+	Graphics()->Swap();
 }
 
-void MENUS::render_news(CUIRect main_view)
+void CMenus::RenderNews(CUIRect MainView)
 {
-	RenderTools()->DrawUIRect(&main_view, color_tabbar_active, CUI::CORNER_ALL, 10.0f);
+	RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f);
 }
 
-void MENUS::on_init()
+void CMenus::OnInit()
 {
 
 	/*
@@ -669,261 +678,263 @@ void MENUS::on_init()
 	exit(-1);
 	// */
 	
-	if(config.cl_show_welcome)
-		popup = POPUP_FIRST_LAUNCH;
-	config.cl_show_welcome = 0;
+	if(g_Config.m_ClShowWelcome)
+		m_Popup = POPUP_FIRST_LAUNCH;
+	g_Config.m_ClShowWelcome = 0;
 }
 
-void MENUS::popup_message(const char *topic, const char *body, const char *button)
+void CMenus::PopupMessage(const char *pTopic, const char *pBody, const char *pButton)
 {
-	str_copy(message_topic, topic, sizeof(message_topic));
-	str_copy(message_body, body, sizeof(message_body));
-	str_copy(message_button, button, sizeof(message_button));
-	popup = POPUP_MESSAGE;
+	str_copy(m_aMessageTopic, pTopic, sizeof(m_aMessageTopic));
+	str_copy(m_aMessageBody, pBody, sizeof(m_aMessageBody));
+	str_copy(m_aMessageButton, pButton, sizeof(m_aMessageButton));
+	m_Popup = POPUP_MESSAGE;
 }
 
 
-int MENUS::render()
+int CMenus::Render()
 {
-    CUIRect screen = *UI()->Screen();
-	Graphics()->MapScreen(screen.x, screen.y, screen.w, screen.h);
+    CUIRect Screen = *UI()->Screen();
+	Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);
 
-	static bool first = true;
-	if(first)
+	static bool s_First = true;
+	if(s_First)
 	{
-		if(config.ui_page == PAGE_INTERNET)
-			client_serverbrowse_refresh(0);
-		else if(config.ui_page == PAGE_LAN)
-			client_serverbrowse_refresh(1);
-		first = false;
+		if(g_Config.m_UiPage == PAGE_INTERNET)
+			ServerBrowser()->Refresh(IServerBrowser::TYPE_INTERNET);
+		else if(g_Config.m_UiPage == PAGE_LAN)
+			ServerBrowser()->Refresh(IServerBrowser::TYPE_LAN);
+		else if(g_Config.m_UiPage == PAGE_FAVORITES)
+			ServerBrowser()->Refresh(IServerBrowser::TYPE_FAVORITES);
+		s_First = false;
 	}
 	
-	if(client_state() == CLIENTSTATE_ONLINE)
+	if(Client()->State() == IClient::STATE_ONLINE)
 	{
-		color_tabbar_inactive = color_tabbar_inactive_ingame;
-		color_tabbar_active = color_tabbar_active_ingame;
+		ms_ColorTabbarInactive = ms_ColorTabbarInactiveIngame;
+		ms_ColorTabbarActive = ms_ColorTabbarActiveIngame;
 	}
 	else
 	{
-		render_background();
-		color_tabbar_inactive = color_tabbar_inactive_outgame;
-		color_tabbar_active = color_tabbar_active_outgame;
+		RenderBackground();
+		ms_ColorTabbarInactive = ms_ColorTabbarInactiveOutgame;
+		ms_ColorTabbarActive = ms_ColorTabbarActiveOutgame;
 	}
 	
-	CUIRect tab_bar;
-	CUIRect main_view;
+	CUIRect TabBar;
+	CUIRect MainView;
 
 	// some margin around the screen
-	screen.Margin(10.0f, &screen);
+	Screen.Margin(10.0f, &Screen);
 	
-	if(popup == POPUP_NONE)
+	if(m_Popup == POPUP_NONE)
 	{
 		// do tab bar
-		screen.HSplitTop(24.0f, &tab_bar, &main_view);
-		tab_bar.VMargin(20.0f, &tab_bar);
-		render_menubar(tab_bar);
+		Screen.HSplitTop(24.0f, &TabBar, &MainView);
+		TabBar.VMargin(20.0f, &TabBar);
+		RenderMenubar(TabBar);
 		
 		// news is not implemented yet
-		if(config.ui_page <= PAGE_NEWS || config.ui_page > PAGE_SETTINGS || (client_state() == CLIENTSTATE_OFFLINE && config.ui_page >= PAGE_GAME && config.ui_page <= PAGE_CALLVOTE))
+		if(g_Config.m_UiPage <= PAGE_NEWS || g_Config.m_UiPage > PAGE_SETTINGS || (Client()->State() == IClient::STATE_OFFLINE && g_Config.m_UiPage >= PAGE_GAME && g_Config.m_UiPage <= PAGE_CALLVOTE))
 		{
-			client_serverbrowse_refresh(BROWSETYPE_INTERNET);
-			config.ui_page = PAGE_INTERNET;
+			ServerBrowser()->Refresh(IServerBrowser::TYPE_INTERNET);
+			g_Config.m_UiPage = PAGE_INTERNET;
 		}
 		
 		// render current page
-		if(client_state() != CLIENTSTATE_OFFLINE)
+		if(Client()->State() != IClient::STATE_OFFLINE)
 		{
-			if(game_page == PAGE_GAME)
-				render_game(main_view);
-			else if(game_page == PAGE_SERVER_INFO)
-				render_serverinfo(main_view);
-			else if(game_page == PAGE_CALLVOTE)
-				render_servercontrol(main_view);
-			else if(game_page == PAGE_SETTINGS)
-				render_settings(main_view);
+			if(m_GamePage == PAGE_GAME)
+				RenderGame(MainView);
+			else if(m_GamePage == PAGE_SERVER_INFO)
+				RenderServerInfo(MainView);
+			else if(m_GamePage == PAGE_CALLVOTE)
+				RenderServerControl(MainView);
+			else if(m_GamePage == PAGE_SETTINGS)
+				RenderSettings(MainView);
 		}
-		else if(config.ui_page == PAGE_NEWS)
-			render_news(main_view);
-		else if(config.ui_page == PAGE_INTERNET)
-			render_serverbrowser(main_view);
-		else if(config.ui_page == PAGE_LAN)
-			render_serverbrowser(main_view);
-		else if(config.ui_page == PAGE_DEMOS)
-			render_demolist(main_view);
-		else if(config.ui_page == PAGE_FAVORITES)
-			render_serverbrowser(main_view);
-		else if(config.ui_page == PAGE_SETTINGS)
-			render_settings(main_view);
+		else if(g_Config.m_UiPage == PAGE_NEWS)
+			RenderNews(MainView);
+		else if(g_Config.m_UiPage == PAGE_INTERNET)
+			RenderServerbrowser(MainView);
+		else if(g_Config.m_UiPage == PAGE_LAN)
+			RenderServerbrowser(MainView);
+		else if(g_Config.m_UiPage == PAGE_DEMOS)
+			RenderDemoList(MainView);
+		else if(g_Config.m_UiPage == PAGE_FAVORITES)
+			RenderServerbrowser(MainView);
+		else if(g_Config.m_UiPage == PAGE_SETTINGS)
+			RenderSettings(MainView);
 	}
 	else
 	{
 		// make sure that other windows doesn't do anything funnay!
 		//UI()->SetHotItem(0);
 		//UI()->SetActiveItem(0);
-		char buf[128];
-		const char *title = "";
-		const char *extra_text = "";
-		const char *button_text = "";
-		int extra_align = 0;
+		char aBuf[128];
+		const char *pTitle = "";
+		const char *pExtraText = "";
+		const char *pButtonText = "";
+		int ExtraAlign = 0;
 		
-		if(popup == POPUP_MESSAGE)
+		if(m_Popup == POPUP_MESSAGE)
 		{
-			title = message_topic;
-			extra_text = message_body;
-			button_text = message_button;
+			pTitle = m_aMessageTopic;
+			pExtraText = m_aMessageBody;
+			pButtonText = m_aMessageButton;
 		}
-		else if(popup == POPUP_CONNECTING)
+		else if(m_Popup == POPUP_CONNECTING)
 		{
-			title = localize("Connecting to");
-			extra_text = config.ui_server_address;  // TODO: query the client about the address
-			button_text = localize("Abort");
-			if(client_mapdownload_totalsize() > 0)
+			pTitle = Localize("Connecting to");
+			pExtraText = g_Config.m_UiServerAddress;  // TODO: query the client about the address
+			pButtonText = Localize("Abort");
+			if(Client()->MapDownloadTotalsize() > 0)
 			{
-				title = localize("Downloading map");
-				str_format(buf, sizeof(buf), "%d/%d KiB", client_mapdownload_amount()/1024, client_mapdownload_totalsize()/1024);
-				extra_text = buf;
+				pTitle = Localize("Downloading map");
+				str_format(aBuf, sizeof(aBuf), "%d/%d KiB", Client()->MapDownloadAmount()/1024, Client()->MapDownloadTotalsize()/1024);
+				pExtraText = aBuf;
 			}
 		}
-		else if(popup == POPUP_DISCONNECTED)
+		else if(m_Popup == POPUP_DISCONNECTED)
 		{
-			title = localize("Disconnected");
-			extra_text = client_error_string();
-			button_text = localize("Ok");
-			extra_align = -1;
+			pTitle = Localize("Disconnected");
+			pExtraText = Client()->ErrorString();
+			pButtonText = Localize("Ok");
+			ExtraAlign = -1;
 		}
-		else if(popup == POPUP_PURE)
+		else if(m_Popup == POPUP_PURE)
 		{
-			title = localize("Disconnected");
-			extra_text = localize("The server is running a non-standard tuning on a pure game type.");
-			button_text = localize("Ok");
-			extra_align = -1;
+			pTitle = Localize("Disconnected");
+			pExtraText = Localize("The server is running a non-standard tuning on a pure game type.");
+			pButtonText = Localize("Ok");
+			ExtraAlign = -1;
 		}
-		else if(popup == POPUP_PASSWORD)
+		else if(m_Popup == POPUP_PASSWORD)
 		{
-			title = localize("Password Incorrect");
-			extra_text = client_error_string();
-			button_text = localize("Try again");
+			pTitle = Localize("Password Incorrect");
+			pExtraText = Client()->ErrorString();
+			pButtonText = Localize("Try again");
 		}
-		else if(popup == POPUP_QUIT)
+		else if(m_Popup == POPUP_QUIT)
 		{
-			title = localize("Quit");
-			extra_text = localize("Are you sure that you want to quit?");
+			pTitle = Localize("Quit");
+			pExtraText = Localize("Are you sure that you want to quit?");
 		}
-		else if(popup == POPUP_FIRST_LAUNCH)
+		else if(m_Popup == POPUP_FIRST_LAUNCH)
 		{
-			title = localize("Welcome to Teeworlds");
-			extra_text = localize("As this is the first time you launch the game, please enter your nick name below. It's recommended that you check the settings to adjust them to your liking before joining a server.");
-			button_text = localize("Ok");
-			extra_align = -1;
+			pTitle = Localize("Welcome to Teeworlds");
+			pExtraText = Localize("As this is the first time you launch the game, please enter your nick name below. It's recommended that you check the settings to adjust them to your liking before joining a server.");
+			pButtonText = Localize("Ok");
+			ExtraAlign = -1;
 		}
 		
-		CUIRect box, part;
-		box = screen;
-		box.VMargin(150.0f, &box);
-		box.HMargin(150.0f, &box);
+		CUIRect Box, Part;
+		Box = Screen;
+		Box.VMargin(150.0f, &Box);
+		Box.HMargin(150.0f, &Box);
 		
 		// render the box
-		RenderTools()->DrawUIRect(&box, vec4(0,0,0,0.5f), CUI::CORNER_ALL, 15.0f);
+		RenderTools()->DrawUIRect(&Box, vec4(0,0,0,0.5f), CUI::CORNER_ALL, 15.0f);
 		 
-		box.HSplitTop(20.f, &part, &box);
-		box.HSplitTop(24.f, &part, &box);
-		UI()->DoLabel(&part, title, 24.f, 0);
-		box.HSplitTop(20.f, &part, &box);
-		box.HSplitTop(24.f, &part, &box);
-		part.VMargin(20.f, &part);
+		Box.HSplitTop(20.f, &Part, &Box);
+		Box.HSplitTop(24.f, &Part, &Box);
+		UI()->DoLabel(&Part, pTitle, 24.f, 0);
+		Box.HSplitTop(20.f, &Part, &Box);
+		Box.HSplitTop(24.f, &Part, &Box);
+		Part.VMargin(20.f, &Part);
 		
-		if(extra_align == -1)
-			UI()->DoLabel(&part, extra_text, 20.f, -1, (int)part.w);
+		if(ExtraAlign == -1)
+			UI()->DoLabel(&Part, pExtraText, 20.f, -1, (int)Part.w);
 		else
-			UI()->DoLabel(&part, extra_text, 20.f, 0, -1);
+			UI()->DoLabel(&Part, pExtraText, 20.f, 0, -1);
 
-		if(popup == POPUP_QUIT)
+		if(m_Popup == POPUP_QUIT)
 		{
-			CUIRect yes, no;
-			box.HSplitBottom(20.f, &box, &part);
-			box.HSplitBottom(24.f, &box, &part);
-			part.VMargin(80.0f, &part);
+			CUIRect Yes, No;
+			Box.HSplitBottom(20.f, &Box, &Part);
+			Box.HSplitBottom(24.f, &Box, &Part);
+			Part.VMargin(80.0f, &Part);
 			
-			part.VSplitMid(&no, &yes);
+			Part.VSplitMid(&No, &Yes);
 			
-			yes.VMargin(20.0f, &yes);
-			no.VMargin(20.0f, &no);
+			Yes.VMargin(20.0f, &Yes);
+			No.VMargin(20.0f, &No);
 
-			static int button_abort = 0;
-			if(DoButton_Menu(&button_abort, localize("No"), 0, &no) || escape_pressed)
-				popup = POPUP_NONE;
+			static int s_ButtonAbort = 0;
+			if(DoButton_Menu(&s_ButtonAbort, Localize("No"), 0, &No) || m_EscapePressed)
+				m_Popup = POPUP_NONE;
 
-			static int button_tryagain = 0;
-			if(DoButton_Menu(&button_tryagain, localize("Yes"), 0, &yes) || enter_pressed)
-				client_quit();
+			static int s_ButtonTryAgain = 0;
+			if(DoButton_Menu(&s_ButtonTryAgain, Localize("Yes"), 0, &Yes) || m_EnterPressed)
+				Client()->Quit();
 		}
-		else if(popup == POPUP_PASSWORD)
+		else if(m_Popup == POPUP_PASSWORD)
 		{
-			CUIRect label, textbox, tryagain, abort;
+			CUIRect Label, TextBox, TryAgain, Abort;
 			
-			box.HSplitBottom(20.f, &box, &part);
-			box.HSplitBottom(24.f, &box, &part);
-			part.VMargin(80.0f, &part);
+			Box.HSplitBottom(20.f, &Box, &Part);
+			Box.HSplitBottom(24.f, &Box, &Part);
+			Part.VMargin(80.0f, &Part);
 			
-			part.VSplitMid(&abort, &tryagain);
+			Part.VSplitMid(&Abort, &TryAgain);
 			
-			tryagain.VMargin(20.0f, &tryagain);
-			abort.VMargin(20.0f, &abort);
+			TryAgain.VMargin(20.0f, &TryAgain);
+			Abort.VMargin(20.0f, &Abort);
 			
-			static int button_abort = 0;
-			if(DoButton_Menu(&button_abort, localize("Abort"), 0, &abort) || escape_pressed)
-				popup = POPUP_NONE;
+			static int s_ButtonAbort = 0;
+			if(DoButton_Menu(&s_ButtonAbort, Localize("Abort"), 0, &Abort) || m_EscapePressed)
+				m_Popup = POPUP_NONE;
 
-			static int button_tryagain = 0;
-			if(DoButton_Menu(&button_tryagain, localize("Try again"), 0, &tryagain) || enter_pressed)
+			static int s_ButtonTryAgain = 0;
+			if(DoButton_Menu(&s_ButtonTryAgain, Localize("Try again"), 0, &TryAgain) || m_EnterPressed)
 			{
-				client_connect(config.ui_server_address);
+				Client()->Connect(g_Config.m_UiServerAddress);
 			}
 			
-			box.HSplitBottom(60.f, &box, &part);
-			box.HSplitBottom(24.f, &box, &part);
+			Box.HSplitBottom(60.f, &Box, &Part);
+			Box.HSplitBottom(24.f, &Box, &Part);
 			
-			part.VSplitLeft(60.0f, 0, &label);
-			label.VSplitLeft(100.0f, 0, &textbox);
-			textbox.VSplitLeft(20.0f, 0, &textbox);
-			textbox.VSplitRight(60.0f, &textbox, 0);
-			UI()->DoLabel(&label, localize("Password"), 20, -1);
-			DoEditBox(&config.password, &textbox, config.password, sizeof(config.password), 14.0f, true);
+			Part.VSplitLeft(60.0f, 0, &Label);
+			Label.VSplitLeft(100.0f, 0, &TextBox);
+			TextBox.VSplitLeft(20.0f, 0, &TextBox);
+			TextBox.VSplitRight(60.0f, &TextBox, 0);
+			UI()->DoLabel(&Label, Localize("Password"), 18.0f, -1);
+			DoEditBox(&g_Config.m_Password, &TextBox, g_Config.m_Password, sizeof(g_Config.m_Password), 12.0f, true);
 		}
-		else if(popup == POPUP_FIRST_LAUNCH)
+		else if(m_Popup == POPUP_FIRST_LAUNCH)
 		{
-			CUIRect label, textbox;
+			CUIRect Label, TextBox;
 			
-			box.HSplitBottom(20.f, &box, &part);
-			box.HSplitBottom(24.f, &box, &part);
-			part.VMargin(80.0f, &part);
+			Box.HSplitBottom(20.f, &Box, &Part);
+			Box.HSplitBottom(24.f, &Box, &Part);
+			Part.VMargin(80.0f, &Part);
 			
-			static int enter_button = 0;
-			if(DoButton_Menu(&enter_button, localize("Enter"), 0, &part) || enter_pressed)
-				popup = POPUP_NONE;
+			static int s_EnterButton = 0;
+			if(DoButton_Menu(&s_EnterButton, Localize("Enter"), 0, &Part) || m_EnterPressed)
+				m_Popup = POPUP_NONE;
 			
-			box.HSplitBottom(40.f, &box, &part);
-			box.HSplitBottom(24.f, &box, &part);
+			Box.HSplitBottom(40.f, &Box, &Part);
+			Box.HSplitBottom(24.f, &Box, &Part);
 			
-			part.VSplitLeft(60.0f, 0, &label);
-			label.VSplitLeft(100.0f, 0, &textbox);
-			textbox.VSplitLeft(20.0f, 0, &textbox);
-			textbox.VSplitRight(60.0f, &textbox, 0);
-			UI()->DoLabel(&label, localize("Nickname"), 20, -1);
-			DoEditBox(&config.player_name, &textbox, config.player_name, sizeof(config.player_name), 14.0f);
+			Part.VSplitLeft(60.0f, 0, &Label);
+			Label.VSplitLeft(100.0f, 0, &TextBox);
+			TextBox.VSplitLeft(20.0f, 0, &TextBox);
+			TextBox.VSplitRight(60.0f, &TextBox, 0);
+			UI()->DoLabel(&Label, Localize("Nickname"), 18.0f, -1);
+			DoEditBox(&g_Config.m_PlayerName, &TextBox, g_Config.m_PlayerName, sizeof(g_Config.m_PlayerName), 12.0f);
 		}
 		else
 		{
-			box.HSplitBottom(20.f, &box, &part);
-			box.HSplitBottom(24.f, &box, &part);
-			part.VMargin(120.0f, &part);
+			Box.HSplitBottom(20.f, &Box, &Part);
+			Box.HSplitBottom(24.f, &Box, &Part);
+			Part.VMargin(120.0f, &Part);
 
-			static int button = 0;
-			if(DoButton_Menu(&button, button_text, 0, &part) || escape_pressed || enter_pressed)
+			static int s_Button = 0;
+			if(DoButton_Menu(&s_Button, pButtonText, 0, &Part) || m_EscapePressed || m_EnterPressed)
 			{
-				if(popup == POPUP_CONNECTING)
-					client_disconnect();
-				popup = POPUP_NONE;
+				if(m_Popup == POPUP_CONNECTING)
+					Client()->Disconnect();
+				m_Popup = POPUP_NONE;
 			}
 		}
 	}
@@ -932,109 +943,113 @@ int MENUS::render()
 }
 
 
-void MENUS::set_active(bool active)
+void CMenus::SetActive(bool Active)
 {
-	menu_active = active;
-	if(!menu_active && need_sendinfo)
+	m_MenuActive = Active;
+	if(!m_MenuActive && m_NeedSendinfo)
 	{
-		gameclient.send_info(false);
-		need_sendinfo = false;
+		m_pClient->SendInfo(false);
+		m_NeedSendinfo = false;
 	}
 }
 
-void MENUS::on_reset()
+void CMenus::OnReset()
 {
 }
 
-bool MENUS::on_mousemove(float x, float y)
+bool CMenus::OnMouseMove(float x, float y)
 {
-	last_input = time_get();
+	m_LastInput = time_get();
 	
-	if(!menu_active)
+	if(!m_MenuActive)
 		return false;
 		
-	mouse_pos.x += x;
-	mouse_pos.y += y;
-	if(mouse_pos.x < 0) mouse_pos.x = 0;
-	if(mouse_pos.y < 0) mouse_pos.y = 0;
-	if(mouse_pos.x > Graphics()->ScreenWidth()) mouse_pos.x = Graphics()->ScreenWidth();
-	if(mouse_pos.y > Graphics()->ScreenHeight()) mouse_pos.y = Graphics()->ScreenHeight();
+	m_MousePos.x += x;
+	m_MousePos.y += y;
+	if(m_MousePos.x < 0) m_MousePos.x = 0;
+	if(m_MousePos.y < 0) m_MousePos.y = 0;
+	if(m_MousePos.x > Graphics()->ScreenWidth()) m_MousePos.x = Graphics()->ScreenWidth();
+	if(m_MousePos.y > Graphics()->ScreenHeight()) m_MousePos.y = Graphics()->ScreenHeight();
 	
 	return true;
 }
 
-bool MENUS::on_input(INPUT_EVENT e)
+bool CMenus::OnInput(IInput::CEvent e)
 {
-	last_input = time_get();
+	m_LastInput = time_get();
 	
 	// special handle esc and enter for popup purposes
-	if(e.flags&INPFLAG_PRESS)
+	if(e.m_Flags&IInput::FLAG_PRESS)
 	{
-		if(e.key == KEY_ESCAPE)
+		if(e.m_Key == KEY_ESCAPE)
 		{
-			escape_pressed = true;
-			set_active(!is_active());
+			m_EscapePressed = true;
+			SetActive(!IsActive());
 			return true;
 		}
 	}
 		
-	if(is_active())
+	if(IsActive())
 	{
 		// special for popups
-		if(e.flags&INPFLAG_PRESS && e.key == KEY_RETURN)
-			enter_pressed = true;
+		if(e.m_Flags&IInput::FLAG_PRESS && e.m_Key == KEY_RETURN)
+			m_EnterPressed = true;
 		
-		if(num_inputevents < MAX_INPUTEVENTS)
-			inputevents[num_inputevents++] = e;
+		if(m_NumInputEvents < MAX_INPUTEVENTS)
+			m_aInputEvents[m_NumInputEvents++] = e;
 		return true;
 	}
 	return false;
 }
 
-void MENUS::on_statechange(int new_state, int old_state)
+void CMenus::OnStateChange(int NewState, int OldState)
 {
-	if(new_state == CLIENTSTATE_OFFLINE)
+	// reset active item
+	UI()->SetActiveItem(0);
+
+	if(NewState == IClient::STATE_OFFLINE)
 	{
-		popup = POPUP_NONE;
-		if(client_error_string() && client_error_string()[0] != 0)
+		m_Popup = POPUP_NONE;
+		if(Client()->ErrorString() && Client()->ErrorString()[0] != 0)
 		{
-			if(strstr(client_error_string(), "password"))
+			if(str_find(Client()->ErrorString(), "password"))
 			{
-				popup = POPUP_PASSWORD;
-				UI()->SetHotItem(&config.password);
-				UI()->SetActiveItem(&config.password);
+				m_Popup = POPUP_PASSWORD;
+				UI()->SetHotItem(&g_Config.m_Password);
+				UI()->SetActiveItem(&g_Config.m_Password);
 			}
 			else
-				popup = POPUP_DISCONNECTED;
-		}	}
-	else if(new_state == CLIENTSTATE_LOADING)
+				m_Popup = POPUP_DISCONNECTED;
+		}
+	}
+	else if(NewState == IClient::STATE_LOADING)
 	{
-		popup = POPUP_CONNECTING;
-		client_serverinfo_request();
+		m_Popup = POPUP_CONNECTING;
+		//client_serverinfo_request();
 	}
-	else if(new_state == CLIENTSTATE_CONNECTING)
-		popup = POPUP_CONNECTING;
-	else if (new_state == CLIENTSTATE_ONLINE || new_state == CLIENTSTATE_DEMOPLAYBACK)
+	else if(NewState == IClient::STATE_CONNECTING)
+		m_Popup = POPUP_CONNECTING;
+	else if (NewState == IClient::STATE_ONLINE || NewState == IClient::STATE_DEMOPLAYBACK)
 	{
-		popup = POPUP_NONE;
-		set_active(false);
+		m_Popup = POPUP_NONE;
+		SetActive(false);
 	}
 }
 
 extern "C" void font_debug_render();
 
-void MENUS::on_render()
+void CMenus::OnRender()
 {
 	/*
 	// text rendering test stuff
 	render_background();
 
-	TEXT_CURSOR cursor;
-	gfx_text_set_cursor(&cursor, 10, 10, 20, TEXTFLAG_RENDER);
-	gfx_text_ex(&cursor, "ようこそ - ガイド", -1);
+	CTextCursor cursor;
+	TextRender()->SetCursor(&cursor, 10, 10, 20, TEXTFLAG_RENDER);
+	TextRender()->TextEx(&cursor, "ようこそ - ガイド", -1);
 
-	gfx_text_set_cursor(&cursor, 10, 30, 15, TEXTFLAG_RENDER);
-	gfx_text_ex(&cursor, "ようこそ - ガイド", -1);
+	TextRender()->SetCursor(&cursor, 10, 30, 15, TEXTFLAG_RENDER);
+	TextRender()->TextEx(&cursor, "ようこそ - ガイド", -1);
 	
 	//Graphics()->TextureSet(-1);
 	Graphics()->QuadsBegin();
@@ -1042,101 +1057,105 @@ void MENUS::on_render()
 	Graphics()->QuadsEnd();
 	return;*/
 	
-	if(client_state() != CLIENTSTATE_ONLINE && client_state() != CLIENTSTATE_DEMOPLAYBACK)
-		set_active(true);
+	if(Client()->State() != IClient::STATE_ONLINE && Client()->State() != IClient::STATE_DEMOPLAYBACK)
+		SetActive(true);
 
-	if(client_state() == CLIENTSTATE_DEMOPLAYBACK)
+	if(Client()->State() == IClient::STATE_DEMOPLAYBACK)
 	{
-		CUIRect screen = *UI()->Screen();
-		Graphics()->MapScreen(screen.x, screen.y, screen.w, screen.h);
-		render_demoplayer(screen);
+		CUIRect Screen = *UI()->Screen();
+		Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);
+		RenderDemoPlayer(Screen);
 	}
 	
-	if(client_state() == CLIENTSTATE_ONLINE && gameclient.servermode == gameclient.SERVERMODE_PUREMOD)
+	if(Client()->State() == IClient::STATE_ONLINE && m_pClient->m_ServerMode == m_pClient->SERVERMODE_PUREMOD)
 	{
-		client_disconnect();
-		set_active(true);
-		popup = POPUP_PURE;
+		Client()->Disconnect();
+		SetActive(true);
+		m_Popup = POPUP_PURE;
 	}
 	
-	if(!is_active())
+	if(!IsActive())
 	{
-		escape_pressed = false;
-		enter_pressed = false;
-		num_inputevents = 0;
+		m_EscapePressed = false;
+		m_EnterPressed = false;
+		m_NumInputEvents = 0;
 		return;
 	}
 	
 	// update colors
-	vec3 rgb = hsl_to_rgb(vec3(config.ui_color_hue/255.0f, config.ui_color_sat/255.0f, config.ui_color_lht/255.0f));
-	gui_color = vec4(rgb.r, rgb.g, rgb.b, config.ui_color_alpha/255.0f);
-
-	color_tabbar_inactive_outgame = vec4(0,0,0,0.25f);
-	color_tabbar_active_outgame = vec4(0,0,0,0.5f);
-
-	float color_ingame_scale_i = 0.5f;
-	float color_ingame_scale_a = 0.2f;
-	color_tabbar_inactive_ingame = vec4(
-		gui_color.r*color_ingame_scale_i,
-		gui_color.g*color_ingame_scale_i,
-		gui_color.b*color_ingame_scale_i,
-		gui_color.a*0.8f);
+	vec3 Rgb = HslToRgb(vec3(g_Config.m_UiColorHue/255.0f, g_Config.m_UiColorSat/255.0f, g_Config.m_UiColorLht/255.0f));
+	ms_GuiColor = vec4(Rgb.r, Rgb.g, Rgb.b, g_Config.m_UiColorAlpha/255.0f);
+
+	ms_ColorTabbarInactiveOutgame = vec4(0,0,0,0.25f);
+	ms_ColorTabbarActiveOutgame = vec4(0,0,0,0.5f);
+
+	float ColorIngameScaleI = 0.5f;
+	float ColorIngameAcaleA = 0.2f;
+	ms_ColorTabbarInactiveIngame = vec4(
+		ms_GuiColor.r*ColorIngameScaleI,
+		ms_GuiColor.g*ColorIngameScaleI,
+		ms_GuiColor.b*ColorIngameScaleI,
+		ms_GuiColor.a*0.8f);
 	
-	color_tabbar_active_ingame = vec4(
-		gui_color.r*color_ingame_scale_a,
-		gui_color.g*color_ingame_scale_a,
-		gui_color.b*color_ingame_scale_a,
-		gui_color.a);
+	ms_ColorTabbarActiveIngame = vec4(
+		ms_GuiColor.r*ColorIngameAcaleA,
+		ms_GuiColor.g*ColorIngameAcaleA,
+		ms_GuiColor.b*ColorIngameAcaleA,
+		ms_GuiColor.a);
     
 	// update the ui
-	CUIRect *screen = UI()->Screen();
-	float mx = (mouse_pos.x/(float)Graphics()->ScreenWidth())*screen->w;
-	float my = (mouse_pos.y/(float)Graphics()->ScreenHeight())*screen->h;
+	CUIRect *pScreen = UI()->Screen();
+	float mx = (m_MousePos.x/(float)Graphics()->ScreenWidth())*pScreen->w;
+	float my = (m_MousePos.y/(float)Graphics()->ScreenHeight())*pScreen->h;
 		
-	int buttons = 0;
-	if(inp_key_pressed(KEY_MOUSE_1)) buttons |= 1;
-	if(inp_key_pressed(KEY_MOUSE_2)) buttons |= 2;
-	if(inp_key_pressed(KEY_MOUSE_3)) buttons |= 4;
+	int Buttons = 0;
+	if(m_UseMouseButtons)
+	{
+		if(Input()->KeyPressed(KEY_MOUSE_1)) Buttons |= 1;
+		if(Input()->KeyPressed(KEY_MOUSE_2)) Buttons |= 2;
+		if(Input()->KeyPressed(KEY_MOUSE_3)) Buttons |= 4;
+	}
 		
-	UI()->Update(mx,my,mx*3.0f,my*3.0f,buttons);
+	UI()->Update(mx,my,mx*3.0f,my*3.0f,Buttons);
     
 	// render
-	if(client_state() != CLIENTSTATE_DEMOPLAYBACK)
-		render();
+	if(Client()->State() != IClient::STATE_DEMOPLAYBACK)
+		Render();
 
 	// render cursor
-	Graphics()->TextureSet(data->images[IMAGE_CURSOR].id);
+	Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CURSOR].m_Id);
 	Graphics()->QuadsBegin();
 	Graphics()->SetColor(1,1,1,1);
-	Graphics()->QuadsDrawTL(mx,my,24,24);
+	IGraphics::CQuadItem QuadItem(mx, my, 24, 24);
+	Graphics()->QuadsDrawTL(&QuadItem, 1);
 	Graphics()->QuadsEnd();
 
 	// render debug information
-	if(config.debug)
+	if(g_Config.m_Debug)
 	{
-		CUIRect screen = *UI()->Screen();
-		Graphics()->MapScreen(screen.x, screen.y, screen.w, screen.h);
-
-		char buf[512];
-		str_format(buf, sizeof(buf), "%p %p %p", UI()->HotItem(), UI()->ActiveItem(), UI()->LastActiveItem());
-		TEXT_CURSOR cursor;
-		gfx_text_set_cursor(&cursor, 10, 10, 10, TEXTFLAG_RENDER);
-		gfx_text_ex(&cursor, buf, -1);
+		CUIRect Screen = *UI()->Screen();
+		Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);
+
+		char aBuf[512];
+		str_format(aBuf, sizeof(aBuf), "%p %p %p", UI()->HotItem(), UI()->ActiveItem(), UI()->LastActiveItem());
+		CTextCursor Cursor;
+		TextRender()->SetCursor(&Cursor, 10, 10, 10, TEXTFLAG_RENDER);
+		TextRender()->TextEx(&Cursor, aBuf, -1);
 	}
 
-	escape_pressed = false;
-	enter_pressed = false;
-	num_inputevents = 0;
+	m_EscapePressed = false;
+	m_EnterPressed = false;
+	m_NumInputEvents = 0;
 }
 
-static int texture_blob = -1;
+static int gs_TextureBlob = -1;
 
-void MENUS::render_background()
+void CMenus::RenderBackground()
 {
 	//Graphics()->Clear(1,1,1);
 	//render_sunrays(0,0);
-	if(texture_blob == -1)
-		texture_blob = Graphics()->LoadTexture("blob.png", IMG_AUTO, 0);
+	if(gs_TextureBlob == -1)
+		gs_TextureBlob = Graphics()->LoadTexture("blob.png", CImageInfo::FORMAT_AUTO, 0);
 
 
 	float sw = 300*Graphics()->ScreenAspect();
@@ -1150,36 +1169,41 @@ void MENUS::render_background()
 	Graphics()->QuadsBegin();
 		//vec4 bottom(gui_color.r*0.3f, gui_color.g*0.3f, gui_color.b*0.3f, 1.0f);
 		//vec4 bottom(0, 0, 0, 1.0f);
-		vec4 bottom(gui_color.r, gui_color.g, gui_color.b, 1.0f);
-		vec4 top(gui_color.r, gui_color.g, gui_color.b, 1.0f);
-		Graphics()->SetColorVertex(0, top.r, top.g, top.b, top.a);
-		Graphics()->SetColorVertex(1, top.r, top.g, top.b, top.a);
-		Graphics()->SetColorVertex(2, bottom.r, bottom.g, bottom.b, bottom.a);
-		Graphics()->SetColorVertex(3, bottom.r, bottom.g, bottom.b, bottom.a);
-		Graphics()->QuadsDrawTL(0, 0, sw, sh);
+		vec4 Bottom(ms_GuiColor.r, ms_GuiColor.g, ms_GuiColor.b, 1.0f);
+		vec4 Top(ms_GuiColor.r, ms_GuiColor.g, ms_GuiColor.b, 1.0f);
+		IGraphics::CColorVertex Array[4] = {
+			IGraphics::CColorVertex(0, Top.r, Top.g, Top.b, Top.a),
+			IGraphics::CColorVertex(1, Top.r, Top.g, Top.b, Top.a),
+			IGraphics::CColorVertex(2, Bottom.r, Bottom.g, Bottom.b, Bottom.a),
+			IGraphics::CColorVertex(3, Bottom.r, Bottom.g, Bottom.b, Bottom.a)};
+		Graphics()->SetColorVertex(Array, 4);
+		IGraphics::CQuadItem QuadItem(0, 0, sw, sh);
+		Graphics()->QuadsDrawTL(&QuadItem, 1);
 	Graphics()->QuadsEnd();
 	
 	// render the tiles
 	Graphics()->TextureSet(-1);
 	Graphics()->QuadsBegin();
-		float size = 15.0f;
-		float offset_time = fmod(client_localtime()*0.15f, 2.0f);
-		for(int y = -2; y < (int)(sw/size); y++)
-			for(int x = -2; x < (int)(sh/size); x++)
+		float Size = 15.0f;
+		float OffsetTime = fmod(Client()->LocalTime()*0.15f, 2.0f);
+		for(int y = -2; y < (int)(sw/Size); y++)
+			for(int x = -2; x < (int)(sh/Size); x++)
 			{
 				Graphics()->SetColor(0,0,0,0.045f);
-				Graphics()->QuadsDrawTL((x-offset_time)*size*2+(y&1)*size, (y+offset_time)*size, size, size);
+				IGraphics::CQuadItem QuadItem((x-OffsetTime)*Size*2+(y&1)*Size, (y+OffsetTime)*Size, Size, Size);
+				Graphics()->QuadsDrawTL(&QuadItem, 1);
 			}
 	Graphics()->QuadsEnd();
 
 	// render border fade
-	Graphics()->TextureSet(texture_blob);
+	Graphics()->TextureSet(gs_TextureBlob);
 	Graphics()->QuadsBegin();
 		Graphics()->SetColor(0,0,0,0.5f);
-		Graphics()->QuadsDrawTL(-100, -100, sw+200, sh+200);
+		QuadItem = IGraphics::CQuadItem(-100, -100, sw+200, sh+200);
+		Graphics()->QuadsDrawTL(&QuadItem, 1);
 	Graphics()->QuadsEnd();
 
 	// restore screen	
-    {CUIRect screen = *UI()->Screen();
-	Graphics()->MapScreen(screen.x, screen.y, screen.w, screen.h);}	
+    {CUIRect Screen = *UI()->Screen();
+	Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);}	
 }
diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h
new file mode 100644
index 00000000..3055e661
--- /dev/null
+++ b/src/game/client/components/menus.h
@@ -0,0 +1,223 @@
+#ifndef GAME_CLIENT_COMPONENTS_MENUS_H
+#define GAME_CLIENT_COMPONENTS_MENUS_H
+
+#include <base/vmath.h>
+#include <base/tl/sorted_array.h>
+
+#include <game/client/component.h>
+#include <game/client/ui.h>
+
+
+// compnent to fetch keypresses, override all other input
+class CMenusKeyBinder : public CComponent
+{
+public:
+	bool m_TakeKey;
+	bool m_GotKey;
+	IInput::CEvent m_Key;
+	CMenusKeyBinder();
+	virtual bool OnInput(IInput::CEvent Event);
+};
+
+class CMenus : public CComponent
+{	
+	static vec4 ms_GuiColor;
+	static vec4 ms_ColorTabbarInactiveOutgame;
+	static vec4 ms_ColorTabbarActiveOutgame;
+	static vec4 ms_ColorTabbarInactiveIngame;
+	static vec4 ms_ColorTabbarActiveIngame;
+	static vec4 ms_ColorTabbarInactive;
+	static vec4 ms_ColorTabbarActive;
+	
+	vec4 ButtonColorMul(const void *pID);
+
+
+	int DoButton_DemoPlayer(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
+	int DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
+	int DoButton_MenuTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners);
+	int DoButton_SettingsTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
+
+	int DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect);
+	int DoButton_CheckBox(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
+	int DoButton_CheckBox_Number(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
+
+	/*static void ui_draw_menu_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
+	static void ui_draw_keyselect_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
+	static void ui_draw_menu_tab_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
+	static void ui_draw_settings_tab_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
+	*/
+
+	int DoButton_BrowseIcon(int Checked, const CUIRect *pRect);
+	int DoButton_GridHeader(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
+	int DoButton_ListRow(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
+
+	//static void ui_draw_browse_icon(int what, const CUIRect *r);
+	//static void ui_draw_grid_header(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
+	
+	/*static void ui_draw_checkbox_common(const void *id, const char *text, const char *boxtext, const CUIRect *r, const void *extra);
+	static void ui_draw_checkbox(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
+	static void ui_draw_checkbox_number(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
+	*/
+	int DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, bool Hidden=false, int Corners=CUI::CORNER_ALL);
+	//static int ui_do_edit_box(void *id, const CUIRect *rect, char *str, unsigned str_size, float font_size, bool hidden=false);
+
+	float DoScrollbarV(const void *pID, const CUIRect *pRect, float Current);
+	float DoScrollbarH(const void *pID, const CUIRect *pRect, float Current);
+	void DoButton_KeySelect(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
+	int DoKeyReader(void *pID, const CUIRect *pRect, int Key);
+
+	//static int ui_do_key_reader(void *id, const CUIRect *rect, int key);
+	void UiDoGetButtons(int Start, int Stop, CUIRect View);
+
+	struct CListboxItem
+	{
+		int m_Visible;
+		int m_Selected;
+		CUIRect m_Rect;
+		CUIRect m_HitRect;
+	};
+	
+	void UiDoListboxStart(void *pId, const CUIRect *pRect, float RowHeight, const char *pTitle, const char *pBottomText, int NumItems,
+						  int ItemsPerRow, int SelectedIndex, float ScrollValue);
+	CListboxItem UiDoListboxNextItem(void *pID, bool Selected = false);
+	static CListboxItem UiDoListboxNextRow();
+	int UiDoListboxEnd(float *pScrollValue, bool *pItemActivated);
+	
+	//static void demolist_listdir_callback(const char *name, int is_dir, void *user);
+	//static void demolist_list_callback(const CUIRect *rect, int index, void *user);
+
+	enum
+	{
+		POPUP_NONE=0,
+		POPUP_FIRST_LAUNCH,
+		POPUP_CONNECTING,
+		POPUP_MESSAGE,
+		POPUP_DISCONNECTED,
+		POPUP_PURE,
+		POPUP_PASSWORD,
+		POPUP_QUIT, 
+	};
+
+	enum
+	{
+		PAGE_NEWS=1,
+		PAGE_GAME,
+		PAGE_SERVER_INFO,
+		PAGE_CALLVOTE,
+		PAGE_INTERNET,
+		PAGE_LAN,
+		PAGE_FAVORITES,
+		PAGE_DEMOS,
+		PAGE_SETTINGS,
+		PAGE_SYSTEM,
+	};
+
+	int m_GamePage;
+	int m_Popup;
+	int m_ActivePage;
+	bool m_MenuActive;
+	bool m_UseMouseButtons;
+	vec2 m_MousePos;
+	
+	int64 m_LastInput;
+	
+	//
+	char m_aMessageTopic[512];
+	char m_aMessageBody[512];
+	char m_aMessageButton[512];
+	
+	void PopupMessage(const char *pTopic, const char *pBody, const char *pButton);
+
+	// TODO: this is a bit ugly but.. well.. yeah	
+	enum { MAX_INPUTEVENTS = 32 };
+	static IInput::CEvent m_aInputEvents[MAX_INPUTEVENTS];
+	static int m_NumInputEvents;
+	
+	// some settings
+	static float ms_ButtonHeight;
+	static float ms_ListheaderHeight;
+	static float ms_FontmodHeight;
+	
+	// for graphic settings
+	bool m_NeedRestart;
+	bool m_NeedSendinfo;
+	
+	//
+	bool m_EscapePressed;
+	bool m_EnterPressed;
+	
+	// for call vote
+	int m_CallvoteSelectedOption;
+	int m_CallvoteSelectedPlayer;
+	
+	// demo
+	struct CDemoItem
+	{
+		char m_aFilename[512];
+		char m_aName[256];
+		
+		bool operator<(const CDemoItem &Other) { return str_comp(m_aName, Other.m_aName) < 0; } 
+	};
+	
+	sorted_array<CDemoItem> m_lDemos;
+		
+	void DemolistPopulate();
+	static void DemolistCountCallback(const char *pName, int IsDir, void *pUser);
+	static void DemolistFetchCallback(const char *pName, int IsDir, void *pUser);
+
+	// found in menus.cpp
+	int Render();
+	//void render_background();
+	//void render_loading(float percent);
+	int RenderMenubar(CUIRect r);
+	void RenderNews(CUIRect MainView);
+	
+	// found in menus_demo.cpp
+	void RenderDemoPlayer(CUIRect MainView);
+	void RenderDemoList(CUIRect MainView);
+	
+	// found in menus_ingame.cpp
+	void RenderGame(CUIRect MainView);
+	void RenderServerInfo(CUIRect MainView);
+	void RenderServerControl(CUIRect MainView);
+	void RenderServerControlKick(CUIRect MainView);
+	void RenderServerControlServer(CUIRect MainView);
+	
+	// found in menus_browser.cpp
+	int m_SelectedIndex;
+	void RenderServerbrowserServerList(CUIRect View);
+	void RenderServerbrowserServerDetail(CUIRect View);
+	void RenderServerbrowserFilters(CUIRect View);
+	void RenderServerbrowser(CUIRect MainView);
+	
+	// found in menus_settings.cpp
+	void RenderSettingsGeneral(CUIRect MainView);
+	void RenderSettingsPlayer(CUIRect MainView);
+	void RenderSettingsControls(CUIRect MainView);
+	void RenderSettingsGraphics(CUIRect MainView);
+	void RenderSettingsSound(CUIRect MainView);
+	void RenderSettings(CUIRect MainView);
+	
+	void SetActive(bool Active);
+public:
+	void RenderBackground();
+
+	void UseMouseButtons(bool Use) { m_UseMouseButtons = Use; }
+
+	static CMenusKeyBinder m_Binder;
+	
+	CMenus();
+
+	void RenderLoading(float Percent);
+
+	bool IsActive() const { return m_MenuActive; }
+
+	virtual void OnInit();
+
+	virtual void OnStateChange(int NewState, int OldState);
+	virtual void OnReset();
+	virtual void OnRender();
+	virtual bool OnInput(IInput::CEvent Event);
+	virtual bool OnMouseMove(float x, float y);
+};
+#endif
diff --git a/src/game/client/components/menus.hpp b/src/game/client/components/menus.hpp
deleted file mode 100644
index 02759403..00000000
--- a/src/game/client/components/menus.hpp
+++ /dev/null
@@ -1,216 +0,0 @@
-#include <base/vmath.hpp>
-#include <base/tl/sorted_array.hpp>
-
-#include <game/client/component.hpp>
-#include <game/client/ui.hpp>
-
-
-// compnent to fetch keypresses, override all other input
-class MENUS_KEYBINDER : public COMPONENT
-{
-public:
-	bool take_key;
-	bool got_key;
-	INPUT_EVENT key;
-	MENUS_KEYBINDER();
-	virtual bool on_input(INPUT_EVENT e);
-};
-
-class MENUS : public COMPONENT
-{	
-	static vec4 gui_color;
-	static vec4 color_tabbar_inactive_outgame;
-	static vec4 color_tabbar_active_outgame;
-	static vec4 color_tabbar_inactive_ingame;
-	static vec4 color_tabbar_active_ingame;
-	static vec4 color_tabbar_inactive;
-	static vec4 color_tabbar_active;
-	
-	vec4 button_color_mul(const void *pID);
-
-
-	int DoButton_DemoPlayer(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
-	int DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
-	int DoButton_MenuTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners);
-	int DoButton_SettingsTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
-
-	int DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect);
-	int DoButton_CheckBox(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
-	int DoButton_CheckBox_Number(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
-
-	/*static void ui_draw_menu_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
-	static void ui_draw_keyselect_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
-	static void ui_draw_menu_tab_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
-	static void ui_draw_settings_tab_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
-	*/
-
-	int DoButton_BrowseIcon(int Checked, const CUIRect *pRect);
-	int DoButton_GridHeader(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
-	int DoButton_ListRow(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
-
-	//static void ui_draw_browse_icon(int what, const CUIRect *r);
-	//static void ui_draw_grid_header(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
-	
-	/*static void ui_draw_checkbox_common(const void *id, const char *text, const char *boxtext, const CUIRect *r, const void *extra);
-	static void ui_draw_checkbox(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
-	static void ui_draw_checkbox_number(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
-	*/
-	int DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, bool Hidden=false);
-	//static int ui_do_edit_box(void *id, const CUIRect *rect, char *str, unsigned str_size, float font_size, bool hidden=false);
-
-	float DoScrollbarV(const void *pID, const CUIRect *pRect, float Current);
-	float DoScrollbarH(const void *pID, const CUIRect *pRect, float Current);
-	int DoButton_KeySelect(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
-	int DoKeyReader(void *pID, const CUIRect *pRect, int Key);
-
-	//static int ui_do_key_reader(void *id, const CUIRect *rect, int key);
-	void ui_do_getbuttons(int start, int stop, CUIRect view);
-
-	struct LISTBOXITEM
-	{
-		int visible;
-		int selected;
-		CUIRect rect;
-		CUIRect hitrect;
-	};
-	
-	void ui_do_listbox_start(void *id, const CUIRect *rect, float row_height, const char *title, int num_items, int selected_index);
-	LISTBOXITEM ui_do_listbox_nextitem(void *id);
-	static LISTBOXITEM ui_do_listbox_nextrow();
-	int ui_do_listbox_end();
-	
-	//static void demolist_listdir_callback(const char *name, int is_dir, void *user);
-	//static void demolist_list_callback(const RECT *rect, int index, void *user);
-
-	enum
-	{
-		POPUP_NONE=0,
-		POPUP_FIRST_LAUNCH,
-		POPUP_CONNECTING,
-		POPUP_MESSAGE,
-		POPUP_DISCONNECTED,
-		POPUP_PURE,
-		POPUP_PASSWORD,
-		POPUP_QUIT, 
-	};
-
-	enum
-	{
-		PAGE_NEWS=1,
-		PAGE_GAME,
-		PAGE_SERVER_INFO,
-		PAGE_CALLVOTE,
-		PAGE_INTERNET,
-		PAGE_LAN,
-		PAGE_FAVORITES,
-		PAGE_DEMOS,
-		PAGE_SETTINGS,
-		PAGE_SYSTEM,
-	};
-
-	int game_page;
-	int popup;
-	int active_page;
-	bool menu_active;
-	vec2 mouse_pos;
-	
-	int64 last_input;
-	
-	//
-	char message_topic[512];
-	char message_body[512];
-	char message_button[512];
-	
-	void popup_message(const char *topic, const char *body, const char *button);
-
-	// TODO: this is a bit ugly but.. well.. yeah	
-	enum { MAX_INPUTEVENTS = 32 };
-	static INPUT_EVENT inputevents[MAX_INPUTEVENTS];
-	static int num_inputevents;
-	
-	// some settings
-	static float button_height;
-	static float listheader_height;
-	static float fontmod_height;
-	
-	// for graphic settings
-	bool need_restart;
-	bool need_sendinfo;
-	
-	//
-	bool escape_pressed;
-	bool enter_pressed;
-	
-	// for call vote
-	int callvote_selectedoption;
-	int callvote_selectedplayer;
-	
-	// demo
-	struct DEMOITEM
-	{
-		char filename[512];
-		char name[256];
-		
-		bool operator<(const DEMOITEM &other) { return str_comp(name, other.name) < 0; } 
-	};
-	
-	sorted_array<DEMOITEM> demos;
-		
-	void demolist_populate();
-	static void demolist_count_callback(const char *name, int is_dir, void *user);
-	static void demolist_fetch_callback(const char *name, int is_dir, void *user);
-
-	// found in menus.cpp
-	int render();
-	//void render_background();
-	//void render_loading(float percent);
-	int render_menubar(CUIRect r);
-	void render_news(CUIRect main_view);
-	
-	// found in menus_demo.cpp
-	void render_demoplayer(CUIRect main_view);
-	void render_demolist(CUIRect main_view);
-	
-	// found in menus_ingame.cpp
-	void render_game(CUIRect main_view);
-	void render_serverinfo(CUIRect main_view);
-	void render_servercontrol(CUIRect main_view);
-	void render_servercontrol_kick(CUIRect main_view);
-	void render_servercontrol_server(CUIRect main_view);
-	
-	// found in menus_browser.cpp
-	int selected_index;
-	void render_serverbrowser_serverlist(CUIRect view);
-	void render_serverbrowser_serverdetail(CUIRect view);
-	void render_serverbrowser_filters(CUIRect view);
-	void render_serverbrowser(CUIRect main_view);
-	
-	// found in menus_settings.cpp
-	void render_settings_general(CUIRect main_view);
-	void render_settings_player(CUIRect main_view);
-	void render_settings_controls(CUIRect main_view);
-	void render_settings_graphics(CUIRect main_view);
-	void render_settings_sound(CUIRect main_view);
-	void render_settings(CUIRect main_view);
-	
-	void set_active(bool active);
-public:
-	void render_background();
-
-
-	static MENUS_KEYBINDER binder;
-	
-	MENUS();
-
-	void render_loading(float percent);
-
-	bool is_active() const { return menu_active; }
-
-	virtual void on_init();
-
-	virtual void on_statechange(int new_state, int old_state);
-	virtual void on_reset();
-	virtual void on_render();
-	virtual bool on_input(INPUT_EVENT e);
-	virtual bool on_mousemove(float x, float y);
-};
diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp
index dcf68f8d..0a737052 100644
--- a/src/game/client/components/menus_browser.cpp
+++ b/src/game/client/components/menus_browser.cpp
@@ -1,46 +1,45 @@
+#include <engine/serverbrowser.h>
+#include <engine/textrender.h>
+#include <engine/keys.h>
+#include <engine/shared/config.h>
+#include <game/generated/protocol.h>
+#include <game/generated/client_data.h>
+
+#include <game/client/ui.h>
+#include <game/client/render.h>
+#include "menus.h"
+#include <game/localization.h>
+#include <game/version.h>
+
+void CMenus::RenderServerbrowserServerList(CUIRect View)
+{
+	CUIRect Headers;
+	CUIRect Status;
 
-#include <string.h> // strcmp, strlen, strncpy
-#include <stdlib.h> // atoi
-
-#include <engine/e_client_interface.h>
-#include <game/generated/g_protocol.hpp>
-#include <game/generated/gc_data.hpp>
-
-#include <game/client/ui.hpp>
-#include <game/client/render.hpp>
-#include "menus.hpp"
-#include <game/localization.hpp>
-#include <game/version.hpp>
+	View.HSplitTop(ms_ListheaderHeight, &Headers, &View);
+	View.HSplitBottom(28.0f, &View, &Status);
 
-void MENUS::render_serverbrowser_serverlist(CUIRect view)
-{
-	CUIRect headers;
-	CUIRect status;
-	
-	view.HSplitTop(listheader_height, &headers, &view);
-	view.HSplitBottom(28.0f, &view, &status);
-	
 	// split of the scrollbar
-	RenderTools()->DrawUIRect(&headers, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f);
-	headers.VSplitRight(20.0f, &headers, 0);
-	
-	struct column
+	RenderTools()->DrawUIRect(&Headers, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f);
+	Headers.VSplitRight(20.0f, &Headers, 0);
+
+	struct CColumn
 	{
-		int id;
-		int sort;
-		LOC_CONSTSTRING caption;
-		int direction;
-		float width;
-		int flags;
-		CUIRect rect;
-		CUIRect spacer;
+		int m_Id;
+		int m_Sort;
+		CLocConstString m_Caption;
+		int m_Direction;
+		float m_Width;
+		int m_Flags;
+		CUIRect m_Rect;
+		CUIRect m_Spacer;
 	};
-	
+
 	enum
 	{
 		FIXED=1,
 		SPACER=2,
-		
+
 		COL_FLAG_LOCK=0,
 		COL_FLAG_PURE,
 		COL_FLAG_FAV,
@@ -51,494 +50,542 @@ void MENUS::render_serverbrowser_serverlist(CUIRect view)
 		COL_PING,
 		COL_VERSION,
 	};
-	
-	static column cols[] = {
+
+	static CColumn s_aCols[] = {
 		{-1,			-1,						" ",		-1, 2.0f, 0, {0}, {0}},
 		{COL_FLAG_LOCK,	-1,						" ",		-1, 14.0f, 0, {0}, {0}},
 		{COL_FLAG_PURE,	-1,						" ",		-1, 14.0f, 0, {0}, {0}},
 		{COL_FLAG_FAV,	-1,						" ",		-1, 14.0f, 0, {0}, {0}},
-		{COL_NAME,		BROWSESORT_NAME,		localize("Name"),		0, 300.0f, 0, {0}, {0}},
-		{COL_GAMETYPE,	BROWSESORT_GAMETYPE,	localize("Type"),		1, 50.0f, 0, {0}, {0}},
-		{COL_MAP,		BROWSESORT_MAP,			localize("Map"), 		1, 100.0f, 0, {0}, {0}},
-		{COL_PLAYERS,	BROWSESORT_NUMPLAYERS,	localize("Players"),	1, 60.0f, 0, {0}, {0}},
+		{COL_NAME,		IServerBrowser::SORT_NAME,		Localize("Name"),		0, 300.0f, 0, {0}, {0}},
+		{COL_GAMETYPE,	IServerBrowser::SORT_GAMETYPE,	Localize("Type"),		1, 50.0f, 0, {0}, {0}},
+		{COL_MAP,		IServerBrowser::SORT_MAP,			Localize("Map"), 		1, 100.0f, 0, {0}, {0}},
+		{COL_PLAYERS,	IServerBrowser::SORT_NUMPLAYERS,	Localize("Players"),	1, 60.0f, 0, {0}, {0}},
 		{-1,			-1,						" ",		1, 10.0f, 0, {0}, {0}},
-		{COL_PING,		BROWSESORT_PING,		localize("Ping"),		1, 40.0f, FIXED, {0}, {0}},
+		{COL_PING,		IServerBrowser::SORT_PING,		Localize("Ping"),		1, 40.0f, FIXED, {0}, {0}},
 	};
-	
-	int num_cols = sizeof(cols)/sizeof(column);
-	
+
+	int NumCols = sizeof(s_aCols)/sizeof(CColumn);
+
 	// do layout
-	for(int i = 0; i < num_cols; i++)
+	for(int i = 0; i < NumCols; i++)
 	{
-		if(cols[i].direction == -1)
+		if(s_aCols[i].m_Direction == -1)
 		{
-			headers.VSplitLeft(cols[i].width, &cols[i].rect, &headers);
-			
-			if(i+1 < num_cols)
+			Headers.VSplitLeft(s_aCols[i].m_Width, &s_aCols[i].m_Rect, &Headers);
+
+			if(i+1 < NumCols)
 			{
-				//cols[i].flags |= SPACER;
-				headers.VSplitLeft(2, &cols[i].spacer, &headers);
+				//Cols[i].flags |= SPACER;
+				Headers.VSplitLeft(2, &s_aCols[i].m_Spacer, &Headers);
 			}
 		}
 	}
-	
-	for(int i = num_cols-1; i >= 0; i--)
+
+	for(int i = NumCols-1; i >= 0; i--)
 	{
-		if(cols[i].direction == 1)
+		if(s_aCols[i].m_Direction == 1)
 		{
-			headers.VSplitRight(cols[i].width, &headers, &cols[i].rect);
-			headers.VSplitRight(2, &headers, &cols[i].spacer);
+			Headers.VSplitRight(s_aCols[i].m_Width, &Headers, &s_aCols[i].m_Rect);
+			Headers.VSplitRight(2, &Headers, &s_aCols[i].m_Spacer);
 		}
 	}
-	
-	for(int i = 0; i < num_cols; i++)
+
+	for(int i = 0; i < NumCols; i++)
 	{
-		if(cols[i].direction == 0)
-			cols[i].rect = headers;
+		if(s_aCols[i].m_Direction == 0)
+			s_aCols[i].m_Rect = Headers;
 	}
-	
+
 	// do headers
-	for(int i = 0; i < num_cols; i++)
+	for(int i = 0; i < NumCols; i++)
 	{
-		if(DoButton_GridHeader(cols[i].caption, cols[i].caption, config.b_sort == cols[i].sort, &cols[i].rect))
+		if(DoButton_GridHeader(s_aCols[i].m_Caption, s_aCols[i].m_Caption, g_Config.m_BrSort == s_aCols[i].m_Sort, &s_aCols[i].m_Rect))
 		{
-			if(cols[i].sort != -1)
+			if(s_aCols[i].m_Sort != -1)
 			{
-				if(config.b_sort == cols[i].sort)
-					config.b_sort_order ^= 1;
+				if(g_Config.m_BrSort == s_aCols[i].m_Sort)
+					g_Config.m_BrSortOrder ^= 1;
 				else
-					config.b_sort_order = 0;
-				config.b_sort = cols[i].sort;
+					g_Config.m_BrSortOrder = 0;
+				g_Config.m_BrSort = s_aCols[i].m_Sort;
 			}
 		}
 	}
-	
-	RenderTools()->DrawUIRect(&view, vec4(0,0,0,0.15f), 0, 0);
-	
-	CUIRect scroll;
-	view.VSplitRight(15, &view, &scroll);
-	
-	int num_servers = client_serverbrowse_sorted_num();
-	
+
+	RenderTools()->DrawUIRect(&View, vec4(0,0,0,0.15f), 0, 0);
+
+	CUIRect Scroll;
+	View.VSplitRight(15, &View, &Scroll);
+
+	int NumServers = ServerBrowser()->NumSortedServers();
+
 	// display important messages in the middle of the screen so no
 	// users misses it
 	{
-		CUIRect msgbox = view;
-		msgbox.y += view.h/3;
-		
-		if(active_page == PAGE_INTERNET && client_serverbrowse_refreshingmasters())
-			UI()->DoLabel(&msgbox, localize("Refreshing master servers"), 16.0f, 0);
-		else if(!client_serverbrowse_num())
-			UI()->DoLabel(&msgbox, localize("No servers found"), 16.0f, 0);
-		else if(client_serverbrowse_num() && !num_servers)
-			UI()->DoLabel(&msgbox, localize("No servers match your filter criteria"), 16.0f, 0);
+		CUIRect MsgBox = View;
+		MsgBox.y += View.h/3;
+
+		if(m_ActivePage == PAGE_INTERNET && ServerBrowser()->IsRefreshingMasters())
+			UI()->DoLabel(&MsgBox, Localize("Refreshing master servers"), 16.0f, 0);
+		else if(!ServerBrowser()->NumServers())
+			UI()->DoLabel(&MsgBox, Localize("No servers found"), 16.0f, 0);
+		else if(ServerBrowser()->NumServers() && !NumServers)
+			UI()->DoLabel(&MsgBox, Localize("No servers match your filter criteria"), 16.0f, 0);
 	}
 
-	int num = (int)(view.h/cols[0].rect.h);
-	static int scrollbar = 0;
-	static float scrollvalue = 0;
-	//static int selected_index = -1;
-	scroll.HMargin(5.0f, &scroll);
-	scrollvalue = DoScrollbarV(&scrollbar, &scroll, scrollvalue);
-	
-	int scrollnum = num_servers-num+10;
-	if(scrollnum > 0)
+	int Num = (int)(View.h/s_aCols[0].m_Rect.h);
+	static int s_ScrollBar = 0;
+	static float s_ScrollValue = 0;
+
+	Scroll.HMargin(5.0f, &Scroll);
+	s_ScrollValue = DoScrollbarV(&s_ScrollBar, &Scroll, s_ScrollValue);
+
+	int ScrollNum = NumServers-Num+10;
+	if(ScrollNum > 0)
 	{
-		if(inp_key_presses(KEY_MOUSE_WHEEL_UP))
-			scrollvalue -= 1.0f/scrollnum;
-		if(inp_key_presses(KEY_MOUSE_WHEEL_DOWN))
-			scrollvalue += 1.0f/scrollnum;
-			
-		if(scrollvalue < 0) scrollvalue = 0;
-		if(scrollvalue > 1) scrollvalue = 1;
+		if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP))
+			s_ScrollValue -= 1.0f/ScrollNum;
+		if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN))
+			s_ScrollValue += 1.0f/ScrollNum;
 	}
 	else
-		scrollnum = 0;
+		ScrollNum = 0;
+		
+    if(m_SelectedIndex > -1)
+	{
+		for(int i = 0; i < m_NumInputEvents; i++)
+		{
+			int NewIndex = -1;
+			if(m_aInputEvents[i].m_Flags&IInput::FLAG_PRESS)
+			{
+				if(m_aInputEvents[i].m_Key == KEY_DOWN) NewIndex = m_SelectedIndex + 1;
+				if(m_aInputEvents[i].m_Key == KEY_UP) NewIndex = m_SelectedIndex - 1;
+			}
+			if(NewIndex > -1 && NewIndex < NumServers)
+			{
+			    //scroll
+			    if(ScrollNum)
+			    {
+			        if(NewIndex - m_SelectedIndex > 0)
+                        s_ScrollValue += 1.0f/ScrollNum;
+                    else
+                        s_ScrollValue -= 1.0f/ScrollNum;
+			    }
+			    
+				m_SelectedIndex = NewIndex;
+				
+				const CServerInfo *pItem = ServerBrowser()->SortedGet(m_SelectedIndex);
+				str_copy(g_Config.m_UiServerAddress, pItem->m_aAddress, sizeof(g_Config.m_UiServerAddress));
+			}
+		}
+	}
+	
+    if(s_ScrollValue < 0) s_ScrollValue = 0;
+    if(s_ScrollValue > 1) s_ScrollValue = 1;
 
 	// set clipping
-	UI()->ClipEnable(&view);
-	
-	int start = (int)(scrollnum*scrollvalue);
-	if(start < 0)
-		start = 0;
-	
-	CUIRect original_view = view;
-	view.y -= scrollvalue*scrollnum*cols[0].rect.h;
-	
-	int new_selected = -1;
-	int num_players = 0;
+	UI()->ClipEnable(&View);
+
+	CUIRect OriginalView = View;
+	View.y -= s_ScrollValue*ScrollNum*s_aCols[0].m_Rect.h;
 
-	selected_index = -1;
+	int NewSelected = -1;
+	int NumPlayers = 0;
 
-	for (int i = 0; i < num_servers; i++)
+	m_SelectedIndex = -1;
+
+	for (int i = 0; i < NumServers; i++)
 	{
-		SERVER_INFO *item = client_serverbrowse_sorted_get(i);
-		num_players += item->num_players;
+		const CServerInfo *pItem = ServerBrowser()->SortedGet(i);
+		NumPlayers += pItem->m_NumPlayers;
 	}
-	
-	for (int i = 0; i < num_servers; i++)
+
+	for (int i = 0; i < NumServers; i++)
 	{
-		int item_index = i;
-		SERVER_INFO *item = client_serverbrowse_sorted_get(item_index);
-		CUIRect row;
-        CUIRect select_hit_box;
-		
-		int selected = strcmp(item->address, config.ui_server_address) == 0; //selected_index==item_index;
-		
-		view.HSplitTop(17.0f, &row, &view);
-		select_hit_box = row;
-		
-		if(selected)
-		{
-			selected_index = i;
-			CUIRect r = row;
-			r.Margin(1.5f, &r);
-			RenderTools()->DrawUIRect(&r, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 4.0f);
-		}
+		int ItemIndex = i;
+		const CServerInfo *pItem = ServerBrowser()->SortedGet(ItemIndex);
+		CUIRect Row;
+        CUIRect SelectHitBox;
+
+		int Selected = str_comp(pItem->m_aAddress, g_Config.m_UiServerAddress) == 0; //selected_index==ItemIndex;
 
+		View.HSplitTop(17.0f, &Row, &View);
+		SelectHitBox = Row;
+
+		if(Selected)
+			m_SelectedIndex = i;
 
 		// make sure that only those in view can be selected
-		if(row.y+row.h > original_view.y)
+		if(Row.y+Row.h > OriginalView.y && Row.y < OriginalView.y+OriginalView.h)
 		{
-			if(select_hit_box.y < original_view.y) // clip the selection
+			if(Selected)
+			{
+				CUIRect r = Row;
+				r.Margin(1.5f, &r);
+				RenderTools()->DrawUIRect(&r, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 4.0f);
+			}
+
+			// clip the selection
+			if(SelectHitBox.y < OriginalView.y) // top
 			{
-				select_hit_box.h -= original_view.y-select_hit_box.y;
-				select_hit_box.y = original_view.y;
+				SelectHitBox.h -= OriginalView.y-SelectHitBox.y;
+				SelectHitBox.y = OriginalView.y;
 			}
-			
-			if(UI()->DoButtonLogic(item, "", selected, &select_hit_box))
+			else if(SelectHitBox.y+SelectHitBox.h > OriginalView.y+OriginalView.h) // bottom
+				SelectHitBox.h = OriginalView.y+OriginalView.h-SelectHitBox.y;
+
+			if(UI()->DoButtonLogic(pItem, "", Selected, &SelectHitBox))
 			{
-				new_selected = item_index;
+				NewSelected = ItemIndex;
 			}
 		}
-		
-		// check if we need to do more
-		if(row.y > original_view.y+original_view.h)
-			break;
+		else
+		{
+			// reset active item, if not visible
+			if(UI()->ActiveItem() == pItem)
+				UI()->SetActiveItem(0);
 
-		for(int c = 0; c < num_cols; c++)
+			// don't render invisible items
+			continue;
+		}
+
+		for(int c = 0; c < NumCols; c++)
 		{
-			CUIRect button;
-			char temp[64];
-			button.x = cols[c].rect.x;
-			button.y = row.y;
-			button.h = row.h;
-			button.w = cols[c].rect.w;
-			
-			//int s = 0;
-			int id = cols[c].id;
-
-			//s = UI()->DoButton(item, "L", l, &button, ui_draw_browse_icon, 0);
-			
-			if(id == COL_FLAG_LOCK)
+			CUIRect Button;
+			char aTemp[64];
+			Button.x = s_aCols[c].m_Rect.x;
+			Button.y = Row.y;
+			Button.h = Row.h;
+			Button.w = s_aCols[c].m_Rect.w;
+
+			int Id = s_aCols[c].m_Id;
+
+			if(Id == COL_FLAG_LOCK)
 			{
-				if(item->flags & SRVFLAG_PASSWORD)
-					DoButton_BrowseIcon(SPRITE_BROWSE_LOCK, &button);
+				if(pItem->m_Flags & SERVER_FLAG_PASSWORD)
+					DoButton_BrowseIcon(SPRITE_BROWSE_LOCK, &Button);
 			}
-			else if(id == COL_FLAG_PURE)
+			else if(Id == COL_FLAG_PURE)
 			{
-				if(strcmp(item->gametype, "DM") == 0 || strcmp(item->gametype, "TDM") == 0 || strcmp(item->gametype, "CTF") == 0)
+				if(	str_comp(pItem->m_aGameType, "DM") == 0 ||
+					str_comp(pItem->m_aGameType, "TDM") == 0 ||
+					str_comp(pItem->m_aGameType, "CTF") == 0)
 				{
 					// pure server
 				}
 				else
 				{
 					// unpure
-					DoButton_BrowseIcon(SPRITE_BROWSE_UNPURE, &button);
+					DoButton_BrowseIcon(SPRITE_BROWSE_UNPURE, &Button);
 				}
 			}
-			else if(id == COL_FLAG_FAV)
+			else if(Id == COL_FLAG_FAV)
 			{
-				if(item->favorite)
-					DoButton_BrowseIcon(SPRITE_BROWSE_HEART, &button);
+				if(pItem->m_Favorite)
+					DoButton_BrowseIcon(SPRITE_BROWSE_HEART, &Button);
 			}
-			else if(id == COL_NAME)
+			else if(Id == COL_NAME)
 			{
-				TEXT_CURSOR cursor;
-				gfx_text_set_cursor(&cursor, button.x, button.y, 12.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
-				cursor.line_width = button.w;
-				
-				if(config.b_filter_string[0] && (item->quicksearch_hit&BROWSEQUICK_SERVERNAME))
+				CTextCursor Cursor;
+				TextRender()->SetCursor(&Cursor, Button.x, Button.y, 12.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
+				Cursor.m_LineWidth = Button.w;
+
+				if(g_Config.m_BrFilterString[0] && (pItem->m_QuickSearchHit&IServerBrowser::QUICK_SERVERNAME))
 				{
 					// highlight the parts that matches
-					const char *s = str_find_nocase(item->name, config.b_filter_string);
+					const char *s = str_find_nocase(pItem->m_aName, g_Config.m_BrFilterString);
 					if(s)
 					{
-						gfx_text_ex(&cursor, item->name, (int)(s-item->name));
-						gfx_text_color(0.4f,0.4f,1.0f,1);
-						gfx_text_ex(&cursor, s, strlen(config.b_filter_string));
-						gfx_text_color(1,1,1,1);
-						gfx_text_ex(&cursor, s+strlen(config.b_filter_string), -1);
+						TextRender()->TextEx(&Cursor, pItem->m_aName, (int)(s-pItem->m_aName));
+						TextRender()->TextColor(0.4f,0.4f,1.0f,1);
+						TextRender()->TextEx(&Cursor, s, str_length(g_Config.m_BrFilterString));
+						TextRender()->TextColor(1,1,1,1);
+						TextRender()->TextEx(&Cursor, s+str_length(g_Config.m_BrFilterString), -1);
 					}
 					else
-						gfx_text_ex(&cursor, item->name, -1);
+						TextRender()->TextEx(&Cursor, pItem->m_aName, -1);
 				}
 				else
-					gfx_text_ex(&cursor, item->name, -1);
+					TextRender()->TextEx(&Cursor, pItem->m_aName, -1);
 			}
-			else if(id == COL_MAP)
-				UI()->DoLabel(&button, item->map, 12.0f, -1);
-			else if(id == COL_PLAYERS)
+			else if(Id == COL_MAP)
+				UI()->DoLabel(&Button, pItem->m_aMap, 12.0f, -1);
+			else if(Id == COL_PLAYERS)
 			{
-				str_format(temp, sizeof(temp), "%i/%i", item->num_players, item->max_players);
-				if(config.b_filter_string[0] && (item->quicksearch_hit&BROWSEQUICK_PLAYERNAME))
-					gfx_text_color(0.4f,0.4f,1.0f,1);
-				UI()->DoLabel(&button, temp, 12.0f, 1);
-				gfx_text_color(1,1,1,1);
+				str_format(aTemp, sizeof(aTemp), "%i/%i", pItem->m_NumPlayers, pItem->m_MaxPlayers);
+				if(g_Config.m_BrFilterString[0] && (pItem->m_QuickSearchHit&IServerBrowser::QUICK_PLAYERNAME))
+					TextRender()->TextColor(0.4f,0.4f,1.0f,1);
+				UI()->DoLabel(&Button, aTemp, 12.0f, 1);
+				TextRender()->TextColor(1,1,1,1);
 			}
-			else if(id == COL_PING)
+			else if(Id == COL_PING)
 			{
-				str_format(temp, sizeof(temp), "%i", item->latency);
-				UI()->DoLabel(&button, temp, 12.0f, 1);
+				str_format(aTemp, sizeof(aTemp), "%i", pItem->m_Latency);
+				UI()->DoLabel(&Button, aTemp, 12.0f, 1);
 			}
-			else if(id == COL_VERSION)
+			else if(Id == COL_VERSION)
 			{
-				const char *version = item->version;
-				if(strcmp(version, "0.3 e2d7973c6647a13c") == 0) // TODO: remove me later on
-					version = "0.3.0";
-				UI()->DoLabel(&button, version, 12.0f, 1);
-			}			
-			else if(id == COL_GAMETYPE)
+				const char *pVersion = pItem->m_aVersion;
+				if(str_comp(pVersion, "0.3 e2d7973c6647a13c") == 0) // TODO: remove me later on
+					pVersion = "0.3.0";
+				UI()->DoLabel(&Button, pVersion, 12.0f, 1);
+			}
+			else if(Id == COL_GAMETYPE)
 			{
-				UI()->DoLabel(&button, item->gametype, 12.0f, 0);
+				UI()->DoLabel(&Button, pItem->m_aGameType, 12.0f, 0);
 			}
 
 		}
 	}
 
 	UI()->ClipDisable();
-	
-	if(new_selected != -1)
+
+	if(NewSelected != -1)
 	{
 		// select the new server
-		SERVER_INFO *item = client_serverbrowse_sorted_get(new_selected);
-		strncpy(config.ui_server_address, item->address, sizeof(config.ui_server_address));
-		if(inp_mouse_doubleclick())
-			client_connect(config.ui_server_address);
+		const CServerInfo *pItem = ServerBrowser()->SortedGet(NewSelected);
+		str_copy(g_Config.m_UiServerAddress, pItem->m_aAddress, sizeof(g_Config.m_UiServerAddress));
+		if(Input()->MouseDoubleClick())
+			Client()->Connect(g_Config.m_UiServerAddress);
 	}
 
-	RenderTools()->DrawUIRect(&status, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f);
-	status.Margin(5.0f, &status);
-	
+	RenderTools()->DrawUIRect(&Status, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f);
+	Status.Margin(5.0f, &Status);
+
 	// render quick search
-	CUIRect quicksearch;
-	status.VSplitLeft(250.0f, &quicksearch, &status);
-	const char *label = localize("Quick search");
-	UI()->DoLabel(&quicksearch, label, 14.0f, -1);
-	quicksearch.VSplitLeft(gfx_text_width(0, 14.0f, label, -1), 0, &quicksearch);
-	quicksearch.VSplitLeft(5, 0, &quicksearch);
-	DoEditBox(&config.b_filter_string, &quicksearch, config.b_filter_string, sizeof(config.b_filter_string), 14.0f);
-	
+	CUIRect QuickSearch, Button;
+	Status.VSplitLeft(260.0f, &QuickSearch, &Status);
+	const char *pLabel = Localize("Quick search:");
+	UI()->DoLabel(&QuickSearch, pLabel, 12.0f, -1);
+	QuickSearch.VSplitLeft(TextRender()->TextWidth(0, 12.0f, pLabel, -1), 0, &QuickSearch);
+	QuickSearch.VSplitLeft(5.0f, 0, &QuickSearch);
+	QuickSearch.VSplitLeft(155.0f, &QuickSearch, &Button);
+	DoEditBox(&g_Config.m_BrFilterString, &QuickSearch, g_Config.m_BrFilterString, sizeof(g_Config.m_BrFilterString), 12.0f, false, CUI::CORNER_L);
+	// clear button
+	{
+		static int s_ClearButton = 0;
+		RenderTools()->DrawUIRect(&Button, vec4(1,1,1,0.33f)*ButtonColorMul(&s_ClearButton), CUI::CORNER_R, 3.0f);
+		UI()->DoLabel(&Button, "x", Button.h*ms_FontmodHeight, 0);
+		if(UI()->DoButtonLogic(&s_ClearButton, "x", 0, &Button))
+		{
+			g_Config.m_BrFilterString[0] = 0;
+			UI()->SetActiveItem(&g_Config.m_BrFilterString);
+		}
+	}
+
 	// render status
-	char buf[128];
-	str_format(buf, sizeof(buf), localize("%d of %d servers, %d players"), client_serverbrowse_sorted_num(), client_serverbrowse_num(), num_players);
-	status.VSplitRight(gfx_text_width(0, 14.0f, buf, -1), 0, &status);
-	UI()->DoLabel(&status, buf, 14.0f, -1);
+	char aBuf[128];
+	str_format(aBuf, sizeof(aBuf), Localize("%d of %d servers, %d players"), ServerBrowser()->NumSortedServers(), ServerBrowser()->NumServers(), NumPlayers);
+	Status.VSplitRight(TextRender()->TextWidth(0, 14.0f, aBuf, -1), 0, &Status);
+	UI()->DoLabel(&Status, aBuf, 14.0f, -1);
 }
 
-void MENUS::render_serverbrowser_filters(CUIRect view)
+void CMenus::RenderServerbrowserFilters(CUIRect View)
 {
 	// filters
-	CUIRect button;
+	CUIRect Button;
 
-	view.HSplitTop(5.0f, 0, &view);
-	view.VSplitLeft(5.0f, 0, &view);
-	view.VSplitRight(5.0f, &view, 0);
-	view.HSplitBottom(5.0f, &view, 0);
+	View.HSplitTop(5.0f, 0, &View);
+	View.VSplitLeft(5.0f, 0, &View);
+	View.VSplitRight(5.0f, &View, 0);
+	View.HSplitBottom(5.0f, &View, 0);
 
 	// render filters
-	view.HSplitTop(20.0f, &button, &view);
-	if (DoButton_CheckBox(&config.b_filter_empty, localize("Has people playing"), config.b_filter_empty, &button))
-		config.b_filter_empty ^= 1;
+	View.HSplitTop(20.0f, &Button, &View);
+	if (DoButton_CheckBox(&g_Config.m_BrFilterEmpty, Localize("Has people playing"), g_Config.m_BrFilterEmpty, &Button))
+		g_Config.m_BrFilterEmpty ^= 1;
 
-	view.HSplitTop(20.0f, &button, &view);
-	if (DoButton_CheckBox(&config.b_filter_full, localize("Server not full"), config.b_filter_full, &button))
-		config.b_filter_full ^= 1;
+	View.HSplitTop(20.0f, &Button, &View);
+	if (DoButton_CheckBox(&g_Config.m_BrFilterFull, Localize("Server not full"), g_Config.m_BrFilterFull, &Button))
+		g_Config.m_BrFilterFull ^= 1;
 
-	view.HSplitTop(20.0f, &button, &view);
-	if (DoButton_CheckBox(&config.b_filter_pw, localize("No password"), config.b_filter_pw, &button))
-		config.b_filter_pw ^= 1;
+	View.HSplitTop(20.0f, &Button, &View);
+	if (DoButton_CheckBox(&g_Config.m_BrFilterPw, Localize("No password"), g_Config.m_BrFilterPw, &Button))
+		g_Config.m_BrFilterPw ^= 1;
 
-	view.HSplitTop(20.0f, &button, &view);
-	if (DoButton_CheckBox((char *)&config.b_filter_compatversion, localize("Compatible version"), config.b_filter_compatversion, &button))
-		config.b_filter_compatversion ^= 1;
+	View.HSplitTop(20.0f, &Button, &View);
+	if (DoButton_CheckBox((char *)&g_Config.m_BrFilterCompatversion, Localize("Compatible version"), g_Config.m_BrFilterCompatversion, &Button))
+		g_Config.m_BrFilterCompatversion ^= 1;
+
+	View.HSplitTop(20.0f, &Button, &View);
+	if (DoButton_CheckBox((char *)&g_Config.m_BrFilterPure, Localize("Standard gametype"), g_Config.m_BrFilterPure, &Button))
+		g_Config.m_BrFilterPure ^= 1;
+
+	View.HSplitTop(20.0f, &Button, &View);
+	//button.VSplitLeft(20.0f, 0, &button);
+	if (DoButton_CheckBox((char *)&g_Config.m_BrFilterPureMap, Localize("Standard map"), g_Config.m_BrFilterPureMap, &Button))
+		g_Config.m_BrFilterPureMap ^= 1;
 	
-	view.HSplitTop(20.0f, &button, &view);
-	if (DoButton_CheckBox((char *)&config.b_filter_pure, localize("Standard gametype"), config.b_filter_pure, &button))
-		config.b_filter_pure ^= 1;
-
-	view.HSplitTop(20.0f, &button, &view);
-	/*button.VSplitLeft(20.0f, 0, &button);*/
-	if (DoButton_CheckBox((char *)&config.b_filter_pure_map, localize("Standard map"), config.b_filter_pure_map, &button))
-		config.b_filter_pure_map ^= 1;
-		
-	view.HSplitTop(20.0f, &button, &view);
-	UI()->DoLabel(&button, localize("Game types"), 14.0f, -1);
-	button.VSplitLeft(95.0f, 0, &button);
-	button.Margin(1.0f, &button);
-	DoEditBox(&config.b_filter_gametype, &button, config.b_filter_gametype, sizeof(config.b_filter_gametype), 14.0f);
+	View.HSplitTop(5.0f, 0, &View);
+
+	View.HSplitTop(19.0f, &Button, &View);
+	UI()->DoLabel(&Button, Localize("Game types:"), 12.0f, -1);
+	Button.VSplitLeft(95.0f, 0, &Button);
+	View.HSplitTop(3.0f, 0, &View);
+	DoEditBox(&g_Config.m_BrFilterGametype, &Button, g_Config.m_BrFilterGametype, sizeof(g_Config.m_BrFilterGametype), 12.0f);
 
 	{
-		view.HSplitTop(20.0f, &button, &view);
-		CUIRect editbox;
-		button.VSplitLeft(40.0f, &editbox, &button);
-		button.VSplitLeft(5.0f, &button, &button);
+		View.HSplitTop(19.0f, &Button, &View);
+		CUIRect EditBox;
+		Button.VSplitRight(50.0f, &Button, &EditBox);
+		EditBox.VSplitRight(5.0f, &EditBox, 0);
 		
-		char buf[8];
-		str_format(buf, sizeof(buf), "%d", config.b_filter_ping);
-		DoEditBox(&config.b_filter_ping, &editbox, buf, sizeof(buf), 14.0f);
-		config.b_filter_ping = atoi(buf);
+		UI()->DoLabel(&Button, Localize("Maximum ping:"), 12.0f, -1);
 		
-		UI()->DoLabel(&button, localize("Maximum ping"), 14.0f, -1);
+		char aBuf[5];
+		str_format(aBuf, sizeof(aBuf), "%d", g_Config.m_BrFilterPing);
+		DoEditBox(&g_Config.m_BrFilterPing, &EditBox, aBuf, sizeof(aBuf), 12.0f);
+		g_Config.m_BrFilterPing = str_toint(aBuf);
 	}
-	
-	view.HSplitBottom(button_height, &view, &button);
-	static int clear_button = 0;
-	if(DoButton_Menu(&clear_button, localize("Reset filter"), 0, &button))
+
+	View.HSplitBottom(ms_ButtonHeight, &View, &Button);
+	static int s_ClearButton = 0;
+	if(DoButton_Menu(&s_ClearButton, Localize("Reset filter"), 0, &Button))
 	{
-		config.b_filter_full = 0;
-		config.b_filter_empty = 0;
-		config.b_filter_pw = 0;
-		config.b_filter_ping = 999;
-		config.b_filter_gametype[0] = 0;
-		config.b_filter_compatversion = 1;
-		config.b_filter_string[0] = 0;
-		config.b_filter_pure = 1;
+		g_Config.m_BrFilterFull = 0;
+		g_Config.m_BrFilterEmpty = 0;
+		g_Config.m_BrFilterPw = 0;
+		g_Config.m_BrFilterPing = 999;
+		g_Config.m_BrFilterGametype[0] = 0;
+		g_Config.m_BrFilterCompatversion = 1;
+		g_Config.m_BrFilterString[0] = 0;
+		g_Config.m_BrFilterPure = 1;
+		g_Config.m_BrFilterPureMap = 1;
 	}
 }
 
-void MENUS::render_serverbrowser_serverdetail(CUIRect view)
+void CMenus::RenderServerbrowserServerDetail(CUIRect View)
 {
-	CUIRect server_details = view;
-	CUIRect server_scoreboard, server_header;
-	
-	SERVER_INFO *selected_server = client_serverbrowse_sorted_get(selected_index);
-	
+	CUIRect ServerDetails = View;
+	CUIRect ServerScoreBoard, ServerHeader;
+
+	const CServerInfo *pSelectedServer = ServerBrowser()->SortedGet(m_SelectedIndex);
+
 	//server_details.VSplitLeft(10.0f, 0x0, &server_details);
 
 	// split off a piece to use for scoreboard
-	server_details.HSplitTop(140.0f, &server_details, &server_scoreboard);
-	server_details.HSplitBottom(10.0f, &server_details, 0x0);
+	ServerDetails.HSplitTop(140.0f, &ServerDetails, &ServerScoreBoard);
+	ServerDetails.HSplitBottom(10.0f, &ServerDetails, 0x0);
 
 	// server details
-	const float font_size = 12.0f;
-	server_details.HSplitTop(20.0f, &server_header, &server_details);
-	RenderTools()->DrawUIRect(&server_header, vec4(1,1,1,0.25f), CUI::CORNER_T, 4.0f);
-	RenderTools()->DrawUIRect(&server_details, vec4(0,0,0,0.15f), CUI::CORNER_B, 4.0f);
-	server_header.VSplitLeft(8.0f, 0x0, &server_header);
-	UI()->DoLabel(&server_header, localize("Server details"), font_size+2.0f, -1);
+	const float FontSize = 12.0f;
+	ServerDetails.HSplitTop(20.0f, &ServerHeader, &ServerDetails);
+	RenderTools()->DrawUIRect(&ServerHeader, vec4(1,1,1,0.25f), CUI::CORNER_T, 4.0f);
+	RenderTools()->DrawUIRect(&ServerDetails, vec4(0,0,0,0.15f), CUI::CORNER_B, 4.0f);
+	ServerHeader.VSplitLeft(8.0f, 0x0, &ServerHeader);
+	UI()->DoLabel(&ServerHeader, Localize("Server details"), FontSize+2.0f, -1);
 
-	server_details.VSplitLeft(5.0f, 0x0, &server_details);
+	ServerDetails.VSplitLeft(5.0f, 0x0, &ServerDetails);
 
-	server_details.Margin(3.0f, &server_details);
+	ServerDetails.Margin(3.0f, &ServerDetails);
 
-	if (selected_server)
+	if (pSelectedServer)
 	{
-		CUIRect row;
-		static LOC_CONSTSTRING labels[] = {
-			localize("Version"),
-			localize("Game type"),
-			localize("Ping")};
+		CUIRect Row;
+		static CLocConstString s_aLabels[] = {
+			Localize("Version"),
+			Localize("Game type"),
+			Localize("Ping")};
 
-		CUIRect left_column;
-		CUIRect right_column;
+		CUIRect LeftColumn;
+		CUIRect RightColumn;
 
-		// 
+		//
 		{
-			CUIRect button;
-			server_details.HSplitBottom(20.0f, &server_details, &button);
-			static int add_fav_button = 0;
-			if(DoButton_CheckBox(&add_fav_button, localize("Favorite"), selected_server->favorite, &button))
+			CUIRect Button;
+			ServerDetails.HSplitBottom(20.0f, &ServerDetails, &Button);
+			static int s_AddFavButton = 0;
+			if(DoButton_CheckBox(&s_AddFavButton, Localize("Favorite"), pSelectedServer->m_Favorite, &Button))
 			{
-				if(selected_server->favorite)
-					client_serverbrowse_removefavorite(selected_server->netaddr);
+				if(pSelectedServer->m_Favorite)
+					ServerBrowser()->RemoveFavorite(pSelectedServer->m_NetAddr);
 				else
-					client_serverbrowse_addfavorite(selected_server->netaddr);
+					ServerBrowser()->AddFavorite(pSelectedServer->m_NetAddr);
 			}
 		}
-		//UI()->DoLabel(&row, temp, font_size, -1);		
+		//UI()->DoLabel(&row, temp, font_size, -1);
 
-		server_details.VSplitLeft(5.0f, 0x0, &server_details);
-		server_details.VSplitLeft(80.0f, &left_column, &right_column);
+		ServerDetails.VSplitLeft(5.0f, 0x0, &ServerDetails);
+		ServerDetails.VSplitLeft(80.0f, &LeftColumn, &RightColumn);
 
-		for (unsigned int i = 0; i < sizeof(labels) / sizeof(labels[0]); i++)
+		for (unsigned int i = 0; i < sizeof(s_aLabels) / sizeof(s_aLabels[0]); i++)
 		{
-			left_column.HSplitTop(15.0f, &row, &left_column);
-			UI()->DoLabel(&row, labels[i], font_size, -1);
+			LeftColumn.HSplitTop(15.0f, &Row, &LeftColumn);
+			UI()->DoLabel(&Row, s_aLabels[i], FontSize, -1);
 		}
 
-		right_column.HSplitTop(15.0f, &row, &right_column);
-		UI()->DoLabel(&row, selected_server->version, font_size, -1);
+		RightColumn.HSplitTop(15.0f, &Row, &RightColumn);
+		UI()->DoLabel(&Row, pSelectedServer->m_aVersion, FontSize, -1);
 
-		right_column.HSplitTop(15.0f, &row, &right_column);
-		UI()->DoLabel(&row, selected_server->gametype, font_size, -1);
+		RightColumn.HSplitTop(15.0f, &Row, &RightColumn);
+		UI()->DoLabel(&Row, pSelectedServer->m_aGameType, FontSize, -1);
 
-		char temp[16];
-		str_format(temp, sizeof(temp), "%d", selected_server->latency);
-		right_column.HSplitTop(15.0f, &row, &right_column);
-		UI()->DoLabel(&row, temp, font_size, -1);
+		char aTemp[16];
+		str_format(aTemp, sizeof(aTemp), "%d", pSelectedServer->m_Latency);
+		RightColumn.HSplitTop(15.0f, &Row, &RightColumn);
+		UI()->DoLabel(&Row, aTemp, FontSize, -1);
 
 	}
-	
+
 	// server scoreboard
-	
-	server_scoreboard.HSplitBottom(10.0f, &server_scoreboard, 0x0);
-	server_scoreboard.HSplitTop(20.0f, &server_header, &server_scoreboard);
-	RenderTools()->DrawUIRect(&server_header, vec4(1,1,1,0.25f), CUI::CORNER_T, 4.0f);
-	RenderTools()->DrawUIRect(&server_scoreboard, vec4(0,0,0,0.15f), CUI::CORNER_B, 4.0f);
-	server_header.VSplitLeft(8.0f, 0x0, &server_header);
-	UI()->DoLabel(&server_header, localize("Scoreboard"), font_size+2.0f, -1);
 
-	server_scoreboard.VSplitLeft(5.0f, 0x0, &server_scoreboard);
+	ServerScoreBoard.HSplitBottom(10.0f, &ServerScoreBoard, 0x0);
+	ServerScoreBoard.HSplitTop(20.0f, &ServerHeader, &ServerScoreBoard);
+	RenderTools()->DrawUIRect(&ServerHeader, vec4(1,1,1,0.25f), CUI::CORNER_T, 4.0f);
+	RenderTools()->DrawUIRect(&ServerScoreBoard, vec4(0,0,0,0.15f), CUI::CORNER_B, 4.0f);
+	ServerHeader.VSplitLeft(8.0f, 0x0, &ServerHeader);
+	UI()->DoLabel(&ServerHeader, Localize("Scoreboard"), FontSize+2.0f, -1);
 
-	server_scoreboard.Margin(3.0f, &server_scoreboard);
+	ServerScoreBoard.VSplitLeft(5.0f, 0x0, &ServerScoreBoard);
 
-	if (selected_server)
+	ServerScoreBoard.Margin(3.0f, &ServerScoreBoard);
+
+	if (pSelectedServer)
 	{
-		for (int i = 0; i < selected_server->num_players; i++)
+		for (int i = 0; i < pSelectedServer->m_NumPlayers; i++)
 		{
-			CUIRect row;
-			char temp[16];
-			server_scoreboard.HSplitTop(16.0f, &row, &server_scoreboard);
+			CUIRect Row;
+			char aTemp[16];
+			ServerScoreBoard.HSplitTop(16.0f, &Row, &ServerScoreBoard);
 
-			str_format(temp, sizeof(temp), "%d", selected_server->players[i].score);
-			UI()->DoLabel(&row, temp, font_size, -1);
+			str_format(aTemp, sizeof(aTemp), "%d", pSelectedServer->m_aPlayers[i].m_Score);
+			UI()->DoLabel(&Row, aTemp, FontSize, -1);
 
-			row.VSplitLeft(25.0f, 0x0, &row);
-		
-			TEXT_CURSOR cursor;
-			gfx_text_set_cursor(&cursor, row.x, row.y, 12.0f, TEXTFLAG_RENDER);
-			
-			const char *name = selected_server->players[i].name;
-			if(config.b_filter_string[0])
+			Row.VSplitLeft(25.0f, 0x0, &Row);
+
+			CTextCursor Cursor;
+			TextRender()->SetCursor(&Cursor, Row.x, Row.y, 12.0f, TEXTFLAG_RENDER);
+
+			const char *pName = pSelectedServer->m_aPlayers[i].m_aName;
+			if(g_Config.m_BrFilterString[0])
 			{
 				// highlight the parts that matches
-				const char *s = str_find_nocase(name, config.b_filter_string);
+				const char *s = str_find_nocase(pName, g_Config.m_BrFilterString);
 				if(s)
 				{
-					gfx_text_ex(&cursor, name, (int)(s-name));
-					gfx_text_color(0.4f,0.4f,1,1);
-					gfx_text_ex(&cursor, s, strlen(config.b_filter_string));
-					gfx_text_color(1,1,1,1);
-					gfx_text_ex(&cursor, s+strlen(config.b_filter_string), -1);
+					TextRender()->TextEx(&Cursor, pName, (int)(s-pName));
+					TextRender()->TextColor(0.4f,0.4f,1,1);
+					TextRender()->TextEx(&Cursor, s, str_length(g_Config.m_BrFilterString));
+					TextRender()->TextColor(1,1,1,1);
+					TextRender()->TextEx(&Cursor, s+str_length(g_Config.m_BrFilterString), -1);
 				}
 				else
-					gfx_text_ex(&cursor, name, -1);
+					TextRender()->TextEx(&Cursor, pName, -1);
 			}
 			else
-				gfx_text_ex(&cursor, name, -1);
-			
+				TextRender()->TextEx(&Cursor, pName, -1);
+
 		}
 	}
 }
 
-void MENUS::render_serverbrowser(CUIRect main_view)
+void CMenus::RenderServerbrowser(CUIRect MainView)
 {
-	RenderTools()->DrawUIRect(&main_view, color_tabbar_active, CUI::CORNER_ALL, 10.0f);
-	
-	CUIRect view;
-	main_view.Margin(10.0f, &view);
-	
+	RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f);
+
+	CUIRect View;
+	MainView.Margin(10.0f, &View);
+
 	/*
 		+-----------------+ +------+
 		|                 | |      |
@@ -549,100 +596,103 @@ void MENUS::render_serverbrowser(CUIRect main_view)
 		+-----------------+  button
 	      status toolbar      box
 	*/
-	
-	
+
+
 	//CUIRect filters;
-	CUIRect status_toolbar;
-	CUIRect toolbox;
-	CUIRect button_box;
+	CUIRect StatusToolBox;
+	CUIRect ToolBox;
+	CUIRect ButtonBox;
 
 	// split off a piece for filters, details and scoreboard
-	view.VSplitRight(200.0f, &view, &toolbox);
-	toolbox.HSplitBottom(80.0f, &toolbox, &button_box);
-	view.HSplitBottom(button_height+5.0f, &view, &status_toolbar);
+	View.VSplitRight(200.0f, &View, &ToolBox);
+	ToolBox.HSplitBottom(80.0f, &ToolBox, &ButtonBox);
+	View.HSplitBottom(ms_ButtonHeight+5.0f, &View, &StatusToolBox);
 
-	render_serverbrowser_serverlist(view);
-	
-	static int toolbox_page = 0;
-	
-	toolbox.VSplitLeft(5.0f, 0, &toolbox);
+	RenderServerbrowserServerList(View);
+
+	int ToolboxPage = g_Config.m_UiToolboxPage;
+
+	ToolBox.VSplitLeft(5.0f, 0, &ToolBox);
 
 	// do tabbar
 	{
-		CUIRect tab_bar;
-		CUIRect tabbutton0, tabbutton1;
-		toolbox.HSplitTop(22.0f, &tab_bar, &toolbox);
-	
-		tab_bar.VSplitMid(&tabbutton0, &tabbutton1);
-		tabbutton0.VSplitRight(5.0f, &tabbutton0, 0);
-		tabbutton1.VSplitLeft(5.0f, 0, &tabbutton1);
-		
-		static int filters_tab = 0;
-		if (DoButton_MenuTab(&filters_tab, localize("Filter"), toolbox_page==0, &tabbutton0, 0))
-			toolbox_page = 0;
-			
-		static int info_tab = 0;
-		if (DoButton_MenuTab(&info_tab, localize("Info"), toolbox_page==1, &tabbutton1, 0))
-			toolbox_page = 1;
+		CUIRect TabBar;
+		CUIRect TabButton0, TabButton1;
+		ToolBox.HSplitTop(22.0f, &TabBar, &ToolBox);
+
+		TabBar.VSplitMid(&TabButton0, &TabButton1);
+		//TabButton0.VSplitRight(5.0f, &TabButton0, 0);
+		//TabButton1.VSplitLeft(5.0f, 0, &TabButton1);
+
+		static int s_FiltersTab = 0;
+		if (DoButton_MenuTab(&s_FiltersTab, Localize("Filter"), ToolboxPage==0, &TabButton0, CUI::CORNER_TL))
+			ToolboxPage = 0;
+
+		static int s_InfoTab = 0;
+		if (DoButton_MenuTab(&s_InfoTab, Localize("Info"), ToolboxPage==1, &TabButton1, CUI::CORNER_TR))
+			ToolboxPage = 1;
 	}
 
-	RenderTools()->DrawUIRect(&toolbox, vec4(0,0,0,0.15f), 0, 0);
-	
-	toolbox.HSplitTop(5.0f, 0, &toolbox);
-	
-	if(toolbox_page == 0)
-		render_serverbrowser_filters(toolbox);
-	else if(toolbox_page == 1)
-		render_serverbrowser_serverdetail(toolbox);
+	g_Config.m_UiToolboxPage = ToolboxPage;
+
+	RenderTools()->DrawUIRect(&ToolBox, vec4(0,0,0,0.15f), 0, 0);
+
+	ToolBox.HSplitTop(5.0f, 0, &ToolBox);
+
+	if(ToolboxPage == 0)
+		RenderServerbrowserFilters(ToolBox);
+	else if(ToolboxPage == 1)
+		RenderServerbrowserServerDetail(ToolBox);
 
 	{
-		status_toolbar.HSplitTop(5.0f, 0, &status_toolbar);
-		
-		CUIRect button;
+		StatusToolBox.HSplitTop(5.0f, 0, &StatusToolBox);
+
+		CUIRect Button;
 		//buttons.VSplitRight(20.0f, &buttons, &button);
-		status_toolbar.VSplitRight(110.0f, &status_toolbar, &button);
-		button.VMargin(2.0f, &button);
-		static int refresh_button = 0;
-		if(DoButton_Menu(&refresh_button, localize("Refresh"), 0, &button))
+		StatusToolBox.VSplitRight(110.0f, &StatusToolBox, &Button);
+		Button.VMargin(2.0f, &Button);
+		static int s_RefreshButton = 0;
+		if(DoButton_Menu(&s_RefreshButton, Localize("Refresh"), 0, &Button))
 		{
-			if(config.ui_page == PAGE_INTERNET)
-				client_serverbrowse_refresh(BROWSETYPE_INTERNET);
-			else if(config.ui_page == PAGE_LAN)
-				client_serverbrowse_refresh(BROWSETYPE_LAN);
-			else if(config.ui_page == PAGE_FAVORITES)
-				client_serverbrowse_refresh(BROWSETYPE_FAVORITES);
+			if(g_Config.m_UiPage == PAGE_INTERNET)
+				ServerBrowser()->Refresh(IServerBrowser::TYPE_INTERNET);
+			else if(g_Config.m_UiPage == PAGE_LAN)
+				ServerBrowser()->Refresh(IServerBrowser::TYPE_LAN);
+			else if(g_Config.m_UiPage == PAGE_FAVORITES)
+				ServerBrowser()->Refresh(IServerBrowser::TYPE_FAVORITES);
 		}
-		
-		char buf[512];
-		if(strcmp(client_latestversion(), "0") != 0)
-			str_format(buf, sizeof(buf), localize("Teeworlds %s is out! Download it at www.teeworlds.com!"), client_latestversion());
+
+		char aBuf[512];
+		if(str_comp(Client()->LatestVersion(), "0") != 0)
+			str_format(aBuf, sizeof(aBuf), Localize("Teeworlds %s is out! Download it at www.teeworlds.com!"), Client()->LatestVersion());
 		else
-			str_format(buf, sizeof(buf), localize("Current version: %s"), GAME_VERSION);
-		UI()->DoLabel(&status_toolbar, buf, 14.0f, -1);
+			str_format(aBuf, sizeof(aBuf), Localize("Current version: %s"), GAME_VERSION);
+		UI()->DoLabel(&StatusToolBox, aBuf, 14.0f, -1);
 	}
-	
+
 	// do the button box
 	{
-		
-		button_box.VSplitLeft(5.0f, 0, &button_box);
-		button_box.VSplitRight(5.0f, &button_box, 0);
-		
-		CUIRect button;
-		button_box.HSplitBottom(button_height, &button_box, &button);
-		button.VSplitRight(120.0f, 0, &button);
-		button.VMargin(2.0f, &button);
+
+		ButtonBox.VSplitLeft(5.0f, 0, &ButtonBox);
+		ButtonBox.VSplitRight(5.0f, &ButtonBox, 0);
+
+		CUIRect Button;
+		ButtonBox.HSplitBottom(ms_ButtonHeight, &ButtonBox, &Button);
+		Button.VSplitRight(120.0f, 0, &Button);
+		Button.VMargin(2.0f, &Button);
 		//button.VMargin(2.0f, &button);
-		static int join_button = 0;
-		if(DoButton_Menu(&join_button, localize("Connect"), 0, &button) || enter_pressed)
+		static int s_JoinButton = 0;
+		if(DoButton_Menu(&s_JoinButton, Localize("Connect"), 0, &Button) || m_EnterPressed)
 		{
-			client_connect(config.ui_server_address);
-			enter_pressed = false;
+			dbg_msg("", "%s", g_Config.m_UiServerAddress);
+			Client()->Connect(g_Config.m_UiServerAddress);
+			m_EnterPressed = false;
 		}
-					
-		button_box.HSplitBottom(5.0f, &button_box, &button);
-		button_box.HSplitBottom(20.0f, &button_box, &button);
-		DoEditBox(&config.ui_server_address, &button, config.ui_server_address, sizeof(config.ui_server_address), 14.0f);
-		button_box.HSplitBottom(20.0f, &button_box, &button);
-		UI()->DoLabel(&button, localize("Host address"), 14.0f, -1);
+
+		ButtonBox.HSplitBottom(5.0f, &ButtonBox, &Button);
+		ButtonBox.HSplitBottom(20.0f, &ButtonBox, &Button);
+		DoEditBox(&g_Config.m_UiServerAddress, &Button, g_Config.m_UiServerAddress, sizeof(g_Config.m_UiServerAddress), 14.0f);
+		ButtonBox.HSplitBottom(20.0f, &ButtonBox, &Button);
+		UI()->DoLabel(&Button, Localize("Host address"), 14.0f, -1);
 	}
 }
diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp
index 07019d46..62c03a92 100644
--- a/src/game/client/components/menus_demo.cpp
+++ b/src/game/client/components/menus_demo.cpp
@@ -1,86 +1,82 @@
 
-#include <base/math.hpp>
+#include <base/math.h>
 
-//#include <string.h> // strcmp, strlen, strncpy
-//#include <stdlib.h> // atoi
 
-#include <engine/e_client_interface.h>
-#include <game/client/render.hpp>
-#include <game/client/gameclient.hpp>
+#include <engine/demo.h>
+#include <engine/keys.h>
 
-//#include <game/generated/g_protocol.hpp>
-//#include <game/generated/gc_data.hpp>
+#include <game/client/render.h>
+#include <game/client/gameclient.h>
+#include <game/localization.h>
 
-#include <game/client/ui.hpp>
-//#include <game/client/gameclient.hpp>
-//#include <game/client/animstate.hpp>
+#include <game/client/ui.h>
 
-#include "menus.hpp"
+#include "menus.h"
 
-int MENUS::DoButton_DemoPlayer(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
+int CMenus::DoButton_DemoPlayer(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
 {
-	RenderTools()->DrawUIRect(pRect, vec4(1,1,1, Checked ? 0.10f : 0.5f)*button_color_mul(pID), CUI::CORNER_ALL, 5.0f);
+	RenderTools()->DrawUIRect(pRect, vec4(1,1,1, Checked ? 0.10f : 0.5f)*ButtonColorMul(pID), CUI::CORNER_ALL, 5.0f);
 	UI()->DoLabel(pRect, pText, 14.0f, 0);
 	return UI()->DoButtonLogic(pID, pText, Checked, pRect);
 }
 
-void MENUS::render_demoplayer(CUIRect main_view)
+void CMenus::RenderDemoPlayer(CUIRect MainView)
 {
-	const DEMOPLAYBACK_INFO *info = client_demoplayer_getinfo();
+	const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo();
 	
-	const float seekbar_height = 15.0f;
-	const float buttonbar_height = 20.0f;
-	const float margins = 5.0f;
-	float total_height;
+	const float SeekBarHeight = 15.0f;
+	const float ButtonbarHeight = 20.0f;
+	const float Margins = 5.0f;
+	float TotalHeight;
 	
-	if(menu_active)
-		total_height = seekbar_height+buttonbar_height+margins*3;
+	if(m_MenuActive)
+		TotalHeight = SeekBarHeight+ButtonbarHeight+Margins*3;
 	else
-		total_height = seekbar_height+margins*2;
+		TotalHeight = SeekBarHeight+Margins*2;
 	
-	main_view.HSplitBottom(total_height, 0, &main_view);
-	main_view.VSplitLeft(250.0f, 0, &main_view);
-	main_view.VSplitRight(250.0f, &main_view, 0);
+	MainView.HSplitBottom(TotalHeight, 0, &MainView);
+	MainView.VSplitLeft(250.0f, 0, &MainView);
+	MainView.VSplitRight(250.0f, &MainView, 0);
 	
-	RenderTools()->DrawUIRect(&main_view, color_tabbar_active, CUI::CORNER_T, 10.0f);
+	RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_T, 10.0f);
 		
-	main_view.Margin(5.0f, &main_view);
+	MainView.Margin(5.0f, &MainView);
 	
-	CUIRect seekbar, buttonbar;
+	CUIRect SeekBar, ButtonBar;
 	
-	if(menu_active)
+	if(m_MenuActive)
 	{
-		main_view.HSplitTop(seekbar_height, &seekbar, &buttonbar);
-		buttonbar.HSplitTop(margins, 0, &buttonbar);
+		MainView.HSplitTop(SeekBarHeight, &SeekBar, &ButtonBar);
+		ButtonBar.HSplitTop(Margins, 0, &ButtonBar);
 	}
 	else
-		seekbar = main_view;
+		SeekBar = MainView;
 
 	// do seekbar
 	{
-		static int seekbar_id = 0;
-		void *id = &seekbar_id;
-		char buffer[128];
+		static int s_SeekBarId = 0;
+		void *id = &s_SeekBarId;
+		char aBuffer[128];
 		
-		RenderTools()->DrawUIRect(&seekbar, vec4(0,0,0,0.5f), CUI::CORNER_ALL, 5.0f);
+		RenderTools()->DrawUIRect(&SeekBar, vec4(0,0,0,0.5f), CUI::CORNER_ALL, 5.0f);
 		
-		int current_tick = info->current_tick - info->first_tick;
-		int total_ticks = info->last_tick - info->first_tick;
+		int CurrentTick = pInfo->m_CurrentTick - pInfo->m_FirstTick;
+		int TotalTicks = pInfo->m_LastTick - pInfo->m_FirstTick;
 		
-		float amount = current_tick/(float)total_ticks;
+		float Amount = CurrentTick/(float)TotalTicks;
 		
-		CUIRect filledbar = seekbar;
-		filledbar.w = 10.0f + (filledbar.w-10.0f)*amount;
+		CUIRect FilledBar = SeekBar;
+		FilledBar.w = 10.0f + (FilledBar.w-10.0f)*Amount;
 		
-		RenderTools()->DrawUIRect(&filledbar, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 5.0f);
+		RenderTools()->DrawUIRect(&FilledBar, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 5.0f);
 		
-		str_format(buffer, sizeof(buffer), "%d:%02d / %d:%02d",
-			current_tick/SERVER_TICK_SPEED/60, (current_tick/SERVER_TICK_SPEED)%60,
-			total_ticks/SERVER_TICK_SPEED/60, (total_ticks/SERVER_TICK_SPEED)%60);
-		UI()->DoLabel(&seekbar, buffer, seekbar.h*0.70f, 0);
+		str_format(aBuffer, sizeof(aBuffer), "%d:%02d / %d:%02d",
+			CurrentTick/SERVER_TICK_SPEED/60, (CurrentTick/SERVER_TICK_SPEED)%60,
+			TotalTicks/SERVER_TICK_SPEED/60, (TotalTicks/SERVER_TICK_SPEED)%60);
+		UI()->DoLabel(&SeekBar, aBuffer, SeekBar.h*0.70f, 0);
 
 		// do the logic
-	    int inside = UI()->MouseInside(&seekbar);
+	    int Inside = UI()->MouseInside(&SeekBar);
 			
 		if(UI()->ActiveItem() == id)
 		{
@@ -88,13 +84,15 @@ void MENUS::render_demoplayer(CUIRect main_view)
 				UI()->SetActiveItem(0);
 			else
 			{
-				float amount = (UI()->MouseX()-seekbar.x)/(float)seekbar.w;
-				if(amount > 0 && amount < 1.0f)
+				static float PrevAmount = 0.0f;
+				float Amount = (UI()->MouseX()-SeekBar.x)/(float)SeekBar.w;
+				if(Amount > 0 && Amount < 1.0f && PrevAmount != Amount)
 				{
-					gameclient.on_reset();
-					gameclient.suppress_events = true;
-					client_demoplayer_setpos(amount);
-					gameclient.suppress_events = false;
+					PrevAmount = Amount;
+					m_pClient->OnReset();
+					m_pClient->m_SuppressEvents = true;
+					DemoPlayer()->SetPos(Amount);
+					m_pClient->m_SuppressEvents = false;
 				}
 			}
 		}
@@ -104,334 +102,357 @@ void MENUS::render_demoplayer(CUIRect main_view)
 				UI()->SetActiveItem(id);
 		}		
 		
-		if(inside)
+		if(Inside)
 			UI()->SetHotItem(id);
 	}	
 	
 
-	if(menu_active)
+	if(m_MenuActive)
 	{
 		// do buttons
-		CUIRect button;
+		CUIRect Button;
 
 		// pause button
-		buttonbar.VSplitLeft(buttonbar_height, &button, &buttonbar);
-		static int pause_button = 0;
-		if(DoButton_DemoPlayer(&pause_button, "| |", info->paused, &button))
-			client_demoplayer_setpause(!info->paused);
+		ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
+		static int s_PauseButton = 0;
+		if(DoButton_DemoPlayer(&s_PauseButton, "| |", pInfo->m_Paused, &Button))
+		{
+			if(pInfo->m_Paused)
+				DemoPlayer()->Unpause();
+			else
+				DemoPlayer()->Pause();
+		}
 		
 		// play button
-		buttonbar.VSplitLeft(margins, 0, &buttonbar);
-		buttonbar.VSplitLeft(buttonbar_height, &button, &buttonbar);
-		static int play_button = 0;
-		if(DoButton_DemoPlayer(&play_button, ">", !info->paused, &button))
+		ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
+		ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
+		static int s_PlayButton = 0;
+		if(DoButton_DemoPlayer(&s_PlayButton, ">", !pInfo->m_Paused, &Button))
 		{
-			client_demoplayer_setpause(0);
-			client_demoplayer_setspeed(1.0f);
+			DemoPlayer()->Unpause();
+			DemoPlayer()->SetSpeed(1.0f);
 		}
 
 		// slowdown
-		buttonbar.VSplitLeft(margins, 0, &buttonbar);
-		buttonbar.VSplitLeft(buttonbar_height, &button, &buttonbar);
-		static int slowdown_button = 0;
-		if(DoButton_DemoPlayer(&slowdown_button, "<<", 0, &button))
+		ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
+		ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
+		static int s_SlowDownButton = 0;
+		if(DoButton_DemoPlayer(&s_SlowDownButton, "<<", 0, &Button))
 		{
-			if(info->speed > 4.0f) client_demoplayer_setspeed(4.0f);
-			else if(info->speed > 2.0f) client_demoplayer_setspeed(2.0f);
-			else if(info->speed > 1.0f) client_demoplayer_setspeed(1.0f);
-			else if(info->speed > 0.5f) client_demoplayer_setspeed(0.5f);
-			else client_demoplayer_setspeed(0.05f);
+			if(pInfo->m_Speed > 4.0f) DemoPlayer()->SetSpeed(4.0f);
+			else if(pInfo->m_Speed > 2.0f) DemoPlayer()->SetSpeed(2.0f);
+			else if(pInfo->m_Speed > 1.0f) DemoPlayer()->SetSpeed(1.0f);
+			else if(pInfo->m_Speed > 0.5f) DemoPlayer()->SetSpeed(0.5f);
+			else DemoPlayer()->SetSpeed(0.05f);
 		}
 		
 		// fastforward
-		buttonbar.VSplitLeft(margins, 0, &buttonbar);
-		buttonbar.VSplitLeft(buttonbar_height, &button, &buttonbar);
-		static int fastforward_button = 0;
-		if(DoButton_DemoPlayer(&fastforward_button, ">>", 0, &button))
+		ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
+		ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
+		static int s_FastForwardButton = 0;
+		if(DoButton_DemoPlayer(&s_FastForwardButton, ">>", 0, &Button))
 		{
-			if(info->speed < 0.5f) client_demoplayer_setspeed(0.5f);
-			else if(info->speed < 1.0f) client_demoplayer_setspeed(1.0f);
-			else if(info->speed < 2.0f) client_demoplayer_setspeed(2.0f);
-			else if(info->speed < 4.0f) client_demoplayer_setspeed(4.0f);
-			else client_demoplayer_setspeed(8.0f);
+			if(pInfo->m_Speed < 0.5f) DemoPlayer()->SetSpeed(0.5f);
+			else if(pInfo->m_Speed < 1.0f) DemoPlayer()->SetSpeed(1.0f);
+			else if(pInfo->m_Speed < 2.0f) DemoPlayer()->SetSpeed(2.0f);
+			else if(pInfo->m_Speed < 4.0f) DemoPlayer()->SetSpeed(4.0f);
+			else DemoPlayer()->SetSpeed(8.0f);
 		}
 
 		// speed meter
-		buttonbar.VSplitLeft(margins*3, 0, &buttonbar);
-		char buffer[64];
-		if(info->speed >= 1.0f)
-			str_format(buffer, sizeof(buffer), "x%.0f", info->speed);
+		ButtonBar.VSplitLeft(Margins*3, 0, &ButtonBar);
+		char aBuffer[64];
+		if(pInfo->m_Speed >= 1.0f)
+			str_format(aBuffer, sizeof(aBuffer), "x%.0f", pInfo->m_Speed);
 		else
-			str_format(buffer, sizeof(buffer), "x%.1f", info->speed);
-		UI()->DoLabel(&buttonbar, buffer, button.h*0.7f, -1);
+			str_format(aBuffer, sizeof(aBuffer), "x%.1f", pInfo->m_Speed);
+		UI()->DoLabel(&ButtonBar, aBuffer, Button.h*0.7f, -1);
 
 		// close button
-		buttonbar.VSplitRight(buttonbar_height*3, &buttonbar, &button);
-		static int exit_button = 0;
-		if(DoButton_DemoPlayer(&exit_button, localize("Close"), 0, &button))
-			client_disconnect();
+		ButtonBar.VSplitRight(ButtonbarHeight*3, &ButtonBar, &Button);
+		static int s_ExitButton = 0;
+		if(DoButton_DemoPlayer(&s_ExitButton, Localize("Close"), 0, &Button))
+			Client()->Disconnect();
 	}
 }
 
-static CUIRect listbox_originalview;
-static CUIRect listbox_view;
-static float listbox_rowheight;
-static int listbox_itemindex;
-static int listbox_selected_index;
-static int listbox_new_selected;
-static int listbox_doneevents;
-static int listbox_numitems;
-
-void MENUS::ui_do_listbox_start(void *id, const CUIRect *rect, float row_height, const char *title, int num_items, int selected_index)
+static CUIRect gs_ListBoxOriginalView;
+static CUIRect gs_ListBoxView;
+static float gs_ListBoxRowHeight;
+static int gs_ListBoxItemIndex;
+static int gs_ListBoxSelectedIndex;
+static int gs_ListBoxNewSelected;
+static int gs_ListBoxDoneEvents;
+static int gs_ListBoxNumItems;
+static int gs_ListBoxItemsPerRow;
+static float gs_ListBoxScrollValue;
+static bool gs_ListBoxItemActivated;
+
+void CMenus::UiDoListboxStart(void *pId, const CUIRect *pRect, float RowHeight, const char *pTitle, const char *pBottomText, int NumItems,
+								int ItemsPerRow, int SelectedIndex, float ScrollValue)
 {
-	CUIRect scroll, row;
-	CUIRect view = *rect;
-	CUIRect header, footer;
+	CUIRect Scroll, Row;
+	CUIRect View = *pRect;
+	CUIRect Header, Footer;
 	
 	// draw header
-	view.HSplitTop(listheader_height, &header, &view);
-	RenderTools()->DrawUIRect(&header, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f); 
-	UI()->DoLabel(&header, title, header.h*fontmod_height, 0);
+	View.HSplitTop(ms_ListheaderHeight, &Header, &View);
+	RenderTools()->DrawUIRect(&Header, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f); 
+	UI()->DoLabel(&Header, pTitle, Header.h*ms_FontmodHeight, 0);
 
 	// draw footers
-	view.HSplitBottom(listheader_height, &view, &footer);
-	RenderTools()->DrawUIRect(&footer, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f); 
-	footer.VSplitLeft(10.0f, 0, &footer);
+	View.HSplitBottom(ms_ListheaderHeight, &View, &Footer);
+	RenderTools()->DrawUIRect(&Footer, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f); 
+	Footer.VSplitLeft(10.0f, 0, &Footer);
+	UI()->DoLabel(&Footer, pBottomText, Header.h*ms_FontmodHeight, 0);
 
 	// background
-	RenderTools()->DrawUIRect(&view, vec4(0,0,0,0.15f), 0, 0);
+	RenderTools()->DrawUIRect(&View, vec4(0,0,0,0.15f), 0, 0);
 
 	// prepare the scroll
-	view.VSplitRight(15, &view, &scroll);
+	View.VSplitRight(15, &View, &Scroll);
 
 	// setup the variables	
-	listbox_originalview = view;
-	listbox_selected_index = selected_index;
-	listbox_new_selected = selected_index;
-	listbox_itemindex = 0;
-	listbox_rowheight = row_height;
-	listbox_numitems = num_items;
-	listbox_doneevents = 0;
-	//int num_servers = client_serverbrowse_sorted_num();
-
+	gs_ListBoxOriginalView = View;
+	gs_ListBoxSelectedIndex = SelectedIndex;
+	gs_ListBoxNewSelected = SelectedIndex;
+	gs_ListBoxItemIndex = 0;
+	gs_ListBoxRowHeight = RowHeight;
+	gs_ListBoxNumItems = NumItems;
+	gs_ListBoxItemsPerRow = ItemsPerRow;
+	gs_ListBoxDoneEvents = 0;
+	gs_ListBoxScrollValue = ScrollValue;
+	gs_ListBoxItemActivated = false;
 
 	// do the scrollbar
-	view.HSplitTop(listbox_rowheight, &row, 0);
+	View.HSplitTop(gs_ListBoxRowHeight, &Row, 0);
 	
-	int num_viewable = (int)(listbox_originalview.h/row.h) + 1;
-	int num = num_items-num_viewable+1;
-	if(num < 0)
-		num = 0;
+	int NumViewable = (int)(gs_ListBoxOriginalView.h/Row.h) + 1;
+	int Num = (NumItems+gs_ListBoxItemsPerRow-1)/gs_ListBoxItemsPerRow-NumViewable+1;
+	if(Num < 0)
+		Num = 0;
+	if(Num > 0)
+	{
+		if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP))
+			gs_ListBoxScrollValue -= 1.0f/Num;
+		if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN))
+			gs_ListBoxScrollValue += 1.0f/Num;
 		
-	static float scrollvalue = 0;
-	scroll.HMargin(5.0f, &scroll);
-	scrollvalue = DoScrollbarV(id, &scroll, scrollvalue);
-
-	int start = (int)(num*scrollvalue);
-	if(start < 0)
-		start = 0;
+		if(gs_ListBoxScrollValue < 0.0f) gs_ListBoxScrollValue = 0.0f;
+		if(gs_ListBoxScrollValue > 1.0f) gs_ListBoxScrollValue = 1.0f;
+	}
+		
+	Scroll.HMargin(5.0f, &Scroll);
+	gs_ListBoxScrollValue = DoScrollbarV(pId, &Scroll, gs_ListBoxScrollValue);
 	
 	// the list
-	listbox_view = listbox_originalview;
-	listbox_view.VMargin(5.0f, &listbox_view);
-	UI()->ClipEnable(&listbox_view);
-	listbox_view.y -= scrollvalue*num*row.h;	
+	gs_ListBoxView = gs_ListBoxOriginalView;
+	gs_ListBoxView.VMargin(5.0f, &gs_ListBoxView);
+	UI()->ClipEnable(&gs_ListBoxView);
+	gs_ListBoxView.y -= gs_ListBoxScrollValue*Num*Row.h;
 }
 
-MENUS::LISTBOXITEM MENUS::ui_do_listbox_nextrow()
+CMenus::CListboxItem CMenus::UiDoListboxNextRow()
 {
-	LISTBOXITEM item = {0};
-	listbox_view.HSplitTop(listbox_rowheight /*-2.0f*/, &item.rect, &listbox_view);
-	item.visible = 1;
+	static CUIRect s_RowView;
+	CListboxItem Item = {0};
+	if(gs_ListBoxItemIndex%gs_ListBoxItemsPerRow == 0)
+		gs_ListBoxView.HSplitTop(gs_ListBoxRowHeight /*-2.0f*/, &s_RowView, &gs_ListBoxView);
+
+	s_RowView.VSplitLeft(s_RowView.w/(gs_ListBoxItemsPerRow-gs_ListBoxItemIndex%gs_ListBoxItemsPerRow), &Item.m_Rect, &s_RowView);
+
+	Item.m_Visible = 1;
 	//item.rect = row;
 	
-	item.hitrect = item.rect;
+	Item.m_HitRect = Item.m_Rect;
 	
 	//CUIRect select_hit_box = item.rect;
 
-	if(listbox_selected_index == listbox_itemindex)
-		item.selected = 1;
+	if(gs_ListBoxSelectedIndex == gs_ListBoxItemIndex)
+		Item.m_Selected = 1;
 	
 	// make sure that only those in view can be selected
-	if(item.rect.y+item.rect.h > listbox_originalview.y)
+	if(Item.m_Rect.y+Item.m_Rect.h > gs_ListBoxOriginalView.y)
 	{
 		
-		if(item.hitrect.y < item.hitrect.y) // clip the selection
+		if(Item.m_HitRect.y < Item.m_HitRect.y) // clip the selection
 		{
-			item.hitrect.h -= listbox_originalview.y-item.hitrect.y;
-			item.hitrect.y = listbox_originalview.y;
+			Item.m_HitRect.h -= gs_ListBoxOriginalView.y-Item.m_HitRect.y;
+			Item.m_HitRect.y = gs_ListBoxOriginalView.y;
 		}
 		
 	}
 	else
-		item.visible = 0;
+		Item.m_Visible = 0;
 
 	// check if we need to do more
-	if(item.rect.y > listbox_originalview.y+listbox_originalview.h)
-		item.visible = 0;
+	if(Item.m_Rect.y > gs_ListBoxOriginalView.y+gs_ListBoxOriginalView.h)
+		Item.m_Visible = 0;
 		
-	listbox_itemindex++;
-	return item;
+	gs_ListBoxItemIndex++;
+	return Item;
 }
 
-MENUS::LISTBOXITEM MENUS::ui_do_listbox_nextitem(void *id)
+CMenus::CListboxItem CMenus::UiDoListboxNextItem(void *pId, bool Selected)
 {
-	int this_itemindex = listbox_itemindex;
-	
-	LISTBOXITEM item = ui_do_listbox_nextrow();
-
-	if(UI()->DoButtonLogic(id, "", listbox_selected_index == listbox_itemindex, &item.hitrect))
-		listbox_new_selected = listbox_itemindex;
-	
-	//CUIRect row;
-	//LISTBOXITEM item = {0};
-	//listbox_view.HSplitTop(listbox_rowheight /*-2.0f*/, &row, &listbox_view);
-	//listbox_view.HSplitTop(2.0f, 0, &listbox_view);
-	/*
-	CUIRect select_hit_box = row;
-
-	item.visible = 1;
-	if(listbox_selected_index == listbox_itemindex)
-		item.selected = 1;
-	
-	// make sure that only those in view can be selected
-	if(row.y+row.h > listbox_originalview.y)
+	int ThisItemIndex = gs_ListBoxItemIndex;
+	if(Selected)
 	{
-		
-		if(select_hit_box.y < listbox_originalview.y) // clip the selection
-		{
-			select_hit_box.h -= listbox_originalview.y-select_hit_box.y;
-			select_hit_box.y = listbox_originalview.y;
-		}
-		
-		if(UI()->DoButton(id, "", listbox_selected_index==listbox_itemindex, &select_hit_box, 0, 0))
-			listbox_new_selected = listbox_itemindex;
+		if(gs_ListBoxSelectedIndex == gs_ListBoxNewSelected)
+			gs_ListBoxNewSelected = ThisItemIndex;
+		gs_ListBoxSelectedIndex = ThisItemIndex;
 	}
-	else
-		item.visible = 0;
-	
-	item.rect = row;
-	*/
 	
+	CListboxItem Item = UiDoListboxNextRow();
 
-	if(listbox_selected_index == this_itemindex)
+	if(Item.m_Visible && UI()->DoButtonLogic(pId, "", gs_ListBoxSelectedIndex == gs_ListBoxItemIndex, &Item.m_HitRect))
+		gs_ListBoxNewSelected = ThisItemIndex;
+	
+	// process input, regard selected index
+	if(gs_ListBoxSelectedIndex == ThisItemIndex)
 	{
-		if(!listbox_doneevents)
+		if(!gs_ListBoxDoneEvents)
 		{
-			listbox_doneevents = 1;
-			
-			for(int i = 0; i < num_inputevents; i++)
+			gs_ListBoxDoneEvents = 1;
+
+			if(m_EnterPressed || (Input()->MouseDoubleClick() && UI()->ActiveItem() == pId))
 			{
-				if(inputevents[i].flags&INPFLAG_PRESS)
+				gs_ListBoxItemActivated = true;
+			}
+			else
+			{			
+				for(int i = 0; i < m_NumInputEvents; i++)
 				{
-					if(inputevents[i].key == KEY_DOWN) listbox_new_selected++;
-					if(inputevents[i].key == KEY_UP) listbox_new_selected--;
+					int NewIndex = -1;
+					if(m_aInputEvents[i].m_Flags&IInput::FLAG_PRESS)
+					{
+						if(m_aInputEvents[i].m_Key == KEY_DOWN) NewIndex = gs_ListBoxNewSelected + 1;
+						if(m_aInputEvents[i].m_Key == KEY_UP) NewIndex = gs_ListBoxNewSelected - 1;
+					}
+					if(NewIndex > -1 && NewIndex < gs_ListBoxNumItems)
+					{
+						// scroll
+						int NumViewable = (int)(gs_ListBoxOriginalView.h/gs_ListBoxRowHeight) + 1;
+						int ScrollNum = (gs_ListBoxNumItems+gs_ListBoxItemsPerRow-1)/gs_ListBoxItemsPerRow-NumViewable+1;
+						if(ScrollNum > 0 && NewIndex/gs_ListBoxItemsPerRow-gs_ListBoxSelectedIndex/gs_ListBoxItemsPerRow)
+						{
+							// TODO: make the scrolling better
+							if(NewIndex - gs_ListBoxSelectedIndex > 0)
+								gs_ListBoxScrollValue += 1.0f/ScrollNum;
+							else
+								gs_ListBoxScrollValue -= 1.0f/ScrollNum;
+							if(gs_ListBoxScrollValue < 0.0f) gs_ListBoxScrollValue = 0.0f;
+							if(gs_ListBoxScrollValue > 1.0f) gs_ListBoxScrollValue = 1.0f;
+						}
+						
+						gs_ListBoxNewSelected = NewIndex;
+					}
 				}
 			}
-
-			if(listbox_new_selected >= listbox_numitems)
-				listbox_new_selected = listbox_numitems-1;
-			if(listbox_new_selected < 0)
-				listbox_new_selected = 0;
 		}
 		
 		//selected_index = i;
-		CUIRect r = item.rect;
+		CUIRect r = Item.m_Rect;
 		r.Margin(1.5f, &r);
 		RenderTools()->DrawUIRect(&r, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 4.0f);
 	}	
 
-	//listbox_itemindex++;
-	return item;
+	return Item;
 }
 
-int MENUS::ui_do_listbox_end()
+int CMenus::UiDoListboxEnd(float *pScrollValue, bool *pItemActivated)
 {
 	UI()->ClipDisable();
-	return listbox_new_selected;
+	if(pScrollValue)
+		*pScrollValue = gs_ListBoxScrollValue;
+	if(pItemActivated)
+		*pItemActivated = gs_ListBoxItemActivated;
+	return gs_ListBoxNewSelected;
 }
 
 struct FETCH_CALLBACKINFO
 {
-	MENUS *self;
-	const char *prefix;
-	int count;
+	CMenus *m_pSelf;
+	const char *m_pPrefix;
+	int m_Count;
 };
 
-void MENUS::demolist_fetch_callback(const char *name, int is_dir, void *user)
+void CMenus::DemolistFetchCallback(const char *pName, int IsDir, void *pUser)
 {
-	if(is_dir || name[0] == '.')
+	if(IsDir || pName[0] == '.')
 		return;
 			
-	FETCH_CALLBACKINFO *info = (FETCH_CALLBACKINFO *)user;
+	FETCH_CALLBACKINFO *pInfo = (FETCH_CALLBACKINFO *)pUser;
 	
-	DEMOITEM item;
-	str_format(item.filename, sizeof(item.filename), "%s/%s", info->prefix, name);
-	str_copy(item.name, name, sizeof(item.name));
-	info->self->demos.add(item);
+	CDemoItem Item;
+	str_format(Item.m_aFilename, sizeof(Item.m_aFilename), "%s/%s", pInfo->m_pPrefix, pName);
+	str_copy(Item.m_aName, pName, sizeof(Item.m_aName));
+	pInfo->m_pSelf->m_lDemos.add(Item);
 }
 
-void MENUS::demolist_populate()
+void CMenus::DemolistPopulate()
 {
-	demos.clear();
+	m_lDemos.clear();
 	
-	char buf[512];
-	str_format(buf, sizeof(buf), "%s/demos", client_user_directory());
+	char aBuf[512];
+	str_format(aBuf, sizeof(aBuf), "%s/demos", Client()->UserDirectory());
 
-	FETCH_CALLBACKINFO info = {this, buf, 0};
-	fs_listdir(buf, demolist_fetch_callback, &info);
-	info.prefix = "demos";
-	fs_listdir("demos", demolist_fetch_callback, &info);
+	FETCH_CALLBACKINFO Info = {this, aBuf, 0};
+	fs_listdir(aBuf, DemolistFetchCallback, &Info);
+	Info.m_pPrefix = "demos";
+	fs_listdir("demos", DemolistFetchCallback, &Info);
 }
 
 
-void MENUS::render_demolist(CUIRect main_view)
+void CMenus::RenderDemoList(CUIRect MainView)
 {
-	static int inited = 0;
-	if(!inited)
-		demolist_populate();
-	inited = 1;
+	static int s_Inited = 0;
+	if(!s_Inited)
+		DemolistPopulate();
+	s_Inited = 1;
 	
 	// render background
-	RenderTools()->DrawUIRect(&main_view, color_tabbar_active, CUI::CORNER_ALL, 10.0f);
-	main_view.Margin(10.0f, &main_view);
+	RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f);
+	MainView.Margin(10.0f, &MainView);
 	
-	CUIRect buttonbar;
-	main_view.HSplitBottom(button_height+5.0f, &main_view, &buttonbar);
-	buttonbar.HSplitTop(5.0f, 0, &buttonbar);
+	CUIRect ButtonBar;
+	MainView.HSplitBottom(ms_ButtonHeight+5.0f, &MainView, &ButtonBar);
+	ButtonBar.HSplitTop(5.0f, 0, &ButtonBar);
 	
-	static int selected_item = -1;
-	static int demolist_id = 0;
+	static int s_SelectedItem = -1;
+	static int s_DemoListId = 0;
+	static float s_ScrollValue = 0;
 	
-	ui_do_listbox_start(&demolist_id, &main_view, 17.0f, localize("Demos"), demos.size(), selected_item);
+	UiDoListboxStart(&s_DemoListId, &MainView, 17.0f, Localize("Demos"), "", m_lDemos.size(), 1, s_SelectedItem, s_ScrollValue);
 	//for(int i = 0; i < num_demos; i++)
-	for(sorted_array<DEMOITEM>::range r = demos.all(); !r.empty(); r.pop_front())
+	for(sorted_array<CDemoItem>::range r = m_lDemos.all(); !r.empty(); r.pop_front())
 	{
-		LISTBOXITEM item = ui_do_listbox_nextitem((void*)(&r.front()));
-		if(item.visible)
-			UI()->DoLabel(&item.rect, r.front().name, item.rect.h*fontmod_height, -1);
+		CListboxItem Item = UiDoListboxNextItem((void*)(&r.front()));
+		if(Item.m_Visible)
+			UI()->DoLabel(&Item.m_Rect, r.front().m_aName, Item.m_Rect.h*ms_FontmodHeight, -1);
 	}
-	selected_item = ui_do_listbox_end();
-	
-	CUIRect refresh_rect, play_rect;
-	buttonbar.VSplitRight(250.0f, &buttonbar, &refresh_rect);
-	refresh_rect.VSplitRight(130.0f, &refresh_rect, &play_rect);
-	play_rect.VSplitRight(120.0f, 0x0, &play_rect);
+	bool Activated = false;
+	s_SelectedItem = UiDoListboxEnd(&s_ScrollValue, &Activated);
 	
-	static int refresh_button = 0;
-	if(DoButton_Menu(&refresh_button, localize("Refresh"), 0, &refresh_rect))
-	{
-		demolist_populate();
-	}	
+	CUIRect RefreshRect, PlayRect;
+	ButtonBar.VSplitRight(250.0f, &ButtonBar, &RefreshRect);
+	RefreshRect.VSplitRight(130.0f, &RefreshRect, &PlayRect);
+	PlayRect.VSplitRight(120.0f, 0x0, &PlayRect);
 	
-	static int play_button = 0;
-	if(DoButton_Menu(&play_button, localize("Play"), 0, &play_rect))
+	static int s_RefreshButton = 0;
+	if(DoButton_Menu(&s_RefreshButton, Localize("Refresh"), 0, &RefreshRect))
 	{
-		if(selected_item >= 0 && selected_item < demos.size())
+		DemolistPopulate();
+	}
+		
+	static int s_PlayButton = 0;
+	if(DoButton_Menu(&s_PlayButton, Localize("Play"), 0, &PlayRect) || Activated)
+	{		
+		if(s_SelectedItem >= 0 && s_SelectedItem < m_lDemos.size())
 		{
-			const char *error = client_demoplayer_play(demos[selected_item].filename);
-			if(error)
-				popup_message(localize("Error"), error, localize("Ok"));
+			const char *pError = Client()->DemoPlayer_Play(m_lDemos[s_SelectedItem].m_aFilename);
+			if(pError)
+				PopupMessage(Localize("Error"), pError, Localize("Ok"));
 		}
 	}
 	
diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp
index d31a15bd..7d1f2513 100644
--- a/src/game/client/components/menus_ingame.cpp
+++ b/src/game/client/components/menus_ingame.cpp
@@ -1,89 +1,90 @@
 
-#include <base/math.hpp>
+#include <base/math.h>
 
-#include <string.h> // strcmp, strlen, strncpy
-#include <stdlib.h> // atoi
 
-#include <engine/e_client_interface.h>
+#include <engine/serverbrowser.h>
+#include <engine/textrender.h>
+#include <engine/shared/config.h>
 
-#include <game/generated/g_protocol.hpp>
-#include <game/generated/gc_data.hpp>
+#include <game/generated/protocol.h>
+#include <game/generated/client_data.h>
 
-#include <game/client/ui.hpp>
-#include <game/client/gameclient.hpp>
-#include <game/client/animstate.hpp>
+#include <game/client/ui.h>
+#include <game/client/gameclient.h>
+#include <game/client/animstate.h>
+#include <game/localization.h>
 
-#include "menus.hpp"
-#include "motd.hpp"
-#include "voting.hpp"
+#include "menus.h"
+#include "motd.h"
+#include "voting.h"
 
-void MENUS::render_game(CUIRect main_view)
+void CMenus::RenderGame(CUIRect MainView)
 {
-	CUIRect button;
+	CUIRect Button;
 	//CUIRect votearea;
-	main_view.HSplitTop(45.0f, &main_view, 0);
-	RenderTools()->DrawUIRect(&main_view, color_tabbar_active, CUI::CORNER_ALL, 10.0f);
+	MainView.HSplitTop(45.0f, &MainView, 0);
+	RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f);
 
-	main_view.HSplitTop(10.0f, 0, &main_view);
-	main_view.HSplitTop(25.0f, &main_view, 0);
-	main_view.VMargin(10.0f, &main_view);
+	MainView.HSplitTop(10.0f, 0, &MainView);
+	MainView.HSplitTop(25.0f, &MainView, 0);
+	MainView.VMargin(10.0f, &MainView);
 	
-	main_view.VSplitRight(120.0f, &main_view, &button);
-	static int disconnect_button = 0;
-	if(DoButton_Menu(&disconnect_button, localize("Disconnect"), 0, &button))
-		client_disconnect();
+	MainView.VSplitRight(120.0f, &MainView, &Button);
+	static int s_DisconnectButton = 0;
+	if(DoButton_Menu(&s_DisconnectButton, Localize("Disconnect"), 0, &Button))
+		Client()->Disconnect();
 
-	if(gameclient.snap.local_info && gameclient.snap.gameobj)
+	if(m_pClient->m_Snap.m_pLocalInfo && m_pClient->m_Snap.m_pGameobj)
 	{
-		if(gameclient.snap.local_info->team != -1)
+		if(m_pClient->m_Snap.m_pLocalInfo->m_Team != -1)
 		{
-			main_view.VSplitLeft(10.0f, &button, &main_view);
-			main_view.VSplitLeft(120.0f, &button, &main_view);
-			static int spectate_button = 0;
-			if(DoButton_Menu(&spectate_button, localize("Spectate"), 0, &button))
+			MainView.VSplitLeft(10.0f, &Button, &MainView);
+			MainView.VSplitLeft(120.0f, &Button, &MainView);
+			static int s_SpectateButton = 0;
+			if(DoButton_Menu(&s_SpectateButton, Localize("Spectate"), 0, &Button))
 			{
-				gameclient.send_switch_team(-1);
-				set_active(false);
+				m_pClient->SendSwitchTeam(-1);
+				SetActive(false);
 			}
 		}
 		
-		if(gameclient.snap.gameobj->flags & GAMEFLAG_TEAMS)
+		if(m_pClient->m_Snap.m_pGameobj->m_Flags & GAMEFLAG_TEAMS)
 		{
-			if(gameclient.snap.local_info->team != 0)
+			if(m_pClient->m_Snap.m_pLocalInfo->m_Team != 0)
 			{
-				main_view.VSplitLeft(10.0f, &button, &main_view);
-				main_view.VSplitLeft(120.0f, &button, &main_view);
-				static int spectate_button = 0;
-				if(DoButton_Menu(&spectate_button, localize("Join red"), 0, &button))
+				MainView.VSplitLeft(10.0f, &Button, &MainView);
+				MainView.VSplitLeft(120.0f, &Button, &MainView);
+				static int s_SpectateButton = 0;
+				if(DoButton_Menu(&s_SpectateButton, Localize("Join red"), 0, &Button))
 				{
-					gameclient.send_switch_team(0);
-					set_active(false);
+					m_pClient->SendSwitchTeam(0);
+					SetActive(false);
 				}
 			}
 
-			if(gameclient.snap.local_info->team != 1)
+			if(m_pClient->m_Snap.m_pLocalInfo->m_Team != 1)
 			{
-				main_view.VSplitLeft(10.0f, &button, &main_view);
-				main_view.VSplitLeft(120.0f, &button, &main_view);
-				static int spectate_button = 0;
-				if(DoButton_Menu(&spectate_button, localize("Join blue"), 0, &button))
+				MainView.VSplitLeft(10.0f, &Button, &MainView);
+				MainView.VSplitLeft(120.0f, &Button, &MainView);
+				static int s_SpectateButton = 0;
+				if(DoButton_Menu(&s_SpectateButton, Localize("Join blue"), 0, &Button))
 				{
-					gameclient.send_switch_team(1);
-					set_active(false);
+					m_pClient->SendSwitchTeam(1);
+					SetActive(false);
 				}
 			}
 		}
 		else
 		{
-			if(gameclient.snap.local_info->team != 0)
+			if(m_pClient->m_Snap.m_pLocalInfo->m_Team != 0)
 			{
-				main_view.VSplitLeft(10.0f, &button, &main_view);
-				main_view.VSplitLeft(120.0f, &button, &main_view);
-				static int spectate_button = 0;
-				if(DoButton_Menu(&spectate_button, localize("Join game"), 0, &button))
+				MainView.VSplitLeft(10.0f, &Button, &MainView);
+				MainView.VSplitLeft(120.0f, &Button, &MainView);
+				static int s_SpectateButton = 0;
+				if(DoButton_Menu(&s_SpectateButton, Localize("Join game"), 0, &Button))
 				{
-					gameclient.send_switch_team(0);
-					set_active(false);
+					m_pClient->SendSwitchTeam(0);
+					SetActive(false);
 				}
 			}
 		}
@@ -141,102 +142,102 @@ void MENUS::render_game(CUIRect main_view)
 	}*/
 }
 
-void MENUS::render_serverinfo(CUIRect main_view)
+void CMenus::RenderServerInfo(CUIRect MainView)
 {
 	// fetch server info
-	SERVER_INFO current_server_info;
-	client_serverinfo(&current_server_info);
+	CServerInfo CurrentServerInfo;
+	Client()->GetServerInfo(&CurrentServerInfo);
 	
-	if(!gameclient.snap.local_info)
+	if(!m_pClient->m_Snap.m_pLocalInfo)
 		return;
 	
 	// count players for server info-box
-	int num_players = 0;
-	for(int i = 0; i < snap_num_items(SNAP_CURRENT); i++)
+	int NumPlayers = 0;
+	for(int i = 0; i < Client()->SnapNumItems(IClient::SNAP_CURRENT); i++)
 	{
-		SNAP_ITEM item;
-		snap_get_item(SNAP_CURRENT, i, &item);
+		IClient::CSnapItem Item;
+		Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item);
 
-		if(item.type == NETOBJTYPE_PLAYER_INFO)
+		if(Item.m_Type == NETOBJTYPE_PLAYERINFO)
 		{
-			num_players++;
+			NumPlayers++;
 		}
 	}
 
 	// render background
-	RenderTools()->DrawUIRect(&main_view, color_tabbar_active, CUI::CORNER_ALL, 10.0f);
+	RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f);
 	
-	CUIRect view, serverinfo, gameinfo, motd;
+	CUIRect View, ServerInfo, GameInfo, Motd;
 	
 	float x = 0.0f;
 	float y = 0.0f;
 	
-	char buf[1024];
+	char aBuf[1024];
 	
 	// set view to use for all sub-modules
-	main_view.Margin(10.0f, &view);
+	MainView.Margin(10.0f, &View);
 	
-	/* serverinfo */
-	view.HSplitTop(view.h/2-5.0f, &serverinfo, &motd);
-	serverinfo.VSplitLeft(view.w/2-5.0f, &serverinfo, &gameinfo);
-	RenderTools()->DrawUIRect(&serverinfo, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
+	// serverinfo
+	View.HSplitTop(View.h/2-5.0f, &ServerInfo, &Motd);
+	ServerInfo.VSplitLeft(View.w/2-5.0f, &ServerInfo, &GameInfo);
+	RenderTools()->DrawUIRect(&ServerInfo, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
 	
-	serverinfo.Margin(5.0f, &serverinfo);
+	ServerInfo.Margin(5.0f, &ServerInfo);
 	
 	x = 5.0f;
 	y = 0.0f;
 	
-	gfx_text(0, serverinfo.x+x, serverinfo.y+y, 32, localize("Server info"), 250);
+	TextRender()->Text(0, ServerInfo.x+x, ServerInfo.y+y, 32, Localize("Server info"), 250);
 	y += 32.0f+5.0f;
 	
-	mem_zero(buf, sizeof(buf));
+	mem_zero(aBuf, sizeof(aBuf));
 	str_format(
-		buf,
-		sizeof(buf),
+		aBuf,
+		sizeof(aBuf),
 		"%s\n\n"
 		"%s: %s\n"
 		"%s: %d\n"
 		"%s: %s\n"
 		"%s: %s\n",
-		current_server_info.name,
-		localize("Address"), config.ui_server_address,
-		localize("Ping"), gameclient.snap.local_info->latency,
-		localize("Version"), current_server_info.version,
-		localize("Password"), current_server_info.flags&1 ? localize("Yes") : localize("No")
+		CurrentServerInfo.m_aName,
+		Localize("Address"), g_Config.m_UiServerAddress,
+		Localize("Ping"), m_pClient->m_Snap.m_pLocalInfo->m_Latency,
+		Localize("Version"), CurrentServerInfo.m_aVersion,
+		Localize("Password"), CurrentServerInfo.m_Flags &1 ? Localize("Yes") : Localize("No")
 	);
 	
-	gfx_text(0, serverinfo.x+x, serverinfo.y+y, 20, buf, 250);
+	TextRender()->Text(0, ServerInfo.x+x, ServerInfo.y+y, 20, aBuf, 250);
 	
 	{
-		CUIRect button;
-		int is_favorite = client_serverbrowse_isfavorite(current_server_info.netaddr);
-		serverinfo.HSplitBottom(20.0f, &serverinfo, &button);
-		static int add_fav_button = 0;
-		if(DoButton_CheckBox(&add_fav_button, localize("Favorite"), is_favorite, &button))
+		CUIRect Button;
+		int IsFavorite = ServerBrowser()->IsFavorite(CurrentServerInfo.m_NetAddr);
+		ServerInfo.HSplitBottom(20.0f, &ServerInfo, &Button);
+		static int s_AddFavButton = 0;
+		if(DoButton_CheckBox(&s_AddFavButton, Localize("Favorite"), IsFavorite, &Button))
 		{
-			if(is_favorite)
-				client_serverbrowse_removefavorite(current_server_info.netaddr);
+			if(IsFavorite)
+				ServerBrowser()->RemoveFavorite(CurrentServerInfo.m_NetAddr);
 			else
-				client_serverbrowse_addfavorite(current_server_info.netaddr);
+				ServerBrowser()->AddFavorite(CurrentServerInfo.m_NetAddr);
 		}
 	}
 	
-	/* gameinfo */
-	gameinfo.VSplitLeft(10.0f, 0x0, &gameinfo);
-	RenderTools()->DrawUIRect(&gameinfo, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
+	// gameinfo
+	GameInfo.VSplitLeft(10.0f, 0x0, &GameInfo);
+	RenderTools()->DrawUIRect(&GameInfo, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
 	
-	gameinfo.Margin(5.0f, &gameinfo);
+	GameInfo.Margin(5.0f, &GameInfo);
 	
 	x = 5.0f;
 	y = 0.0f;
 	
-	gfx_text(0, gameinfo.x+x, gameinfo.y+y, 32, localize("Game info"), 250);
+	TextRender()->Text(0, GameInfo.x+x, GameInfo.y+y, 32, Localize("Game info"), 250);
 	y += 32.0f+5.0f;
 	
-	mem_zero(buf, sizeof(buf));
+	mem_zero(aBuf, sizeof(aBuf));
 	str_format(
-		buf,
-		sizeof(buf),
+		aBuf,
+		sizeof(aBuf),
 		"\n\n"
 		"%s: %s\n"
 		"%s: %s\n"
@@ -244,153 +245,178 @@ void MENUS::render_serverinfo(CUIRect main_view)
 		"%s: %d\n"
 		"\n"
 		"%s: %d/%d\n",
-		localize("Game type"), current_server_info.gametype,
-		localize("Map"), current_server_info.map,
-		localize("Score limit"), gameclient.snap.gameobj->score_limit,
-		localize("Time limit"), gameclient.snap.gameobj->time_limit,
-		localize("Players"), gameclient.snap.num_players, current_server_info.max_players
+		Localize("Game type"), CurrentServerInfo.m_aGameType,
+		Localize("Map"), CurrentServerInfo.m_aMap,
+		Localize("Score limit"), m_pClient->m_Snap.m_pGameobj->m_ScoreLimit,
+		Localize("Time limit"), m_pClient->m_Snap.m_pGameobj->m_TimeLimit,
+		Localize("Players"), m_pClient->m_Snap.m_NumPlayers, CurrentServerInfo.m_MaxPlayers
 	);
-	gfx_text(0, gameinfo.x+x, gameinfo.y+y, 20, buf, 250);
+	TextRender()->Text(0, GameInfo.x+x, GameInfo.y+y, 20, aBuf, 250);
 	
-	/* motd */
-	motd.HSplitTop(10.0f, 0, &motd);
-	RenderTools()->DrawUIRect(&motd, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
-	motd.Margin(5.0f, &motd);
+	// motd
+	Motd.HSplitTop(10.0f, 0, &Motd);
+	RenderTools()->DrawUIRect(&Motd, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
+	Motd.Margin(5.0f, &Motd);
 	y = 0.0f;
 	x = 5.0f;
-	gfx_text(0, motd.x+x, motd.y+y, 32, localize("MOTD"), -1);
+	TextRender()->Text(0, Motd.x+x, Motd.y+y, 32, Localize("MOTD"), -1);
 	y += 32.0f+5.0f;
-	gfx_text(0, motd.x+x, motd.y+y, 16, gameclient.motd->server_motd, (int)motd.w);
+	TextRender()->Text(0, Motd.x+x, Motd.y+y, 16, m_pClient->m_pMotd->m_aServerMotd, (int)Motd.w);
 }
 
-static const char *format_command(const char *cmd)
+static const char *FormatCommand(const char *pCmd)
 {
-	return cmd;
+	return pCmd;
 }
 
-void MENUS::render_servercontrol_server(CUIRect main_view)
+void CMenus::RenderServerControlServer(CUIRect MainView)
 {
-	int num_options = 0;
-	for(VOTING::VOTEOPTION *option = gameclient.voting->first; option; option = option->next)
-		num_options++;
-
-	static int votelist = 0;
-	CUIRect list = main_view;
-	ui_do_listbox_start(&votelist, &list, 24.0f, localize("Settings"), num_options, callvote_selectedoption);
+	int NumOptions = 0;
+	for(CVoting::CVoteOption *pOption = m_pClient->m_pVoting->m_pFirst; pOption; pOption = pOption->m_pNext)
+		NumOptions++;
+
+	static int s_VoteList = 0;
+	static float s_ScrollValue = 0;
+	CUIRect List = MainView;
+	UiDoListboxStart(&s_VoteList, &List, 24.0f, Localize("Settings"), "", NumOptions, 1, m_CallvoteSelectedOption, s_ScrollValue);
 	
-	for(VOTING::VOTEOPTION *option = gameclient.voting->first; option; option = option->next)
+	for(CVoting::CVoteOption *pOption = m_pClient->m_pVoting->m_pFirst; pOption; pOption = pOption->m_pNext)
 	{
-		LISTBOXITEM item = ui_do_listbox_nextitem(option);
+		CListboxItem Item = UiDoListboxNextItem(pOption);
 		
-		if(item.visible)
-			UI()->DoLabel(&item.rect, format_command(option->command), 16.0f, -1);
+		if(Item.m_Visible)
+			UI()->DoLabel(&Item.m_Rect, FormatCommand(pOption->m_aCommand), 16.0f, -1);
 	}
 	
-	callvote_selectedoption = ui_do_listbox_end();
+	m_CallvoteSelectedOption = UiDoListboxEnd(&s_ScrollValue, 0);
 }
 
-void MENUS::render_servercontrol_kick(CUIRect main_view)
+void CMenus::RenderServerControlKick(CUIRect MainView)
 {
 	// draw header
-	CUIRect header, footer;
-	main_view.HSplitTop(20, &header, &main_view);
-	RenderTools()->DrawUIRect(&header, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f); 
-	UI()->DoLabel(&header, localize("Players"), 18.0f, 0);
+	CUIRect Header, Footer;
+	MainView.HSplitTop(20, &Header, &MainView);
+	RenderTools()->DrawUIRect(&Header, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f); 
+	UI()->DoLabel(&Header, Localize("Players"), 18.0f, 0);
 
 	// draw footers	
-	main_view.HSplitBottom(20, &main_view, &footer);
-	RenderTools()->DrawUIRect(&footer, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f); 
-	footer.VSplitLeft(10.0f, 0, &footer);
+	MainView.HSplitBottom(20, &MainView, &Footer);
+	RenderTools()->DrawUIRect(&Footer, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f); 
+	Footer.VSplitLeft(10.0f, 0, &Footer);
 
 	// players
-	RenderTools()->DrawUIRect(&main_view, vec4(0,0,0,0.15f), 0, 0);
-	CUIRect list = main_view;
+	RenderTools()->DrawUIRect(&MainView, vec4(0,0,0,0.15f), 0, 0);
+	CUIRect List = MainView;
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
-		if(!gameclient.snap.player_infos[i])
+		if(!m_pClient->m_Snap.m_paPlayerInfos[i])
 			continue;
 
-		CUIRect button;
-		list.HSplitTop(button_height, &button, &list);
+		CUIRect Button;
+		List.HSplitTop(ms_ButtonHeight, &Button, &List);
 		
-		if(DoButton_ListRow((char *)&gameclient.snap+i, "", callvote_selectedplayer == i, &button))
-			callvote_selectedplayer = i;
+		if(DoButton_ListRow((char *)&m_pClient->m_Snap+i, "", m_CallvoteSelectedPlayer == i, &Button))
+			m_CallvoteSelectedPlayer = i;
 
-		TEE_RENDER_INFO info = gameclient.clients[i].render_info;
-		info.size = button.h;
-		RenderTools()->RenderTee(ANIMSTATE::get_idle(), &info, EMOTE_NORMAL, vec2(1,0), vec2(button.x+button.h/2, button.y+button.h/2));
+		CTeeRenderInfo Info = m_pClient->m_aClients[i].m_RenderInfo;
+		Info.m_Size = Button.h;
+		RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1,0), vec2(Button.x+Button.h/2, Button.y+Button.h/2));
 
-		button.x += button.h;
-		UI()->DoLabel(&button, gameclient.clients[i].name, 18.0f, -1);
+		Button.x += Button.h;
+		UI()->DoLabel(&Button, m_pClient->m_aClients[i].m_aName, 18.0f, -1);
 	}
 }
 
-void MENUS::render_servercontrol(CUIRect main_view)
+void CMenus::RenderServerControl(CUIRect MainView)
 {
-	static int control_page = 0;
+	static int s_ControlPage = 0;
 	
 	// render background
-	CUIRect temp, tabbar;
-	main_view.VSplitRight(120.0f, &main_view, &tabbar);
-	RenderTools()->DrawUIRect(&main_view, color_tabbar_active, CUI::CORNER_B|CUI::CORNER_TL, 10.0f);
-	tabbar.HSplitTop(50.0f, &temp, &tabbar);
-	RenderTools()->DrawUIRect(&temp, color_tabbar_active, CUI::CORNER_R, 10.0f);
+	CUIRect Temp, TabBar;
+	MainView.VSplitRight(120.0f, &MainView, &TabBar);
+	RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_B|CUI::CORNER_TL, 10.0f);
+	TabBar.HSplitTop(50.0f, &Temp, &TabBar);
+	RenderTools()->DrawUIRect(&Temp, ms_ColorTabbarActive, CUI::CORNER_R, 10.0f);
 	
-	main_view.HSplitTop(10.0f, 0, &main_view);
+	MainView.HSplitTop(10.0f, 0, &MainView);
 	
-	CUIRect button;
+	CUIRect Button;
 	
-	const char *tabs[] = {
-		localize("Settings"),
-		localize("Kick")};
-	int num_tabs = (int)(sizeof(tabs)/sizeof(*tabs));
+	const char *paTabs[] = {
+		Localize("Settings"),
+		Localize("Kick")};
+	int aNumTabs = (int)(sizeof(paTabs)/sizeof(*paTabs));
 	
-	for(int i = 0; i < num_tabs; i++)
+	for(int i = 0; i < aNumTabs; i++)
 	{
-		tabbar.HSplitTop(10, &button, &tabbar);
-		tabbar.HSplitTop(26, &button, &tabbar);
-		if(DoButton_SettingsTab(tabs[i], tabs[i], control_page == i, &button))
+		TabBar.HSplitTop(10, &Button, &TabBar);
+		TabBar.HSplitTop(26, &Button, &TabBar);
+		if(DoButton_SettingsTab(paTabs[i], paTabs[i], s_ControlPage == i, &Button))
 		{
-			control_page = i;
-			callvote_selectedplayer = -1;
-			callvote_selectedoption = -1;
+			s_ControlPage = i;
+			m_CallvoteSelectedPlayer = -1;
+			m_CallvoteSelectedOption = -1;
 		}
 	}
 		
-	main_view.Margin(10.0f, &main_view);
-	CUIRect bottom;
-	main_view.HSplitBottom(button_height + 5*2, &main_view, &bottom);
-	bottom.HMargin(5.0f, &bottom);
+	MainView.Margin(10.0f, &MainView);
+	CUIRect Bottom;
+	MainView.HSplitBottom(ms_ButtonHeight + 5*2, &MainView, &Bottom);
+	Bottom.HMargin(5.0f, &Bottom);
 	
 	// render page		
-	if(control_page == 0)
-		render_servercontrol_server(main_view);
-	else if(control_page == 1)
-		render_servercontrol_kick(main_view);
+	if(s_ControlPage == 0)
+		RenderServerControlServer(MainView);
+	else if(s_ControlPage == 1)
+		RenderServerControlKick(MainView);
 		
 
 	{
-		CUIRect button;
-		bottom.VSplitRight(120.0f, &bottom, &button);
+		CUIRect Button;
+		Bottom.VSplitRight(120.0f, &Bottom, &Button);
 		
-		static int callvote_button = 0;
-		if(DoButton_Menu(&callvote_button, localize("Call vote"), 0, &button))
+		static int s_CallVoteButton = 0;
+		if(DoButton_Menu(&s_CallVoteButton, Localize("Call vote"), 0, &Button))
 		{
-			if(control_page == 0)
+			if(s_ControlPage == 0)
 			{
 				//
-				gameclient.voting->callvote_option(callvote_selectedoption);
+				m_pClient->m_pVoting->CallvoteOption(m_CallvoteSelectedOption);
 				/*
 				if(callvote_selectedmap >= 0 && callvote_selectedmap < gameclient.maplist->num())
 					gameclient.voting->callvote_map(gameclient.maplist->name(callvote_selectedmap));*/
 			}
-			else if(control_page == 1)
+			else if(s_ControlPage == 1)
+			{
+				if(m_CallvoteSelectedPlayer >= 0 && m_CallvoteSelectedPlayer < MAX_CLIENTS &&
+					m_pClient->m_Snap.m_paPlayerInfos[m_CallvoteSelectedPlayer])
+				{
+					m_pClient->m_pVoting->CallvoteKick(m_CallvoteSelectedPlayer);
+					SetActive(false);
+				}
+			}
+		}
+
+		// force vote button (only available when authed in rcon)
+		if(Client()->RconAuthed())
+		{
+			Bottom.VSplitLeft(120.0f, &Button, &Bottom);
+			
+			static int s_ForceVoteButton = 0;
+			if(DoButton_Menu(&s_ForceVoteButton, Localize("Force vote"), 0, &Button))
 			{
-				if(callvote_selectedplayer >= 0 && callvote_selectedplayer < MAX_CLIENTS &&
-					gameclient.snap.player_infos[callvote_selectedplayer])
+				if(s_ControlPage == 0)
+				{
+					m_pClient->m_pVoting->ForcevoteOption(m_CallvoteSelectedOption);
+				}
+				else if(s_ControlPage == 1)
 				{
-					gameclient.voting->callvote_kick(callvote_selectedplayer);
-					set_active(false);
+					if(m_CallvoteSelectedPlayer >= 0 && m_CallvoteSelectedPlayer < MAX_CLIENTS &&
+						m_pClient->m_Snap.m_paPlayerInfos[m_CallvoteSelectedPlayer])
+					{
+						m_pClient->m_pVoting->ForcevoteKick(m_CallvoteSelectedPlayer);
+						SetActive(false);
+					}
 				}
 			}
 		}
diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp
index 05b4d047..a612ed77 100644
--- a/src/game/client/components/menus_settings.cpp
+++ b/src/game/client/components/menus_settings.cpp
@@ -1,821 +1,752 @@
 
-#include <base/math.hpp>
+#include <base/math.h>
 
-#include <string.h> // strcmp, strlen, strncpy
-#include <stdlib.h> // atoi
 
-#include <engine/e_client_interface.h>
-#include <engine/client/graphics.h>
+#include <engine/graphics.h>
+#include <engine/textrender.h>
+#include <engine/shared/config.h>
 
-#include <game/generated/g_protocol.hpp>
-#include <game/generated/gc_data.hpp>
+#include <game/generated/protocol.h>
+#include <game/generated/client_data.h>
 
-#include <game/client/ui.hpp>
-#include <game/client/render.hpp>
-#include <game/client/gameclient.hpp>
-#include <game/client/animstate.hpp>
-#include <game/localization.hpp>
+#include <game/client/ui.h>
+#include <game/client/render.h>
+#include <game/client/gameclient.h>
+#include <game/client/animstate.h>
+#include <game/localization.h>
 
-#include "binds.hpp"
-#include "menus.hpp"
-#include "skins.hpp"
+#include "binds.h"
+#include "menus.h"
+#include "skins.h"
 
-MENUS_KEYBINDER MENUS::binder;
+CMenusKeyBinder CMenus::m_Binder;
 
-MENUS_KEYBINDER::MENUS_KEYBINDER()
+CMenusKeyBinder::CMenusKeyBinder()
 {
-	take_key = false;
-	got_key = false;
+	m_TakeKey = false;
+	m_GotKey = false;
 }
 
-bool MENUS_KEYBINDER::on_input(INPUT_EVENT e)
+bool CMenusKeyBinder::OnInput(IInput::CEvent Event)
 {
-	if(take_key)
+	if(m_TakeKey)
 	{
-		if(e.flags&INPFLAG_PRESS && e.key != KEY_ESCAPE)
+		if(Event.m_Flags&IInput::FLAG_PRESS && Event.m_Key != KEY_ESCAPE)
 		{
-			key = e;
-			got_key = true;
-			take_key = false;
+			m_Key = Event;
+			m_GotKey = true;
+			m_TakeKey = false;
 		}
 		return true;
 	}
-	
+
 	return false;
 }
 
-void MENUS::render_settings_player(CUIRect main_view)
+void CMenus::RenderSettingsPlayer(CUIRect MainView)
 {
-	CUIRect button;
-	CUIRect othersection;
-	main_view.VSplitLeft(300.0f, &main_view, &othersection);
-	main_view.HSplitTop(20.0f, &button, &main_view);
+	CUIRect Button;
+	CUIRect LeftView, RightView;
+
+	MainView.VSplitLeft(MainView.w/2, &LeftView, &RightView);
+    LeftView.HSplitTop(20.0f, &Button, &LeftView);
 
 	// render settings
-	{	
-		char buf[128];
-		
-		main_view.HSplitTop(20.0f, &button, &main_view);
-		str_format(buf, sizeof(buf), "%s:", localize("Name"));
-		UI()->DoLabel(&button, buf, 14.0, -1);
-		button.VSplitLeft(80.0f, 0, &button);
-		button.VSplitLeft(180.0f, &button, 0);
-		if(DoEditBox(config.player_name, &button, config.player_name, sizeof(config.player_name), 14.0f))
-			need_sendinfo = true;
+	{
+		char aBuf[128];
+
+		LeftView.HSplitTop(20.0f, &Button, &LeftView);
+		str_format(aBuf, sizeof(aBuf), "%s:", Localize("Name"));
+		UI()->DoLabel(&Button, aBuf, 14.0, -1);
+		Button.VSplitLeft(80.0f, 0, &Button);
+		Button.VSplitLeft(180.0f, &Button, 0);
+		if(DoEditBox(g_Config.m_PlayerName, &Button, g_Config.m_PlayerName, sizeof(g_Config.m_PlayerName), 14.0f))
+			m_NeedSendinfo = true;
 
 		// extra spacing
-		main_view.HSplitTop(10.0f, 0, &main_view);
+		LeftView.HSplitTop(10.0f, 0, &LeftView);
 
-		static int dynamic_camera_button = 0;
-		main_view.HSplitTop(20.0f, &button, &main_view);
-		if(DoButton_CheckBox(&dynamic_camera_button, localize("Dynamic Camera"), config.cl_mouse_deadzone != 0, &button))
+		static int s_DynamicCameraButton = 0;
+		LeftView.HSplitTop(20.0f, &Button, &LeftView);
+		if(DoButton_CheckBox(&s_DynamicCameraButton, Localize("Dynamic Camera"), g_Config.m_ClMouseDeadzone != 0, &Button))
 		{
-			
-			if(config.cl_mouse_deadzone)
+
+			if(g_Config.m_ClMouseDeadzone)
 			{
-				config.cl_mouse_followfactor = 0;
-				config.cl_mouse_max_distance = 400;
-				config.cl_mouse_deadzone = 0;
+				g_Config.m_ClMouseFollowfactor = 0;
+				g_Config.m_ClMouseMaxDistance = 400;
+				g_Config.m_ClMouseDeadzone = 0;
 			}
 			else
 			{
-				config.cl_mouse_followfactor = 60;
-				config.cl_mouse_max_distance = 1000;
-				config.cl_mouse_deadzone = 300;
+				g_Config.m_ClMouseFollowfactor = 60;
+				g_Config.m_ClMouseMaxDistance = 1000;
+				g_Config.m_ClMouseDeadzone = 300;
 			}
 		}
 
-		main_view.HSplitTop(20.0f, &button, &main_view);
-		if(DoButton_CheckBox(&config.cl_autoswitch_weapons, localize("Switch weapon on pickup"), config.cl_autoswitch_weapons, &button))
-			config.cl_autoswitch_weapons ^= 1;
-			
-		main_view.HSplitTop(20.0f, &button, &main_view);
-		if(DoButton_CheckBox(&config.cl_nameplates, localize("Show name plates"), config.cl_nameplates, &button))
-			config.cl_nameplates ^= 1;
+		LeftView.HSplitTop(20.0f, &Button, &LeftView);
+		if(DoButton_CheckBox(&g_Config.m_ClAutoswitchWeapons, Localize("Switch weapon on pickup"), g_Config.m_ClAutoswitchWeapons, &Button))
+			g_Config.m_ClAutoswitchWeapons ^= 1;
+
+		LeftView.HSplitTop(20.0f, &Button, &LeftView);
+		if(DoButton_CheckBox(&g_Config.m_ClNameplates, Localize("Show name plates"), g_Config.m_ClNameplates, &Button))
+			g_Config.m_ClNameplates ^= 1;
 
 		//if(config.cl_nameplates)
 		{
-			main_view.HSplitTop(20.0f, &button, &main_view);
-			button.VSplitLeft(15.0f, 0, &button);
-			if(DoButton_CheckBox(&config.cl_nameplates_always, localize("Always show name plates"), config.cl_nameplates_always, &button))
-				config.cl_nameplates_always ^= 1;
+			LeftView.HSplitTop(20.0f, &Button, &LeftView);
+			Button.VSplitLeft(15.0f, 0, &Button);
+			if(DoButton_CheckBox(&g_Config.m_ClNameplatesAlways, Localize("Always show name plates"), g_Config.m_ClNameplatesAlways, &Button))
+				g_Config.m_ClNameplatesAlways ^= 1;
 		}
-			
-		main_view.HSplitTop(20.0f, &button, &main_view);
-		
-		main_view.HSplitTop(20.0f, &button, &main_view);
-		if(DoButton_CheckBox(&config.player_color_body, localize("Custom colors"), config.player_use_custom_color, &button))
+
+        {
+            const CSkins::CSkin *pOwnSkin = m_pClient->m_pSkins->Get(max(0, m_pClient->m_pSkins->Find(g_Config.m_PlayerSkin)));
+
+            CTeeRenderInfo OwnSkinInfo;
+            OwnSkinInfo.m_Texture = pOwnSkin->m_OrgTexture;
+            OwnSkinInfo.m_ColorBody = vec4(1, 1, 1, 1);
+            OwnSkinInfo.m_ColorFeet = vec4(1, 1, 1, 1);
+
+            if(g_Config.m_PlayerUseCustomColor)
+            {
+                OwnSkinInfo.m_ColorBody = m_pClient->m_pSkins->GetColor(g_Config.m_PlayerColorBody);
+                OwnSkinInfo.m_ColorFeet = m_pClient->m_pSkins->GetColor(g_Config.m_PlayerColorFeet);
+                OwnSkinInfo.m_Texture = pOwnSkin->m_ColorTexture;
+            }
+
+            OwnSkinInfo.m_Size = UI()->Scale()*50.0f;
+
+            LeftView.HSplitTop(20.0f, &Button, &LeftView);
+            LeftView.HSplitTop(20.0f, &Button, &LeftView);
+
+            str_format(aBuf, sizeof(aBuf), "%s:", Localize("Your skin"));
+            UI()->DoLabel(&Button, aBuf, 14.0, -1);
+
+            CUIRect SkinRect;
+            LeftView.VSplitLeft(LeftView.w/1.2f, &SkinRect, 0);
+            SkinRect.HSplitTop(50.0f, &SkinRect, 0);
+            RenderTools()->DrawUIRect(&SkinRect, vec4(1, 1, 1, 0.25f), CUI::CORNER_ALL, 10.0f);
+
+            Button.VSplitLeft(30.0f, 0, &Button);
+            Button.HSplitTop(50.0f, 0, &Button);
+            RenderTools()->RenderTee(CAnimState::GetIdle(), &OwnSkinInfo, 0, vec2(1, 0), vec2(Button.x, Button.y));
+
+            LeftView.HSplitTop(20.0f, &Button, &LeftView);
+            Button.HSplitTop(15.0f, 0, &Button);
+            Button.VSplitLeft(100.0f, 0, &Button);
+
+            str_format(aBuf, sizeof(aBuf), "%s", g_Config.m_PlayerSkin);
+            UI()->DoLabel(&Button, aBuf, 14.0, -1);
+        }
+
+		RightView.HSplitTop(20.0f, &Button, &RightView);
+		RightView.HSplitTop(20.0f, &Button, &RightView);
+
+		if(DoButton_CheckBox(&g_Config.m_PlayerColorBody, Localize("Custom colors"), g_Config.m_PlayerUseCustomColor, &Button))
 		{
-			config.player_use_custom_color = config.player_use_custom_color?0:1;
-			need_sendinfo = true;
+			g_Config.m_PlayerUseCustomColor = g_Config.m_PlayerUseCustomColor?0:1;
+			m_NeedSendinfo = true;
 		}
-		
-		if(config.player_use_custom_color)
+
+		if(g_Config.m_PlayerUseCustomColor)
 		{
-			int *colors[2];
-			colors[0] = &config.player_color_body;
-			colors[1] = &config.player_color_feet;
-			
-			const char *parts[] = {
-				localize("Body"),
-				localize("Feet")};
-			const char *labels[] = {
-				localize("Hue"),
-				localize("Sat."),
-				localize("Lht.")};
-			static int color_slider[2][3] = {{0}};
+			int *paColors[2];
+			paColors[0] = &g_Config.m_PlayerColorBody;
+			paColors[1] = &g_Config.m_PlayerColorFeet;
+
+			const char *paParts[] = {
+				Localize("Body"),
+				Localize("Feet")};
+			const char *paLabels[] = {
+				Localize("Hue"),
+				Localize("Sat."),
+				Localize("Lht.")};
+			static int s_aColorSlider[2][3] = {{0}};
 			//static float v[2][3] = {{0, 0.5f, 0.25f}, {0, 0.5f, 0.25f}};
-				
+
 			for(int i = 0; i < 2; i++)
 			{
-				CUIRect text;
-				main_view.HSplitTop(20.0f, &text, &main_view);
-				text.VSplitLeft(15.0f, 0, &text);
-				UI()->DoLabel(&text, parts[i], 14.0f, -1);
-				
-				int prevcolor = *colors[i];
-				int color = 0;
+				CUIRect Text;
+				RightView.HSplitTop(20.0f, &Text, &RightView);
+				Text.VSplitLeft(15.0f, 0, &Text);
+				UI()->DoLabel(&Text, paParts[i], 14.0f, -1);
+
+				int PrevColor = *paColors[i];
+				int Color = 0;
 				for(int s = 0; s < 3; s++)
 				{
-					CUIRect text;
-					main_view.HSplitTop(19.0f, &button, &main_view);
-					button.VSplitLeft(30.0f, 0, &button);
-					button.VSplitLeft(70.0f, &text, &button);
-					button.VSplitRight(5.0f, &button, 0);
-					button.HSplitTop(4.0f, 0, &button);
-					
-					float k = ((prevcolor>>((2-s)*8))&0xff)  / 255.0f;
-					k = DoScrollbarH(&color_slider[i][s], &button, k);
-					color <<= 8;
-					color += clamp((int)(k*255), 0, 255);
-					UI()->DoLabel(&text, labels[s], 15.0f, -1);
-					 
+					CUIRect Text;
+					RightView.HSplitTop(19.0f, &Button, &RightView);
+					Button.VSplitLeft(30.0f, 0, &Button);
+					Button.VSplitLeft(70.0f, &Text, &Button);
+					Button.VSplitRight(5.0f, &Button, 0);
+					Button.HSplitTop(4.0f, 0, &Button);
+
+					float k = ((PrevColor>>((2-s)*8))&0xff)  / 255.0f;
+					k = DoScrollbarH(&s_aColorSlider[i][s], &Button, k);
+					Color <<= 8;
+					Color += clamp((int)(k*255), 0, 255);
+					UI()->DoLabel(&Text, paLabels[s], 15.0f, -1);
+
 				}
-		
-				if(*colors[i] != color)
-					need_sendinfo = true;
-					
-				*colors[i] = color;
-				main_view.HSplitTop(5.0f, 0, &main_view);
+
+				if(*paColors[i] != Color)
+					m_NeedSendinfo = true;
+
+				*paColors[i] = Color;
+				RightView.HSplitTop(5.0f, 0, &RightView);
 			}
 		}
-		
+
+        MainView.HSplitTop(MainView.h/2, 0, &MainView);
+
 		// render skinselector
-		static int skinselector_id = 0;		
-		ui_do_listbox_start(&skinselector_id, &main_view, 50, localize("Skins"), (gameclient.skins->num()+3)/4, 0);
+		static const int s_MaxSkins = 256;
+		static const CSkins::CSkin *s_paSkinList[s_MaxSkins];
+		static int s_NumSkins = -1;
+		static float s_ScrollValue = 0;
+		if(s_NumSkins == -1)
+		{
+			mem_zero(s_paSkinList, sizeof(s_paSkinList));
+			s_NumSkins = 0;
+			for(int i = 0; i < m_pClient->m_pSkins->Num() && i < s_MaxSkins; ++i)
+			{
+				const CSkins::CSkin *s = m_pClient->m_pSkins->Get(i);
+				// no special skins
+				if(s->m_aName[0] == 'x' && s->m_aName[1] == '_')
+					continue;
+				s_paSkinList[s_NumSkins++] = s;
+			}
+		}
 
-		for(int skin_id = 0; skin_id < gameclient.skins->num(); )
+		int OldSelected = -1;
+		UiDoListboxStart(&s_NumSkins , &MainView, 50.0f, Localize("Skins"), "", s_NumSkins, 4, OldSelected, s_ScrollValue);
+
+		for(int i = 0; i < s_NumSkins; ++i)
 		{
-			LISTBOXITEM item = ui_do_listbox_nextrow();
-			CUIRect boxes[4];
-			CUIRect first_half, second_half;
-			item.rect.VSplitMid(&first_half, &second_half);
-			first_half.VSplitMid(&boxes[0], &boxes[1]);
-			second_half.VSplitMid(&boxes[2], &boxes[3]);
-			
-			for(int i = 0; i < 4 && skin_id < gameclient.skins->num(); i++, skin_id++)
+			const CSkins::CSkin *s = s_paSkinList[i];
+			if(s == 0)
+				continue;
+
+			if(str_comp(s->m_aName, g_Config.m_PlayerSkin) == 0)
+				OldSelected = i;
+
+			CListboxItem Item = UiDoListboxNextItem(&s_paSkinList[i], OldSelected == i);
+			if(Item.m_Visible)
 			{
-				//CUIRect r = item.
-				const SKINS::SKIN *s = gameclient.skins->get(skin_id);
-
-				TEE_RENDER_INFO info;
-				info.texture = s->org_texture;
-				info.color_body = vec4(1,1,1,1);
-				info.color_feet = vec4(1,1,1,1);
-				if(config.player_use_custom_color)
+				CTeeRenderInfo Info;
+				Info.m_Texture = s->m_OrgTexture;
+				Info.m_ColorBody = vec4(1, 1, 1, 1);
+				Info.m_ColorFeet = vec4(1, 1, 1, 1);
+
+				if(g_Config.m_PlayerUseCustomColor)
 				{
-					info.color_body = gameclient.skins->get_color(config.player_color_body);
-					info.color_feet = gameclient.skins->get_color(config.player_color_feet);
-					info.texture = s->color_texture;
+					Info.m_ColorBody = m_pClient->m_pSkins->GetColor(g_Config.m_PlayerColorBody);
+					Info.m_ColorFeet = m_pClient->m_pSkins->GetColor(g_Config.m_PlayerColorFeet);
+					Info.m_Texture = s->m_ColorTexture;
 				}
-					
-				info.size = UI()->Scale()*50.0f;
-				
-				CUIRect icon = boxes[i]; //item.rect;
-				//button.VSplitLeft(50.0f, &icon, &text);
-				
-				/*if(UI()->DoButton(s, "", selected, &button, ui_draw_list_row, 0))
-				{
-					config_set_player_skin(&config, s->name);
-					need_sendinfo = true;
-				}*/
-
-				//text.HSplitTop(12.0f, 0, &text); // some margin from the top
-				//UI()->DoLabel(&text, buf, 18.0f, 0);
-				
-				icon.HSplitTop(5.0f, 0, &icon); // some margin from the top
-				RenderTools()->RenderTee(ANIMSTATE::get_idle(), &info, 0, vec2(1, 0), vec2(icon.x+icon.w/2, icon.y+icon.h/2));
-				
-				if(config.debug)
+
+				Info.m_Size = UI()->Scale()*50.0f;
+				Item.m_Rect.HSplitTop(5.0f, 0, &Item.m_Rect); // some margin from the top
+				RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, 0, vec2(1, 0), vec2(Item.m_Rect.x+Item.m_Rect.w/2, Item.m_Rect.y+Item.m_Rect.h/2));
+
+				if(g_Config.m_Debug)
 				{
 					Graphics()->TextureSet(-1);
 					Graphics()->QuadsBegin();
-					Graphics()->SetColor(s->blood_color.r, s->blood_color.g, s->blood_color.b, 1.0f);
-					Graphics()->QuadsDrawTL(icon.x, icon.y, 12, 12);
+					Graphics()->SetColor(s->m_BloodColor.r, s->m_BloodColor.g, s->m_BloodColor.b, 1.0f);
+					IGraphics::CQuadItem QuadItem(Item.m_Rect.x, Item.m_Rect.y, 12, 12);
+					Graphics()->QuadsDrawTL(&QuadItem, 1);
 					Graphics()->QuadsEnd();
 				}
 			}
 		}
-		
-		int new_selection = ui_do_listbox_end();
-		(void)new_selection;
-		//main_view
-	}
-	
-	// render skinselector
-	/*
-	{
-		
-		//othersection
-	}
-		
-	// draw header
-	CUIRect header, footer;
-	skinselection.HSplitTop(20, &header, &skinselection);
-	RenderTools()->DrawUIRect(&header, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f); 
-	UI()->DoLabel(&header, localize("Skins"), 18.0f, 0);
-
-	// draw footers	
-	skinselection.HSplitBottom(20, &skinselection, &footer);
-	RenderTools()->DrawUIRect(&footer, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f); 
-	footer.VSplitLeft(10.0f, 0, &footer);
-
-	// modes
-	RenderTools()->DrawUIRect(&skinselection, vec4(0,0,0,0.15f), 0, 0);
-
-	CUIRect scroll;
-	skinselection.VSplitRight(15, &skinselection, &scroll);
-
-	CUIRect list = skinselection;
-	list.HSplitTop(50, &button, &list);
-	
-	int num = (int)(skinselection.h/button.h);
-	static float scrollvalue = 0;
-	static int scrollbar = 0;
-	scroll.HMargin(5.0f, &scroll);
-	scrollvalue = ui_do_scrollbar_v(&scrollbar, &scroll, scrollvalue);
-
-	int start = (int)((gameclient.skins->num()-num)*scrollvalue);
-	if(start < 0)
-		start = 0;
-		
-	for(int i = start; i < start+num && i < gameclient.skins->num(); i++)
-	{
-		const SKINS::SKIN *s = gameclient.skins->get(i);
-		
-		// no special skins
-		if(s->name[0] == 'x' && s->name[1] == '_')
-		{
-			num++;
-			continue;
-		}
-		
-		char buf[128];
-		str_format(buf, sizeof(buf), "%s", s->name);
-		int selected = 0;
-		if(strcmp(s->name, config.player_skin) == 0)
-			selected = 1;
-		
-		TEE_RENDER_INFO info;
-		info.texture = s->org_texture;
-		info.color_body = vec4(1,1,1,1);
-		info.color_feet = vec4(1,1,1,1);
-		if(config.player_use_custom_color)
-		{
-			info.color_body = gameclient.skins->get_color(config.player_color_body);
-			info.color_feet = gameclient.skins->get_color(config.player_color_feet);
-			info.texture = s->color_texture;
-		}
-			
-		info.size = UI()->Scale()*50.0f;
-		
-		CUIRect icon;
-		CUIRect text;
-		button.VSplitLeft(50.0f, &icon, &text);
-		
-		if(UI()->DoButton(s, "", selected, &button, ui_draw_list_row, 0))
-		{
-			config_set_player_skin(&config, s->name);
-			need_sendinfo = true;
-		}
 
-		text.HSplitTop(12.0f, 0, &text); // some margin from the top
-		UI()->DoLabel(&text, buf, 18.0f, 0);
-		
-		icon.HSplitTop(5.0f, 0, &icon); // some margin from the top
-		RenderTools()->RenderTee(ANIMSTATE::get_idle(), &info, 0, vec2(1, 0), vec2(icon.x+icon.w/2, icon.y+icon.h/2));
-		
-		if(config.debug)
+		const int NewSelected = UiDoListboxEnd(&s_ScrollValue, 0);
+		if(OldSelected != NewSelected)
 		{
-			Graphics()->TextureSet(-1);
-			Graphics()->QuadsBegin();
-			Graphics()->SetColor(s->blood_color.r, s->blood_color.g, s->blood_color.b, 1.0f);
-			Graphics()->QuadsDrawTL(icon.x, icon.y, 12, 12);
-			Graphics()->QuadsEnd();
+			mem_copy(g_Config.m_PlayerSkin, s_paSkinList[NewSelected]->m_aName, sizeof(g_Config.m_PlayerSkin));
+			m_NeedSendinfo = true;
 		}
-		
-		list.HSplitTop(50, &button, &list);
-	}*/
+	}
 }
 
-typedef void (*assign_func_callback)(CONFIGURATION *config, int value);
+typedef void (*pfnAssignFuncCallback)(CConfiguration *pConfig, int Value);
 
-typedef struct 
+typedef struct
 {
-	LOC_CONSTSTRING name;
-	const char *command;
-	int keyid;
-} KEYINFO;
+	CLocConstString m_Name;
+	const char *m_pCommand;
+	int m_KeyId;
+} CKeyInfo;
 
-static KEYINFO keys[] = 
+static CKeyInfo gs_aKeys[] =
 {
 	// we need to do localize so the scripts can pickup the string
-	{ localize("Move left"), "+left", 0},
-	{ localize("Move right"), "+right", 0 },
-	{ localize("Jump"), "+jump", 0 },
-	{ localize("Fire"), "+fire", 0 },
-	{ localize("Hook"), "+hook", 0 },
-	{ localize("Hammer"), "+weapon1", 0 },
-	{ localize("Pistol"), "+weapon2", 0 },
-	{ localize("Shotgun"), "+weapon3", 0 },
-	{ localize("Grenade"), "+weapon4", 0 },
-	{ localize("Rifle"), "+weapon5", 0 },
-	{ localize("Next weapon"), "+nextweapon", 0 },
-	{ localize("Prev. weapon"), "+prevweapon", 0 },
-	{ localize("Vote yes"), "vote yes", 0 },
-	{ localize("Vote no"), "vote no", 0 },
-	{ localize("Chat"), "chat all", 0 },
-	{ localize("Team chat"), "chat team", 0 },
-	{ localize("Emoticon"), "+emote", 0 },
-	{ localize("Console"), "toggle_local_console", 0 },
-	{ localize("Remote console"), "toggle_remote_console", 0 },
-	{ localize("Screenshot"), "screenshot", 0 },
-	{ localize("Scoreboard"), "+scoreboard", 0 },
+	{ Localize("Move left"), "+left", 0},
+	{ Localize("Move right"), "+right", 0 },
+	{ Localize("Jump"), "+jump", 0 },
+	{ Localize("Fire"), "+fire", 0 },
+	{ Localize("Hook"), "+hook", 0 },
+	{ Localize("Hammer"), "+weapon1", 0 },
+	{ Localize("Pistol"), "+weapon2", 0 },
+	{ Localize("Shotgun"), "+weapon3", 0 },
+	{ Localize("Grenade"), "+weapon4", 0 },
+	{ Localize("Rifle"), "+weapon5", 0 },
+	{ Localize("Next weapon"), "+nextweapon", 0 },
+	{ Localize("Prev. weapon"), "+prevweapon", 0 },
+	{ Localize("Vote yes"), "vote yes", 0 },
+	{ Localize("Vote no"), "vote no", 0 },
+	{ Localize("Chat"), "chat all", 0 },
+	{ Localize("Team chat"), "chat team", 0 },
+	{ Localize("Emoticon"), "+emote", 0 },
+	{ Localize("Console"), "toggle_local_console", 0 },
+	{ Localize("Remote console"), "toggle_remote_console", 0 },
+	{ Localize("Screenshot"), "screenshot", 0 },
+	{ Localize("Scoreboard"), "+scoreboard", 0 },
 };
 
-const int key_count = sizeof(keys) / sizeof(KEYINFO);
+const int g_KeyCount = sizeof(gs_aKeys) / sizeof(CKeyInfo);
 
-void MENUS::ui_do_getbuttons(int start, int stop, CUIRect view)
+void CMenus::UiDoGetButtons(int Start, int Stop, CUIRect View)
 {
-	for (int i = start; i < stop; i++)
+	for (int i = Start; i < Stop; i++)
 	{
-		KEYINFO &key = keys[i];
-		CUIRect button, label;
-		view.HSplitTop(20.0f, &button, &view);
-		button.VSplitLeft(130.0f, &label, &button);
-	
-		char buf[64];
-		str_format(buf, sizeof(buf), "%s:", (const char *)key.name);
-		
-		UI()->DoLabel(&label, key.name, 14.0f, -1);
-		int oldid = key.keyid;
-		int newid = DoKeyReader((void *)&keys[i].name, &button, oldid);
-		if(newid != oldid)
+		CKeyInfo &Key = gs_aKeys[i];
+		CUIRect Button, Label;
+		View.HSplitTop(20.0f, &Button, &View);
+		Button.VSplitLeft(130.0f, &Label, &Button);
+
+		char aBuf[64];
+		str_format(aBuf, sizeof(aBuf), "%s:", (const char *)Key.m_Name);
+
+		UI()->DoLabel(&Label, aBuf, 14.0f, -1);
+		int OldId = Key.m_KeyId;
+		int NewId = DoKeyReader((void *)&gs_aKeys[i].m_Name, &Button, OldId);
+		if(NewId != OldId)
 		{
-			gameclient.binds->bind(oldid, "");
-			gameclient.binds->bind(newid, keys[i].command);
+			m_pClient->m_pBinds->Bind(OldId, "");
+			m_pClient->m_pBinds->Bind(NewId, gs_aKeys[i].m_pCommand);
 		}
-		view.HSplitTop(5.0f, 0, &view);
+		View.HSplitTop(5.0f, 0, &View);
 	}
 }
 
-void MENUS::render_settings_controls(CUIRect main_view)
+void CMenus::RenderSettingsControls(CUIRect MainView)
 {
 	// this is kinda slow, but whatever
-	for(int i = 0; i < key_count; i++)
-		keys[i].keyid = 0;
-	
-	for(int keyid = 0; keyid < KEY_LAST; keyid++)
+	for(int i = 0; i < g_KeyCount; i++)
+		gs_aKeys[i].m_KeyId = 0;
+
+	for(int KeyId = 0; KeyId < KEY_LAST; KeyId++)
 	{
-		const char *bind = gameclient.binds->get(keyid);
-		if(!bind[0])
+		const char *pBind = m_pClient->m_pBinds->Get(KeyId);
+		if(!pBind[0])
 			continue;
-		
-		for(int i = 0; i < key_count; i++)
-			if(strcmp(bind, keys[i].command) == 0)
+
+		for(int i = 0; i < g_KeyCount; i++)
+			if(str_comp(pBind, gs_aKeys[i].m_pCommand) == 0)
 			{
-				keys[i].keyid = keyid;
+				gs_aKeys[i].m_KeyId = KeyId;
 				break;
 			}
 	}
 
-	CUIRect movement_settings, weapon_settings, voting_settings, chat_settings, misc_settings, reset_button;
-	main_view.VSplitLeft(main_view.w/2-5.0f, &movement_settings, &voting_settings);
-	
-	/* movement settings */
+	CUIRect MovementSettings, WeaponSettings, VotingSettings, ChatSettings, MiscSettings, ResetButton;
+	MainView.VSplitLeft(MainView.w/2-5.0f, &MovementSettings, &VotingSettings);
+
+	// movement settings
 	{
-		movement_settings.HSplitTop(main_view.h/2-5.0f, &movement_settings, &weapon_settings);
-		RenderTools()->DrawUIRect(&movement_settings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
-		movement_settings.Margin(10.0f, &movement_settings);
-		
-		gfx_text(0, movement_settings.x, movement_settings.y, 14, localize("Movement"), -1);
-		
-		movement_settings.HSplitTop(14.0f+5.0f+10.0f, 0, &movement_settings);
-		
+		MovementSettings.HSplitTop(MainView.h/2-5.0f, &MovementSettings, &WeaponSettings);
+		RenderTools()->DrawUIRect(&MovementSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
+		MovementSettings.Margin(10.0f, &MovementSettings);
+
+		TextRender()->Text(0, MovementSettings.x, MovementSettings.y, 14, Localize("Movement"), -1);
+
+		MovementSettings.HSplitTop(14.0f+5.0f+10.0f, 0, &MovementSettings);
+
 		{
-			CUIRect button, label;
-			movement_settings.HSplitTop(20.0f, &button, &movement_settings);
-			button.VSplitLeft(130.0f, &label, &button);
-			UI()->DoLabel(&label, localize("Mouse sens."), 14.0f, -1);
-			button.HMargin(2.0f, &button);
-			config.inp_mousesens = (int)(DoScrollbarV(&config.inp_mousesens, &button, (config.inp_mousesens-5)/500.0f)*500.0f)+5;
-			//*key.key = ui_do_key_reader(key.key, &button, *key.key);
-			movement_settings.HSplitTop(20.0f, 0, &movement_settings);
+			CUIRect Button, Label;
+			MovementSettings.HSplitTop(20.0f, &Button, &MovementSettings);
+			Button.VSplitLeft(130.0f, &Label, &Button);
+			UI()->DoLabel(&Label, Localize("Mouse sens."), 14.0f, -1);
+			Button.HMargin(2.0f, &Button);
+			g_Config.m_InpMousesens = (int)(DoScrollbarH(&g_Config.m_InpMousesens, &Button, (g_Config.m_InpMousesens-5)/500.0f)*500.0f)+5;
+			//*key.key = ui_do_key_reader(key.key, &Button, *key.key);
+			MovementSettings.HSplitTop(20.0f, 0, &MovementSettings);
 		}
-		
-		ui_do_getbuttons(0, 5, movement_settings);
+
+		UiDoGetButtons(0, 5, MovementSettings);
 
 	}
-	
-	/* weapon settings */
+
+	// weapon settings
 	{
-		weapon_settings.HSplitTop(10.0f, 0, &weapon_settings);
-		RenderTools()->DrawUIRect(&weapon_settings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
-		weapon_settings.Margin(10.0f, &weapon_settings);
-
-		gfx_text(0, weapon_settings.x, weapon_settings.y, 14, localize("Weapon"), -1);
-		
-		weapon_settings.HSplitTop(14.0f+5.0f+10.0f, 0, &weapon_settings);
-		ui_do_getbuttons(5, 12, weapon_settings);
+		WeaponSettings.HSplitTop(10.0f, 0, &WeaponSettings);
+		RenderTools()->DrawUIRect(&WeaponSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
+		WeaponSettings.Margin(10.0f, &WeaponSettings);
+
+		TextRender()->Text(0, WeaponSettings.x, WeaponSettings.y, 14, Localize("Weapon"), -1);
+
+		WeaponSettings.HSplitTop(14.0f+5.0f+10.0f, 0, &WeaponSettings);
+		UiDoGetButtons(5, 12, WeaponSettings);
 	}
-	
-	/* voting settings */
+
+	// voting settings
 	{
-		voting_settings.VSplitLeft(10.0f, 0, &voting_settings);
-		voting_settings.HSplitTop(main_view.h/4-5.0f, &voting_settings, &chat_settings);
-		RenderTools()->DrawUIRect(&voting_settings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
-		voting_settings.Margin(10.0f, &voting_settings);
-	
-		gfx_text(0, voting_settings.x, voting_settings.y, 14, localize("Voting"), -1);
-		
-		voting_settings.HSplitTop(14.0f+5.0f+10.0f, 0, &voting_settings);
-		ui_do_getbuttons(12, 14, voting_settings);
+		VotingSettings.VSplitLeft(10.0f, 0, &VotingSettings);
+		VotingSettings.HSplitTop(MainView.h/4-5.0f, &VotingSettings, &ChatSettings);
+		RenderTools()->DrawUIRect(&VotingSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
+		VotingSettings.Margin(10.0f, &VotingSettings);
+
+		TextRender()->Text(0, VotingSettings.x, VotingSettings.y, 14, Localize("Voting"), -1);
+
+		VotingSettings.HSplitTop(14.0f+5.0f+10.0f, 0, &VotingSettings);
+		UiDoGetButtons(12, 14, VotingSettings);
 	}
-	
-	/* chat settings */
+
+	// chat settings
 	{
-		chat_settings.HSplitTop(10.0f, 0, &chat_settings);
-		chat_settings.HSplitTop(main_view.h/4-10.0f, &chat_settings, &misc_settings);
-		RenderTools()->DrawUIRect(&chat_settings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
-		chat_settings.Margin(10.0f, &chat_settings);
-	
-		gfx_text(0, chat_settings.x, chat_settings.y, 14, localize("Chat"), -1);
-		
-		chat_settings.HSplitTop(14.0f+5.0f+10.0f, 0, &chat_settings);
-		ui_do_getbuttons(14, 16, chat_settings);
+		ChatSettings.HSplitTop(10.0f, 0, &ChatSettings);
+		ChatSettings.HSplitTop(MainView.h/4-10.0f, &ChatSettings, &MiscSettings);
+		RenderTools()->DrawUIRect(&ChatSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
+		ChatSettings.Margin(10.0f, &ChatSettings);
+
+		TextRender()->Text(0, ChatSettings.x, ChatSettings.y, 14, Localize("Chat"), -1);
+
+		ChatSettings.HSplitTop(14.0f+5.0f+10.0f, 0, &ChatSettings);
+		UiDoGetButtons(14, 16, ChatSettings);
 	}
-	
-	/* misc settings */
+
+	// misc settings
 	{
-		misc_settings.HSplitTop(10.0f, 0, &misc_settings);
-		misc_settings.HSplitTop(main_view.h/2-5.0f-45.0f, &misc_settings, &reset_button);
-		RenderTools()->DrawUIRect(&misc_settings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
-		misc_settings.Margin(10.0f, &misc_settings);
-	
-		gfx_text(0, misc_settings.x, misc_settings.y, 14, localize("Miscellaneous"), -1);
-		
-		misc_settings.HSplitTop(14.0f+5.0f+10.0f, 0, &misc_settings);
-		ui_do_getbuttons(16, 21, misc_settings);
+		MiscSettings.HSplitTop(10.0f, 0, &MiscSettings);
+		MiscSettings.HSplitTop(MainView.h/2-5.0f-45.0f, &MiscSettings, &ResetButton);
+		RenderTools()->DrawUIRect(&MiscSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
+		MiscSettings.Margin(10.0f, &MiscSettings);
+
+		TextRender()->Text(0, MiscSettings.x, MiscSettings.y, 14, Localize("Miscellaneous"), -1);
+
+		MiscSettings.HSplitTop(14.0f+5.0f+10.0f, 0, &MiscSettings);
+		UiDoGetButtons(16, 21, MiscSettings);
 	}
-	
+
 	// defaults
-	reset_button.HSplitTop(10.0f, 0, &reset_button);
-	static int default_button = 0;
-	if(DoButton_Menu((void*)&default_button, localize("Reset to defaults"), 0, &reset_button))
-		gameclient.binds->set_defaults();
+	ResetButton.HSplitTop(10.0f, 0, &ResetButton);
+	static int s_DefaultButton = 0;
+	if(DoButton_Menu((void*)&s_DefaultButton, Localize("Reset to defaults"), 0, &ResetButton))
+		m_pClient->m_pBinds->SetDefaults();
 }
 
-void MENUS::render_settings_graphics(CUIRect main_view)
+void CMenus::RenderSettingsGraphics(CUIRect MainView)
 {
-	CUIRect button;
-	char buf[128];
-	
+	CUIRect Button;
+	char aBuf[128];
+
 	static const int MAX_RESOLUTIONS = 256;
-	static VIDEO_MODE modes[MAX_RESOLUTIONS];
-	static int num_modes = -1;
-	
-	if(num_modes == -1)
-		num_modes = gfx_get_video_modes(modes, MAX_RESOLUTIONS);
-	
-	CUIRect modelist;
-	main_view.VSplitLeft(300.0f, &main_view, &modelist);
-	
+	static CVideoMode s_aModes[MAX_RESOLUTIONS];
+	static int s_NumNodes = -1;
+	const static int s_GfxScreenWidth = g_Config.m_GfxScreenWidth;
+	const static int s_GfxScreenHeight = g_Config.m_GfxScreenHeight;
+	const static int s_GfxColorDepth = g_Config.m_GfxColorDepth;
+
+	if(s_NumNodes == -1)
+		s_NumNodes = Graphics()->GetVideoModes(s_aModes, MAX_RESOLUTIONS);
+
+	CUIRect ModeList;
+	MainView.VSplitLeft(300.0f, &MainView, &ModeList);
+
 	// draw allmodes switch
-	CUIRect header, footer;
-	modelist.HSplitTop(20, &button, &modelist);
-	if(DoButton_CheckBox(&config.gfx_display_all_modes, localize("Show only supported"), config.gfx_display_all_modes^1, &button))
+	ModeList.HSplitTop(20, &Button, &ModeList);
+	if(DoButton_CheckBox(&g_Config.m_GfxDisplayAllModes, Localize("Show only supported"), g_Config.m_GfxDisplayAllModes^1, &Button))
 	{
-		config.gfx_display_all_modes ^= 1;
-		num_modes = gfx_get_video_modes(modes, MAX_RESOLUTIONS);
+		g_Config.m_GfxDisplayAllModes ^= 1;
+		s_NumNodes = Graphics()->GetVideoModes(s_aModes, MAX_RESOLUTIONS);
 	}
-	
-	// draw header
-	modelist.HSplitTop(20, &header, &modelist);
-	RenderTools()->DrawUIRect(&header, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f); 
-	UI()->DoLabel(&header, localize("Display Modes"), 14.0f, 0);
-
-	// draw footers	
-	modelist.HSplitBottom(20, &modelist, &footer);
-	str_format(buf, sizeof(buf), "%s: %dx%d %d bit", localize("Current"), config.gfx_screen_width, config.gfx_screen_height, config.gfx_color_depth);
-	RenderTools()->DrawUIRect(&footer, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f); 
-	footer.VSplitLeft(10.0f, 0, &footer);
-	UI()->DoLabel(&footer, buf, 14.0f, -1);
-
-	// modes
-	RenderTools()->DrawUIRect(&modelist, vec4(0,0,0,0.15f), 0, 0);
-
-	CUIRect scroll;
-	modelist.VSplitRight(15, &modelist, &scroll);
-
-	CUIRect list = modelist;
-	list.HSplitTop(20, &button, &list);
-	
-	int num = (int)(modelist.h/button.h);
-	static float scrollvalue = 0;
-	static int scrollbar = 0;
-	scroll.HMargin(5.0f, &scroll);
-	scrollvalue = DoScrollbarV(&scrollbar, &scroll, scrollvalue);
-
-	int start = (int)((num_modes-num)*scrollvalue);
-	if(start < 0)
-		start = 0;
-		
-	for(int i = start; i < start+num && i < num_modes; i++)
+
+	// display mode list
+	static float s_ScrollValue = 0;
+	int OldSelected = -1;
+	str_format(aBuf, sizeof(aBuf), "%s: %dx%d %d bit", Localize("Current"), s_GfxScreenWidth, s_GfxScreenHeight, s_GfxColorDepth);
+	UiDoListboxStart(&s_NumNodes , &ModeList, 24.0f, Localize("Display Modes"), aBuf, s_NumNodes, 1, OldSelected, s_ScrollValue);
+
+	for(int i = 0; i < s_NumNodes; ++i)
 	{
-		int depth = modes[i].red+modes[i].green+modes[i].blue;
-		if(depth < 16)
-			depth = 16;
-		else if(depth > 16)
-			depth = 24;
-			
-		int selected = 0;
-		if(config.gfx_color_depth == depth &&
-			config.gfx_screen_width == modes[i].width &&
-			config.gfx_screen_height == modes[i].height)
+		const int Depth = s_aModes[i].m_Red+s_aModes[i].m_Green+s_aModes[i].m_Blue > 16 ? 24 : 16;
+		if(g_Config.m_GfxColorDepth == Depth &&
+			g_Config.m_GfxScreenWidth == s_aModes[i].m_Width &&
+			g_Config.m_GfxScreenHeight == s_aModes[i].m_Height)
 		{
-			selected = 1;
+			OldSelected = i;
 		}
-		
-		str_format(buf, sizeof(buf), "  %dx%d %d bit", modes[i].width, modes[i].height, depth);
-		if(DoButton_ListRow(&modes[i], buf, selected, &button))
+
+		CListboxItem Item = UiDoListboxNextItem(&s_aModes[i], OldSelected == i);
+		if(Item.m_Visible)
 		{
-			config.gfx_color_depth = depth;
-			config.gfx_screen_width = modes[i].width;
-			config.gfx_screen_height = modes[i].height;
-			if(!selected)
-				need_restart = true;
+			str_format(aBuf, sizeof(aBuf), "  %dx%d %d bit", s_aModes[i].m_Width, s_aModes[i].m_Height, Depth);
+			UI()->DoLabel(&Item.m_Rect, aBuf, 16.0f, -1);
 		}
-		
-		list.HSplitTop(20, &button, &list);
 	}
-	
-	
+
+	const int NewSelected = UiDoListboxEnd(&s_ScrollValue, 0);
+	if(OldSelected != NewSelected)
+	{
+		const int Depth = s_aModes[NewSelected].m_Red+s_aModes[NewSelected].m_Green+s_aModes[NewSelected].m_Blue > 16 ? 24 : 16;
+		g_Config.m_GfxColorDepth = Depth;
+		g_Config.m_GfxScreenWidth = s_aModes[NewSelected].m_Width;
+		g_Config.m_GfxScreenHeight = s_aModes[NewSelected].m_Height;
+		m_NeedRestart = true;
+	}
+
 	// switches
-	main_view.HSplitTop(20.0f, &button, &main_view);
-	if(DoButton_CheckBox(&config.gfx_fullscreen, localize("Fullscreen"), config.gfx_fullscreen, &button))
+	MainView.HSplitTop(20.0f, &Button, &MainView);
+	if(DoButton_CheckBox(&g_Config.m_GfxFullscreen, Localize("Fullscreen"), g_Config.m_GfxFullscreen, &Button))
 	{
-		config.gfx_fullscreen ^= 1;
-		need_restart = true;
+		g_Config.m_GfxFullscreen ^= 1;
+		m_NeedRestart = true;
 	}
 
-	main_view.HSplitTop(20.0f, &button, &main_view);
-	if(DoButton_CheckBox(&config.gfx_vsync, localize("V-Sync"), config.gfx_vsync, &button))
+	MainView.HSplitTop(20.0f, &Button, &MainView);
+	if(DoButton_CheckBox(&g_Config.m_GfxVsync, Localize("V-Sync"), g_Config.m_GfxVsync, &Button))
 	{
-		config.gfx_vsync ^= 1;
-		need_restart = true;
+		g_Config.m_GfxVsync ^= 1;
+		m_NeedRestart = true;
 	}
 
-	main_view.HSplitTop(20.0f, &button, &main_view);
-	if(DoButton_CheckBox_Number(&config.gfx_fsaa_samples, localize("FSAA samples"), config.gfx_fsaa_samples, &button))
+	MainView.HSplitTop(20.0f, &Button, &MainView);
+	if(DoButton_CheckBox_Number(&g_Config.m_GfxFsaaSamples, Localize("FSAA samples"), g_Config.m_GfxFsaaSamples, &Button))
 	{
-		config.gfx_fsaa_samples = (config.gfx_fsaa_samples+1)%17;
-		need_restart = true;
+		g_Config.m_GfxFsaaSamples = (g_Config.m_GfxFsaaSamples+1)%17;
+		m_NeedRestart = true;
 	}
-		
-	main_view.HSplitTop(40.0f, &button, &main_view);
-	main_view.HSplitTop(20.0f, &button, &main_view);
-	if(DoButton_CheckBox(&config.gfx_texture_quality, localize("Quality Textures"), config.gfx_texture_quality, &button))
+
+	MainView.HSplitTop(40.0f, &Button, &MainView);
+	MainView.HSplitTop(20.0f, &Button, &MainView);
+	if(DoButton_CheckBox(&g_Config.m_GfxTextureQuality, Localize("Quality Textures"), g_Config.m_GfxTextureQuality, &Button))
 	{
-		config.gfx_texture_quality ^= 1;
-		need_restart = true;
+		g_Config.m_GfxTextureQuality ^= 1;
+		m_NeedRestart = true;
 	}
 
-	main_view.HSplitTop(20.0f, &button, &main_view);
-	if(DoButton_CheckBox(&config.gfx_texture_compression, localize("Texture Compression"), config.gfx_texture_compression, &button))
+	MainView.HSplitTop(20.0f, &Button, &MainView);
+	if(DoButton_CheckBox(&g_Config.m_GfxTextureCompression, Localize("Texture Compression"), g_Config.m_GfxTextureCompression, &Button))
 	{
-		config.gfx_texture_compression ^= 1;
-		need_restart = true;
+		g_Config.m_GfxTextureCompression ^= 1;
+		m_NeedRestart = true;
 	}
 
-	main_view.HSplitTop(20.0f, &button, &main_view);
-	if(DoButton_CheckBox(&config.gfx_high_detail, localize("High Detail"), config.gfx_high_detail, &button))
-		config.gfx_high_detail ^= 1;
+	MainView.HSplitTop(20.0f, &Button, &MainView);
+	if(DoButton_CheckBox(&g_Config.m_GfxHighDetail, Localize("High Detail"), g_Config.m_GfxHighDetail, &Button))
+		g_Config.m_GfxHighDetail ^= 1;
 
 	//
-	
-	CUIRect text;
-	main_view.HSplitTop(20.0f, 0, &main_view);
-	main_view.HSplitTop(20.0f, &text, &main_view);
+
+	CUIRect Text;
+	MainView.HSplitTop(20.0f, 0, &MainView);
+	MainView.HSplitTop(20.0f, &Text, &MainView);
 	//text.VSplitLeft(15.0f, 0, &text);
-	UI()->DoLabel(&text, localize("UI Color"), 14.0f, -1);
-	
-	const char *labels[] = {
-		localize("Hue"),
-		localize("Sat."),
-		localize("Lht."),
-		localize("Alpha")};
-	int *color_slider[4] = {&config.ui_color_hue, &config.ui_color_sat, &config.ui_color_lht, &config.ui_color_alpha};
+	UI()->DoLabel(&Text, Localize("UI Color"), 14.0f, -1);
+
+	const char *paLabels[] = {
+		Localize("Hue"),
+		Localize("Sat."),
+		Localize("Lht."),
+		Localize("Alpha")};
+	int *pColorSlider[4] = {&g_Config.m_UiColorHue, &g_Config.m_UiColorSat, &g_Config.m_UiColorLht, &g_Config.m_UiColorAlpha};
 	for(int s = 0; s < 4; s++)
 	{
-		CUIRect text;
-		main_view.HSplitTop(19.0f, &button, &main_view);
-		button.VMargin(15.0f, &button);
-		button.VSplitLeft(50.0f, &text, &button);
-		button.VSplitRight(5.0f, &button, 0);
-		button.HSplitTop(4.0f, 0, &button);
-		
-		float k = (*color_slider[s]) / 255.0f;
-		k = DoScrollbarH(color_slider[s], &button, k);
-		*color_slider[s] = (int)(k*255.0f);
-		UI()->DoLabel(&text, labels[s], 15.0f, -1);
-	}		
+		CUIRect Text;
+		MainView.HSplitTop(19.0f, &Button, &MainView);
+		Button.VMargin(15.0f, &Button);
+		Button.VSplitLeft(50.0f, &Text, &Button);
+		Button.VSplitRight(5.0f, &Button, 0);
+		Button.HSplitTop(4.0f, 0, &Button);
+
+		float k = (*pColorSlider[s]) / 255.0f;
+		k = DoScrollbarH(pColorSlider[s], &Button, k);
+		*pColorSlider[s] = (int)(k*255.0f);
+		UI()->DoLabel(&Text, paLabels[s], 15.0f, -1);
+	}
 }
 
-void MENUS::render_settings_sound(CUIRect main_view)
+void CMenus::RenderSettingsSound(CUIRect MainView)
 {
-	CUIRect button;
-	main_view.VSplitLeft(300.0f, &main_view, 0);
-	
-	main_view.HSplitTop(20.0f, &button, &main_view);
-	if(DoButton_CheckBox(&config.snd_enable, localize("Use sounds"), config.snd_enable, &button))
+	CUIRect Button;
+	MainView.VSplitLeft(300.0f, &MainView, 0);
+
+	MainView.HSplitTop(20.0f, &Button, &MainView);
+	if(DoButton_CheckBox(&g_Config.m_SndEnable, Localize("Use sounds"), g_Config.m_SndEnable, &Button))
 	{
-		config.snd_enable ^= 1;
-		need_restart = true;
+		g_Config.m_SndEnable ^= 1;
+		m_NeedRestart = true;
 	}
-	
-	if(!config.snd_enable)
+
+	if(!g_Config.m_SndEnable)
 		return;
-	
-	main_view.HSplitTop(20.0f, &button, &main_view);
-	if(DoButton_CheckBox(&config.snd_nonactive_mute, localize("Mute when not active"), config.snd_nonactive_mute, &button))
-		config.snd_nonactive_mute ^= 1;
-		
+
+	MainView.HSplitTop(20.0f, &Button, &MainView);
+	if(DoButton_CheckBox(&g_Config.m_SndNonactiveMute, Localize("Mute when not active"), g_Config.m_SndNonactiveMute, &Button))
+		g_Config.m_SndNonactiveMute ^= 1;
+
 	// sample rate box
 	{
-		char buf[64];
-		str_format(buf, sizeof(buf), "%d", config.snd_rate);
-		main_view.HSplitTop(20.0f, &button, &main_view);
-		UI()->DoLabel(&button, localize("Sample rate"), 14.0f, -1);
-		button.VSplitLeft(110.0f, 0, &button);
-		button.VSplitLeft(180.0f, &button, 0);
-		DoEditBox(&config.snd_rate, &button, buf, sizeof(buf), 14.0f);
-		int before = config.snd_rate;
-		config.snd_rate = atoi(buf);
-		
-		if(config.snd_rate != before)
-			need_restart = true;
-
-		if(config.snd_rate < 1)
-			config.snd_rate = 1;
+		char aBuf[64];
+		str_format(aBuf, sizeof(aBuf), "%d", g_Config.m_SndRate);
+		MainView.HSplitTop(20.0f, &Button, &MainView);
+		UI()->DoLabel(&Button, Localize("Sample rate"), 14.0f, -1);
+		Button.VSplitLeft(110.0f, 0, &Button);
+		Button.VSplitLeft(180.0f, &Button, 0);
+		DoEditBox(&g_Config.m_SndRate, &Button, aBuf, sizeof(aBuf), 14.0f);
+		int Before = g_Config.m_SndRate;
+		g_Config.m_SndRate = str_toint(aBuf);
+
+		if(g_Config.m_SndRate != Before)
+			m_NeedRestart = true;
+
+		if(g_Config.m_SndRate < 1)
+			g_Config.m_SndRate = 1;
 	}
-	
+
 	// volume slider
 	{
-		CUIRect button, label;
-		main_view.HSplitTop(5.0f, &button, &main_view);
-		main_view.HSplitTop(20.0f, &button, &main_view);
-		button.VSplitLeft(110.0f, &label, &button);
-		button.HMargin(2.0f, &button);
-		UI()->DoLabel(&label, localize("Sound volume"), 14.0f, -1);
-		config.snd_volume = (int)(DoScrollbarH(&config.snd_volume, &button, config.snd_volume/100.0f)*100.0f);
-		main_view.HSplitTop(20.0f, 0, &main_view);
+		CUIRect Button, Label;
+		MainView.HSplitTop(5.0f, &Button, &MainView);
+		MainView.HSplitTop(20.0f, &Button, &MainView);
+		Button.VSplitLeft(110.0f, &Label, &Button);
+		Button.HMargin(2.0f, &Button);
+		UI()->DoLabel(&Label, Localize("Sound volume"), 14.0f, -1);
+		g_Config.m_SndVolume = (int)(DoScrollbarH(&g_Config.m_SndVolume, &Button, g_Config.m_SndVolume/100.0f)*100.0f);
+		MainView.HSplitTop(20.0f, 0, &MainView);
 	}
 }
 
 struct LANGUAGE
 {
 	LANGUAGE() {}
-	LANGUAGE(const char *n, const char *f) : name(n), filename(f) {}
-	
-	string name;
-	string filename;
-	
-	bool operator<(const LANGUAGE &other) { return name < other.name; }
+	LANGUAGE(const char *n, const char *f) : m_Name(n), m_FileName(f) {}
+
+	string m_Name;
+	string m_FileName;
+
+	bool operator<(const LANGUAGE &Other) { return m_Name < Other.m_Name; }
 };
 
 
-int fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, void *user);
+int fs_listdir(const char *pDir, FS_LISTDIR_CALLBACK cb, void *pUser);
 
-void gather_languages(const char *name, int is_dir, void *user)
+void GatherLanguages(const char *pName, int IsDir, void *pUser)
 {
-	if(is_dir || name[0] == '.')
+	if(IsDir || pName[0] == '.')
 		return;
-		
-	sorted_array<LANGUAGE> &languages = *((sorted_array<LANGUAGE> *)user);
-	char filename[128];
-	str_format(filename, sizeof(filename), "data/languages/%s", name);
-
-	char nicename[128];
-	str_format(nicename, sizeof(nicename), "%s", name);
-	nicename[0] = str_uppercase(nicename[0]);
-	
-	
-	for(char *p = nicename; *p; p++)
+
+	sorted_array<LANGUAGE> &Languages = *((sorted_array<LANGUAGE> *)pUser);
+	char aFileName[128];
+	str_format(aFileName, sizeof(aFileName), "data/languages/%s", pName);
+
+	char NiceName[128];
+	str_format(NiceName, sizeof(NiceName), "%s", pName);
+	NiceName[0] = str_uppercase(NiceName[0]);
+
+
+	for(char *p = NiceName; *p; p++)
 		if(*p == '.')
 			*p = 0;
-	
-	languages.add(LANGUAGE(nicename, filename));
+
+	Languages.add(LANGUAGE(NiceName, aFileName));
 }
 
-void MENUS::render_settings_general(CUIRect main_view)
+void CMenus::RenderSettingsGeneral(CUIRect MainView)
 {
-	static int lanuagelist = 0;
-	static int selected_language = 0;
-	static sorted_array<LANGUAGE> languages;
-	
-	if(languages.size() == 0)
+	static int s_LanguageList  = 0;
+	static int s_SelectedLanguage = 0;
+	static sorted_array<LANGUAGE> s_Languages;
+	static float s_ScrollValue = 0;
+
+	if(s_Languages.size() == 0)
 	{
-		languages.add(LANGUAGE("English", ""));
-		fs_listdir("data/languages", gather_languages, &languages);
-		for(int i = 0; i < languages.size(); i++)
-			if(str_comp(languages[i].filename, config.cl_languagefile) == 0)
+		s_Languages.add(LANGUAGE("English", ""));
+		fs_listdir("data/languages", GatherLanguages, &s_Languages);
+		for(int i = 0; i < s_Languages.size(); i++)
+			if(str_comp(s_Languages[i].m_FileName, g_Config.m_ClLanguagefile) == 0)
 			{
-				selected_language = i;
+				s_SelectedLanguage = i;
 				break;
 			}
 	}
-	
-	int old_selected = selected_language;
-	
-	CUIRect list = main_view;
-	ui_do_listbox_start(&lanuagelist, &list, 24.0f, localize("Language"), languages.size(), selected_language);
-	
-	for(sorted_array<LANGUAGE>::range r = languages.all(); !r.empty(); r.pop_front())
+
+	int OldSelected = s_SelectedLanguage;
+
+	CUIRect List = MainView;
+	UiDoListboxStart(&s_LanguageList , &List, 24.0f, Localize("Language"), "", s_Languages.size(), 1, s_SelectedLanguage, s_ScrollValue);
+
+	for(sorted_array<LANGUAGE>::range r = s_Languages.all(); !r.empty(); r.pop_front())
 	{
-		LISTBOXITEM item = ui_do_listbox_nextitem(&r.front());
-		
-		if(item.visible)
-			UI()->DoLabel(&item.rect, r.front().name, 16.0f, -1);
+		CListboxItem Item = UiDoListboxNextItem(&r.front());
+
+		if(Item.m_Visible)
+			UI()->DoLabel(&Item.m_Rect, r.front().m_Name, 16.0f, -1);
 	}
-	
-	selected_language = ui_do_listbox_end();
-	
-	if(old_selected != selected_language)
+
+	s_SelectedLanguage = UiDoListboxEnd(&s_ScrollValue, 0);
+
+	if(OldSelected != s_SelectedLanguage)
 	{
-		str_copy(config.cl_languagefile, languages[selected_language].filename, sizeof(config.cl_languagefile));
-		localization.load(languages[selected_language].filename);
+		str_copy(g_Config.m_ClLanguagefile, s_Languages[s_SelectedLanguage].m_FileName, sizeof(g_Config.m_ClLanguagefile));
+		g_Localization.Load(s_Languages[s_SelectedLanguage].m_FileName);
 	}
 }
 
-void MENUS::render_settings(CUIRect main_view)
+void CMenus::RenderSettings(CUIRect MainView)
 {
-	static int settings_page = 0;
-	
+	static int s_SettingsPage = 0;
+
 	// render background
-	CUIRect temp, tabbar;
-	main_view.VSplitRight(120.0f, &main_view, &tabbar);
-	RenderTools()->DrawUIRect(&main_view, color_tabbar_active, CUI::CORNER_B|CUI::CORNER_TL, 10.0f);
-	tabbar.HSplitTop(50.0f, &temp, &tabbar);
-	RenderTools()->DrawUIRect(&temp, color_tabbar_active, CUI::CORNER_R, 10.0f);
-	
-	main_view.HSplitTop(10.0f, 0, &main_view);
-	
-	CUIRect button;
-	
-	const char *tabs[] = {
-		localize("General"),
-		localize("Player"),
-		localize("Controls"),
-		localize("Graphics"),
-		localize("Sound")};
-		
-	int num_tabs = (int)(sizeof(tabs)/sizeof(*tabs));
-
-	for(int i = 0; i < num_tabs; i++)
+	CUIRect Temp, TabBar;
+	MainView.VSplitRight(120.0f, &MainView, &TabBar);
+	RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_B|CUI::CORNER_TL, 10.0f);
+	TabBar.HSplitTop(50.0f, &Temp, &TabBar);
+	RenderTools()->DrawUIRect(&Temp, ms_ColorTabbarActive, CUI::CORNER_R, 10.0f);
+
+	MainView.HSplitTop(10.0f, 0, &MainView);
+
+	CUIRect Button;
+
+	const char *aTabs[] = {
+		Localize("General"),
+		Localize("Player"),
+		Localize("Controls"),
+		Localize("Graphics"),
+		Localize("Sound")};
+
+	int NumTabs = (int)(sizeof(aTabs)/sizeof(*aTabs));
+
+	for(int i = 0; i < NumTabs; i++)
 	{
-		tabbar.HSplitTop(10, &button, &tabbar);
-		tabbar.HSplitTop(26, &button, &tabbar);
-		if(DoButton_SettingsTab(tabs[i], tabs[i], settings_page == i, &button))
-			settings_page = i;
+		TabBar.HSplitTop(10, &Button, &TabBar);
+		TabBar.HSplitTop(26, &Button, &TabBar);
+		if(DoButton_SettingsTab(aTabs[i], aTabs[i], s_SettingsPage == i, &Button))
+			s_SettingsPage = i;
 	}
-	
-	main_view.Margin(10.0f, &main_view);
-	
-	if(settings_page == 0)
-		render_settings_general(main_view);
-	else if(settings_page == 1)
-		render_settings_player(main_view);
-	else if(settings_page == 2)
-		render_settings_controls(main_view);
-	else if(settings_page == 3)
-		render_settings_graphics(main_view);
-	else if(settings_page == 4)
-		render_settings_sound(main_view);
-
-	if(need_restart)
+
+	MainView.Margin(10.0f, &MainView);
+
+	if(s_SettingsPage == 0)
+		RenderSettingsGeneral(MainView);
+	else if(s_SettingsPage == 1)
+		RenderSettingsPlayer(MainView);
+	else if(s_SettingsPage == 2)
+		RenderSettingsControls(MainView);
+	else if(s_SettingsPage == 3)
+		RenderSettingsGraphics(MainView);
+	else if(s_SettingsPage == 4)
+		RenderSettingsSound(MainView);
+
+	if(m_NeedRestart)
 	{
-		CUIRect restart_warning;
-		main_view.HSplitBottom(40, &main_view, &restart_warning);
-		UI()->DoLabel(&restart_warning, localize("You must restart the game for all settings to take effect."), 15.0f, -1, 220);
+		CUIRect RestartWarning;
+		MainView.HSplitBottom(40, &MainView, &RestartWarning);
+		UI()->DoLabel(&RestartWarning, Localize("You must restart the game for all settings to take effect."), 15.0f, -1, 220);
 	}
 }
diff --git a/src/game/client/components/motd.cpp b/src/game/client/components/motd.cpp
index ba85f7f8..5905d52e 100644
--- a/src/game/client/components/motd.cpp
+++ b/src/game/client/components/motd.cpp
@@ -1,87 +1,91 @@
-#include <engine/e_client_interface.h>
-#include <engine/client/graphics.h>
-#include <engine/e_config.h>
-#include <game/generated/g_protocol.hpp>
-#include <game/generated/gc_data.hpp>
+#include <engine/shared/config.h>
+#include <engine/graphics.h>
+#include <engine/textrender.h>
+#include <engine/keys.h>
 
-#include <game/client/gameclient.hpp>
+#include <game/generated/protocol.h>
+#include <game/generated/client_data.h>
+#include <game/client/gameclient.h>
 
-#include "motd.hpp"
+#include "motd.h"
 
-void MOTD::clear()
+void CMotd::Clear()
 {
-	server_motd_time = 0;
+	m_ServerMotdTime = 0;
 }
 
-bool MOTD::is_active()
+bool CMotd::IsActive()
 {
-	return time_get() < server_motd_time;	
+	return time_get() < m_ServerMotdTime;	
 }
 
-void MOTD::on_statechange(int new_state, int old_state)
+void CMotd::OnStateChange(int NewState, int OldState)
 {
-	if(old_state == CLIENTSTATE_ONLINE || old_state == CLIENTSTATE_OFFLINE)
-		clear();
+	if(OldState == IClient::STATE_ONLINE || OldState == IClient::STATE_OFFLINE)
+		Clear();
 }
 
-void MOTD::on_render()
+void CMotd::OnRender()
 {
-	if(!is_active())
+	if(!IsActive())
 		return;
 		
-	float width = 400*3.0f*Graphics()->ScreenAspect();
-	float height = 400*3.0f;
+	float Width = 400*3.0f*Graphics()->ScreenAspect();
+	float Height = 400*3.0f;
 
-	Graphics()->MapScreen(0, 0, width, height);
+	Graphics()->MapScreen(0, 0, Width, Height);
 	
 	float h = 800.0f;
 	float w = 650.0f;
-	float x = width/2 - w/2;
+	float x = Width/2 - w/2;
 	float y = 150.0f;
 
 	Graphics()->BlendNormal();
 	Graphics()->TextureSet(-1);
 	Graphics()->QuadsBegin();
 	Graphics()->SetColor(0,0,0,0.5f);
-	RenderTools()->draw_round_rect(x, y, w, h, 40.0f);
+	RenderTools()->DrawRoundRect(x, y, w, h, 40.0f);
 	Graphics()->QuadsEnd();
 
-	gfx_text(0, x+40.0f, y+40.0f, 32.0f, server_motd, (int)(w-80.0f));
+	TextRender()->Text(0, x+40.0f, y+40.0f, 32.0f, m_aServerMotd, (int)(w-80.0f));
 }
 
-void MOTD::on_message(int msgtype, void *rawmsg)
+void CMotd::OnMessage(int MsgType, void *pRawMsg)
 {
-	if(msgtype == NETMSGTYPE_SV_MOTD)
+	if(Client()->State() == IClient::STATE_DEMOPLAYBACK)
+		return;
+
+	if(MsgType == NETMSGTYPE_SV_MOTD)
 	{
-		NETMSG_SV_MOTD *msg = (NETMSG_SV_MOTD *)rawmsg;
+		CNetMsg_Sv_Motd *pMsg = (CNetMsg_Sv_Motd *)pRawMsg;
 
 		// process escaping			
-		str_copy(server_motd, msg->message, sizeof(server_motd));
-		for(int i = 0; server_motd[i]; i++)
+		str_copy(m_aServerMotd, pMsg->m_pMessage, sizeof(m_aServerMotd));
+		for(int i = 0; m_aServerMotd[i]; i++)
 		{
-			if(server_motd[i] == '\\')
+			if(m_aServerMotd[i] == '\\')
 			{
-				if(server_motd[i+1] == 'n')
+				if(m_aServerMotd[i+1] == 'n')
 				{
-					server_motd[i] = ' ';
-					server_motd[i+1] = '\n';
+					m_aServerMotd[i] = ' ';
+					m_aServerMotd[i+1] = '\n';
 					i++;
 				}
 			}
 		}
 
-		if(server_motd[0] && config.cl_motd_time)
-			server_motd_time = time_get()+time_freq()*config.cl_motd_time;
+		if(m_aServerMotd[0] && g_Config.m_ClMotdTime)
+			m_ServerMotdTime = time_get()+time_freq()*g_Config.m_ClMotdTime;
 		else
-			server_motd_time = 0;
+			m_ServerMotdTime = 0;
 	}
 }
 
-bool MOTD::on_input(INPUT_EVENT e)
+bool CMotd::OnInput(IInput::CEvent Event)
 {
-	if(is_active() && e.flags&INPFLAG_PRESS && e.key == KEY_ESCAPE)
+	if(IsActive() && Event.m_Flags&IInput::FLAG_PRESS && Event.m_Key == KEY_ESCAPE)
 	{
-		clear();
+		Clear();
 		return true;
 	}
 	return false;
diff --git a/src/game/client/components/motd.h b/src/game/client/components/motd.h
new file mode 100644
index 00000000..41e15b8c
--- /dev/null
+++ b/src/game/client/components/motd.h
@@ -0,0 +1,21 @@
+#ifndef GAME_CLIENT_COMPONENTS_MOTD_H
+#define GAME_CLIENT_COMPONENTS_MOTD_H
+#include <game/client/component.h>
+
+class CMotd : public CComponent
+{
+	// motd
+	int64 m_ServerMotdTime;
+public:
+	char m_aServerMotd[900];
+
+	void Clear();
+	bool IsActive();
+	
+	virtual void OnRender();
+	virtual void OnStateChange(int NewState, int OldState);
+	virtual void OnMessage(int MsgType, void *pRawMsg);
+	virtual bool OnInput(IInput::CEvent Event);
+};
+
+#endif
diff --git a/src/game/client/components/motd.hpp b/src/game/client/components/motd.hpp
deleted file mode 100644
index 3b175e0a..00000000
--- a/src/game/client/components/motd.hpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <game/client/component.hpp>
-
-class MOTD : public COMPONENT
-{
-	// motd
-	int64 server_motd_time;
-public:
-	char server_motd[900];
-
-	void clear();
-	bool is_active();
-	
-	virtual void on_render();
-	virtual void on_statechange(int new_state, int old_state);
-	virtual void on_message(int msgtype, void *rawmsg);
-	virtual bool on_input(INPUT_EVENT e);
-};
-
diff --git a/src/game/client/components/nameplates.cpp b/src/game/client/components/nameplates.cpp
index 4a47ea37..da114bbb 100644
--- a/src/game/client/components/nameplates.cpp
+++ b/src/game/client/components/nameplates.cpp
@@ -1,65 +1,66 @@
-#include <engine/e_client_interface.h>
-#include <game/generated/g_protocol.hpp>
-#include <game/generated/gc_data.hpp>
+#include <engine/textrender.h>
+#include <engine/shared/config.h>
+#include <game/generated/protocol.h>
+#include <game/generated/client_data.h>
 
-#include <game/client/gameclient.hpp>
-#include <game/client/animstate.hpp>
-#include "nameplates.hpp"
-#include "controls.hpp"
+#include <game/client/gameclient.h>
+#include <game/client/animstate.h>
+#include "nameplates.h"
+#include "controls.h"
 
-void NAMEPLATES::render_nameplate(
-	const NETOBJ_CHARACTER *prev_char,
-	const NETOBJ_CHARACTER *player_char,
-	const NETOBJ_PLAYER_INFO *player_info
+void CNamePlates::RenderNameplate(
+	const CNetObj_Character *pPrevChar,
+	const CNetObj_Character *pPlayerChar,
+	const CNetObj_PlayerInfo *pPlayerInfo
 	)
 {
-	float intratick = client_intratick();
+	float IntraTick = Client()->IntraGameTick();
 	
-	vec2 position = mix(vec2(prev_char->x, prev_char->y), vec2(player_char->x, player_char->y), intratick);
+	vec2 Position = mix(vec2(pPrevChar->m_X, pPrevChar->m_Y), vec2(pPlayerChar->m_X, pPlayerChar->m_Y), IntraTick);
 	
 	// render name plate
-	if(!player_info->local)
+	if(!pPlayerInfo->m_Local)
 	{
-		//gfx_text_color
+		//TextRender()->TextColor
 		float a = 1;
-		if(config.cl_nameplates_always == 0)
-			a = clamp(1-powf(distance(gameclient.controls->target_pos, position)/200.0f,16.0f), 0.0f, 1.0f);
+		if(g_Config.m_ClNameplatesAlways == 0)
+			a = clamp(1-powf(distance(m_pClient->m_pControls->m_TargetPos, Position)/200.0f,16.0f), 0.0f, 1.0f);
 			
-		const char *name = gameclient.clients[player_info->cid].name;
-		float tw = gfx_text_width(0, 28.0f, name, -1);
-		gfx_text_color(1,1,1,a);
-		gfx_text(0, position.x-tw/2.0f, position.y-60, 28.0f, name, -1);
+		const char *pName = m_pClient->m_aClients[pPlayerInfo->m_ClientId].m_aName;
+		float tw = TextRender()->TextWidth(0, 28.0f, pName, -1);
+		TextRender()->TextColor(1,1,1,a);
+		TextRender()->Text(0, Position.x-tw/2.0f, Position.y-60, 28.0f, pName, -1);
 		
-		if(config.debug) // render client id when in debug aswell
+		if(g_Config.m_Debug) // render client id when in debug aswell
 		{
-			char buf[128];
-			str_format(buf, sizeof(buf),"%d", player_info->cid);
-			gfx_text(0, position.x, position.y-90, 28.0f, buf, -1);
+			char aBuf[128];
+			str_format(aBuf, sizeof(aBuf),"%d", pPlayerInfo->m_ClientId);
+			TextRender()->Text(0, Position.x, Position.y-90, 28.0f, aBuf, -1);
 		}
 
-		gfx_text_color(1,1,1,1);
+		TextRender()->TextColor(1,1,1,1);
 	}
 }
 
-void NAMEPLATES::on_render()
+void CNamePlates::OnRender()
 {
-	if (!config.cl_nameplates)
+	if (!g_Config.m_ClNameplates)
 		return;
 
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
 		// only render active characters
-		if(!gameclient.snap.characters[i].active)
+		if(!m_pClient->m_Snap.m_aCharacters[i].m_Active)
 			continue;
 
-		const void *info = snap_find_item(SNAP_CURRENT, NETOBJTYPE_PLAYER_INFO, i);
+		const void *pInfo = Client()->SnapFindItem(IClient::SNAP_CURRENT, NETOBJTYPE_PLAYERINFO, i);
 
-		if(info)
+		if(pInfo)
 		{
-			render_nameplate(
-				&gameclient.snap.characters[i].prev,
-				&gameclient.snap.characters[i].cur,
-				(const NETOBJ_PLAYER_INFO *)info);
+			RenderNameplate(
+				&m_pClient->m_Snap.m_aCharacters[i].m_Prev,
+				&m_pClient->m_Snap.m_aCharacters[i].m_Cur,
+				(const CNetObj_PlayerInfo *)pInfo);
 		}
 	}
 }
diff --git a/src/game/client/components/nameplates.h b/src/game/client/components/nameplates.h
new file mode 100644
index 00000000..279b6582
--- /dev/null
+++ b/src/game/client/components/nameplates.h
@@ -0,0 +1,17 @@
+#ifndef GAME_CLIENT_COMPONENTS_NAMEPLATES_H
+#define GAME_CLIENT_COMPONENTS_NAMEPLATES_H
+#include <game/client/component.h>
+
+class CNamePlates : public CComponent
+{
+	void RenderNameplate(
+		const class CNetObj_Character *pPrevChar,
+		const class CNetObj_Character *pPlayerChar,
+		const class CNetObj_PlayerInfo *pPlayerInfo
+	);
+
+public:
+	virtual void OnRender();
+};
+
+#endif
diff --git a/src/game/client/components/nameplates.hpp b/src/game/client/components/nameplates.hpp
deleted file mode 100644
index 2695f5ac..00000000
--- a/src/game/client/components/nameplates.hpp
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <game/client/component.hpp>
-
-class NAMEPLATES : public COMPONENT
-{
-	void render_nameplate(
-		const class NETOBJ_CHARACTER *prev_char,
-		const class NETOBJ_CHARACTER *player_char,
-		const class NETOBJ_PLAYER_INFO *player_info
-	);
-
-public:
-	virtual void on_render();
-};
-
diff --git a/src/game/client/components/particles.cpp b/src/game/client/components/particles.cpp
index 61fcf738..99c2c721 100644
--- a/src/game/client/components/particles.cpp
+++ b/src/game/client/components/particles.cpp
@@ -1,155 +1,156 @@
-#include <base/math.hpp>
-#include <engine/client/graphics.h>
+#include <base/math.h>
+#include <engine/graphics.h>
 
-#include <game/generated/gc_data.hpp>
-#include <game/client/render.hpp>
-#include <game/gamecore.hpp>
-#include "particles.hpp"
+#include <game/generated/client_data.h>
+#include <game/client/render.h>
+#include <game/gamecore.h>
+#include "particles.h"
 
-PARTICLES::PARTICLES()
+CParticles::CParticles()
 {
-	on_reset();
-	render_trail.parts = this;
-	render_explosions.parts = this;
-	render_general.parts = this;
+	OnReset();
+	m_RenderTrail.m_pParts = this;
+	m_RenderExplosions.m_pParts = this;
+	m_RenderGeneral.m_pParts = this;
 }
 
 
-void PARTICLES::on_reset()
+void CParticles::OnReset()
 {
 	// reset particles
 	for(int i = 0; i < MAX_PARTICLES; i++)
 	{
-		particles[i].prev_part = i-1;
-		particles[i].next_part = i+1;
+		m_aParticles[i].m_PrevPart = i-1;
+		m_aParticles[i].m_NextPart = i+1;
 	}
 	
-	particles[0].prev_part = 0;
-	particles[MAX_PARTICLES-1].next_part = -1;
-	first_free = 0;
+	m_aParticles[0].m_PrevPart = 0;
+	m_aParticles[MAX_PARTICLES-1].m_NextPart = -1;
+	m_FirstFree = 0;
 
 	for(int i = 0; i < NUM_GROUPS; i++)
-		first_part[i] = -1;
+		m_aFirstPart[i] = -1;
 }
 
-void PARTICLES::add(int group, PARTICLE *part)
+void CParticles::Add(int Group, CParticle *pPart)
 {
-	if (first_free == -1)
+	if (m_FirstFree == -1)
 		return;
 		
 	// remove from the free list
-	int id = first_free;
-	first_free = particles[id].next_part;
-	particles[first_free].prev_part = -1;
+	int Id = m_FirstFree;
+	m_FirstFree = m_aParticles[Id].m_NextPart;
+	m_aParticles[m_FirstFree].m_PrevPart = -1;
 	
 	// copy data
-	particles[id] = *part;
+	m_aParticles[Id] = *pPart;
 	
 	// insert to the group list
-	particles[id].prev_part = -1;
-	particles[id].next_part = first_part[group];
-	if(first_part[group] != -1)
-		particles[first_part[group]].prev_part = id;
-	first_part[group] = id;
+	m_aParticles[Id].m_PrevPart = -1;
+	m_aParticles[Id].m_NextPart = m_aFirstPart[Group];
+	if(m_aFirstPart[Group] != -1)
+		m_aParticles[m_aFirstPart[Group]].m_PrevPart = Id;
+	m_aFirstPart[Group] = Id;
 	
 	// set some parameters
-	particles[id].life = 0;
+	m_aParticles[Id].m_Life = 0;
 }
 
-void PARTICLES::update(float time_passed)
+void CParticles::Update(float TimePassed)
 {
-	static float friction_fraction = 0;
-	friction_fraction += time_passed;
+	static float FrictionFraction = 0;
+	FrictionFraction += TimePassed;
 
-	if(friction_fraction > 2.0f) // safty messure
-		friction_fraction = 0;
+	if(FrictionFraction > 2.0f) // safty messure
+		FrictionFraction = 0;
 	
-	int friction_count = 0;
-	while(friction_fraction > 0.05f)
+	int FrictionCount = 0;
+	while(FrictionFraction > 0.05f)
 	{
-		friction_count++;
-		friction_fraction -= 0.05f;
+		FrictionCount++;
+		FrictionFraction -= 0.05f;
 	}
 	
 	for(int g = 0; g < NUM_GROUPS; g++)
 	{
-		int i = first_part[g];
+		int i = m_aFirstPart[g];
 		while(i != -1)
 		{
-			int next = particles[i].next_part;
-			//particles[i].vel += flow_get(particles[i].pos)*time_passed * particles[i].flow_affected;
-			particles[i].vel.y += particles[i].gravity*time_passed;
+			int Next = m_aParticles[i].m_NextPart;
+			//m_aParticles[i].vel += flow_get(m_aParticles[i].pos)*time_passed * m_aParticles[i].flow_affected;
+			m_aParticles[i].m_Vel.y += m_aParticles[i].m_Gravity*TimePassed;
 			
-			for(int f = 0; f < friction_count; f++) // apply friction
-				particles[i].vel *= particles[i].friction;
+			for(int f = 0; f < FrictionCount; f++) // apply friction
+				m_aParticles[i].m_Vel *= m_aParticles[i].m_Friction;
 			
 			// move the point
-			vec2 vel = particles[i].vel*time_passed;
-			move_point(&particles[i].pos, &vel, 0.1f+0.9f*frandom(), NULL);
-			particles[i].vel = vel* (1.0f/time_passed);
+			vec2 Vel = m_aParticles[i].m_Vel*TimePassed;
+			Collision()->MovePoint(&m_aParticles[i].m_Pos, &Vel, 0.1f+0.9f*frandom(), NULL);
+			m_aParticles[i].m_Vel = Vel* (1.0f/TimePassed);
 			
-			particles[i].life += time_passed;
-			particles[i].rot += time_passed * particles[i].rotspeed;
+			m_aParticles[i].m_Life += TimePassed;
+			m_aParticles[i].m_Rot += TimePassed * m_aParticles[i].m_Rotspeed;
 
 			// check particle death
-			if(particles[i].life > particles[i].life_span)
+			if(m_aParticles[i].m_Life > m_aParticles[i].m_LifeSpan)
 			{
 				// remove it from the group list
-				if(particles[i].prev_part != -1)
-					particles[particles[i].prev_part].next_part = particles[i].next_part;
+				if(m_aParticles[i].m_PrevPart != -1)
+					m_aParticles[m_aParticles[i].m_PrevPart].m_NextPart = m_aParticles[i].m_NextPart;
 				else
-					first_part[g] = particles[i].next_part;
+					m_aFirstPart[g] = m_aParticles[i].m_NextPart;
 					
-				if(particles[i].next_part != -1)
-					particles[particles[i].next_part].prev_part = particles[i].prev_part;
+				if(m_aParticles[i].m_NextPart != -1)
+					m_aParticles[m_aParticles[i].m_NextPart].m_PrevPart = m_aParticles[i].m_PrevPart;
 					
 				// insert to the free list
-				if(first_free != -1)
-					particles[first_free].prev_part = i;
-				particles[i].prev_part = -1;
-				particles[i].next_part = first_free;
-				first_free = i;
+				if(m_FirstFree != -1)
+					m_aParticles[m_FirstFree].m_PrevPart = i;
+				m_aParticles[i].m_PrevPart = -1;
+				m_aParticles[i].m_NextPart = m_FirstFree;
+				m_FirstFree = i;
 			}
 			
-			i = next;
+			i = Next;
 		}
 	}
 }
 
-void PARTICLES::on_render()
+void CParticles::OnRender()
 {
-	static int64 lasttime = 0;
+	static int64 LastTime = 0;
 	int64 t = time_get();
-	update((float)((t-lasttime)/(double)time_freq()));
-	lasttime = t;
+	Update((float)((t-LastTime)/(double)time_freq()));
+	LastTime = t;
 }
 
-void PARTICLES::render_group(int group)
+void CParticles::RenderGroup(int Group)
 {
 	Graphics()->BlendNormal();
 	//gfx_blend_additive();
-	Graphics()->TextureSet(data->images[IMAGE_PARTICLES].id);
+	Graphics()->TextureSet(g_pData->m_aImages[IMAGE_PARTICLES].m_Id);
 	Graphics()->QuadsBegin();
 
-	int i = first_part[group];
+	int i = m_aFirstPart[Group];
 	while(i != -1)
 	{
-		RenderTools()->select_sprite(particles[i].spr);
-		float a = particles[i].life / particles[i].life_span;
-		vec2 p = particles[i].pos;
-		float size = mix(particles[i].start_size, particles[i].end_size, a);
+		RenderTools()->SelectSprite(m_aParticles[i].m_Spr);
+		float a = m_aParticles[i].m_Life / m_aParticles[i].m_LifeSpan;
+		vec2 p = m_aParticles[i].m_Pos;
+		float Size = mix(m_aParticles[i].m_StartSize, m_aParticles[i].m_EndSize, a);
 
-		Graphics()->QuadsSetRotation(particles[i].rot);
+		Graphics()->QuadsSetRotation(m_aParticles[i].m_Rot);
 
 		Graphics()->SetColor(
-			particles[i].color.r,
-			particles[i].color.g,
-			particles[i].color.b,
-			particles[i].color.a); // pow(a, 0.75f) * 
+			m_aParticles[i].m_Color.r,
+			m_aParticles[i].m_Color.g,
+			m_aParticles[i].m_Color.b,
+			m_aParticles[i].m_Color.a); // pow(a, 0.75f) * 
 
-		Graphics()->QuadsDraw(p.x, p.y, size, size);
+		IGraphics::CQuadItem QuadItem(p.x, p.y, Size, Size);
+		Graphics()->QuadsDraw(&QuadItem, 1);
 		
-		i = particles[i].next_part;
+		i = m_aParticles[i].m_NextPart;
 	}
 	Graphics()->QuadsEnd();
 	Graphics()->BlendNormal();
diff --git a/src/game/client/components/particles.h b/src/game/client/components/particles.h
new file mode 100644
index 00000000..af9a9203
--- /dev/null
+++ b/src/game/client/components/particles.h
@@ -0,0 +1,94 @@
+#ifndef GAME_CLIENT_COMPONENTS_PARTICLES_H
+#define GAME_CLIENT_COMPONENTS_PARTICLES_H
+#include <base/vmath.h>
+#include <game/client/component.h>
+
+// particles
+struct CParticle
+{
+	void SetDefault()
+	{
+		m_Vel = vec2(0,0);
+		m_LifeSpan = 0;
+		m_StartSize = 32;
+		m_EndSize = 32;
+		m_Rot = 0;
+		m_Rotspeed = 0;
+		m_Gravity = 0;
+		m_Friction = 0;
+		m_FlowAffected = 1.0f;
+		m_Color = vec4(1,1,1,1);
+	}
+	
+	vec2 m_Pos;
+	vec2 m_Vel;
+
+	int m_Spr;
+
+	float m_FlowAffected;
+
+	float m_LifeSpan;
+	
+	float m_StartSize;
+	float m_EndSize;
+
+	float m_Rot;
+	float m_Rotspeed;
+
+	float m_Gravity;
+	float m_Friction;
+
+	vec4 m_Color;
+	
+	// set by the particle system
+	float m_Life;
+	int m_PrevPart;
+	int m_NextPart;
+};
+
+class CParticles : public CComponent
+{
+	friend class CGameClient;
+public:
+	enum
+	{
+		GROUP_PROJECTILE_TRAIL=0,
+		GROUP_EXPLOSIONS,
+		GROUP_GENERAL,
+		NUM_GROUPS
+	};
+
+	CParticles();
+	
+	void Add(int Group, CParticle *pPart);
+	
+	virtual void OnReset();
+	virtual void OnRender();
+
+private:
+	
+	enum
+	{
+		MAX_PARTICLES=1024*8,
+	};
+
+	CParticle m_aParticles[MAX_PARTICLES];
+	int m_FirstFree;
+	int m_aFirstPart[NUM_GROUPS];
+	
+	void RenderGroup(int Group);
+	void Update(float TimePassed);
+
+	template<int TGROUP>
+	class CRenderGroup : public CComponent
+	{
+	public:
+		CParticles *m_pParts;
+		virtual void OnRender() { m_pParts->RenderGroup(TGROUP); }
+	};
+	
+	CRenderGroup<GROUP_PROJECTILE_TRAIL> m_RenderTrail;
+	CRenderGroup<GROUP_EXPLOSIONS> m_RenderExplosions;
+	CRenderGroup<GROUP_GENERAL> m_RenderGeneral;
+};
+#endif
diff --git a/src/game/client/components/particles.hpp b/src/game/client/components/particles.hpp
deleted file mode 100644
index 6c466d94..00000000
--- a/src/game/client/components/particles.hpp
+++ /dev/null
@@ -1,91 +0,0 @@
-#include <base/vmath.hpp>
-#include <game/client/component.hpp>
-
-// particles
-struct PARTICLE
-{
-	void set_default()
-	{
-		vel = vec2(0,0);
-		life_span = 0;
-		start_size = 32;
-		end_size = 32;
-		rot = 0;
-		rotspeed = 0;
-		gravity = 0;
-		friction = 0;
-		flow_affected = 1.0f;
-		color = vec4(1,1,1,1);
-	}
-	
-	vec2 pos;
-	vec2 vel;
-
-	int spr;
-
-	float flow_affected;
-
-	float life_span;
-	
-	float start_size;
-	float end_size;
-
-	float rot;
-	float rotspeed;
-
-	float gravity;
-	float friction;
-
-	vec4 color;
-	
-	// set by the particle system
-	float life;
-	int prev_part;
-	int next_part;
-};
-
-class PARTICLES : public COMPONENT
-{
-	friend class GAMECLIENT;
-public:
-	enum
-	{
-		GROUP_PROJECTILE_TRAIL=0,
-		GROUP_EXPLOSIONS,
-		GROUP_GENERAL,
-		NUM_GROUPS
-	};
-
-	PARTICLES();
-	
-	void add(int group, PARTICLE *part);
-	
-	virtual void on_reset();
-	virtual void on_render();
-
-private:
-	
-	enum
-	{
-		MAX_PARTICLES=1024*8,
-	};
-
-	PARTICLE particles[MAX_PARTICLES];
-	int first_free;
-	int first_part[NUM_GROUPS];
-	
-	void render_group(int group);
-	void update(float time_passed);
-
-	template<int TGROUP>
-	class RENDER_GROUP : public COMPONENT
-	{
-	public:
-		PARTICLES *parts;
-		virtual void on_render() { parts->render_group(TGROUP); }
-	};
-	
-	RENDER_GROUP<GROUP_PROJECTILE_TRAIL> render_trail;
-	RENDER_GROUP<GROUP_EXPLOSIONS> render_explosions;
-	RENDER_GROUP<GROUP_GENERAL> render_general;
-};
diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp
index e1fee3e8..8ad7b0cb 100644
--- a/src/game/client/components/players.cpp
+++ b/src/game/client/components/players.cpp
@@ -1,147 +1,269 @@
-#include <engine/e_client_interface.h>
-#include <engine/client/graphics.h>
-#include <game/generated/g_protocol.hpp>
-#include <game/generated/gc_data.hpp>
-
-#include <game/gamecore.hpp> // get_angle
-#include <game/client/animstate.hpp>
-#include <game/client/gameclient.hpp>
-#include <game/client/ui.hpp>
-#include <game/client/render.hpp>
-
-#include <game/client/components/flow.hpp>
-#include <game/client/components/skins.hpp>
-#include <game/client/components/effects.hpp>
-#include <game/client/components/sounds.hpp>
-#include <game/client/components/controls.hpp>
-
-#include "players.hpp"
-
-void PLAYERS::render_hand(TEE_RENDER_INFO *info, vec2 center_pos, vec2 dir, float angle_offset, vec2 post_rot_offset)
+#include <engine/graphics.h>
+#include <engine/shared/config.h>
+#include <game/generated/protocol.h>
+#include <game/generated/client_data.h>
+
+#include <game/gamecore.h> // get_angle
+#include <game/client/animstate.h>
+#include <game/client/gameclient.h>
+#include <game/client/ui.h>
+#include <game/client/render.h>
+
+#include <game/client/components/flow.h>
+#include <game/client/components/skins.h>
+#include <game/client/components/effects.h>
+#include <game/client/components/sounds.h>
+#include <game/client/components/controls.h>
+
+#include "players.h"
+
+void CPlayers::RenderHand(CTeeRenderInfo *pInfo, vec2 CenterPos, vec2 Dir, float AngleOffset, vec2 PostRotOffset)
 {
 	// for drawing hand
 	//const skin *s = skin_get(skin_id);
 	
-	float basesize = 10.0f;
+	float BaseSize = 10.0f;
 	//dir = normalize(hook_pos-pos);
 
-	vec2 hand_pos = center_pos + dir;
-	float angle = get_angle(dir);
-	if (dir.x < 0)
-		angle -= angle_offset;
+	vec2 HandPos = CenterPos + Dir;
+	float Angle = GetAngle(Dir);
+	if (Dir.x < 0)
+		Angle -= AngleOffset;
 	else
-		angle += angle_offset;
+		Angle += AngleOffset;
 
-	vec2 dirx = dir;
-	vec2 diry(-dir.y,dir.x);
+	vec2 DirX = Dir;
+	vec2 DirY(-Dir.y,Dir.x);
 
-	if (dir.x < 0)
-		diry = -diry;
+	if (Dir.x < 0)
+		DirY = -DirY;
 
-	hand_pos += dirx * post_rot_offset.x;
-	hand_pos += diry * post_rot_offset.y;
+	HandPos += DirX * PostRotOffset.x;
+	HandPos += DirY * PostRotOffset.y;
 
-	//Graphics()->TextureSet(data->images[IMAGE_CHAR_DEFAULT].id);
-	Graphics()->TextureSet(info->texture);
+	//Graphics()->TextureSet(data->m_aImages[IMAGE_CHAR_DEFAULT].id);
+	Graphics()->TextureSet(pInfo->m_Texture);
 	Graphics()->QuadsBegin();
-	Graphics()->SetColor(info->color_body.r, info->color_body.g, info->color_body.b, info->color_body.a);
+	Graphics()->SetColor(pInfo->m_ColorBody.r, pInfo->m_ColorBody.g, pInfo->m_ColorBody.b, pInfo->m_ColorBody.a);
 
 	// two passes
 	for (int i = 0; i < 2; i++)
 	{
-		bool outline = i == 0;
+		bool OutLine = i == 0;
 
-		RenderTools()->select_sprite(outline?SPRITE_TEE_HAND_OUTLINE:SPRITE_TEE_HAND, 0, 0, 0);
-		Graphics()->QuadsSetRotation(angle);
-		Graphics()->QuadsDraw(hand_pos.x, hand_pos.y, 2*basesize, 2*basesize);
+		RenderTools()->SelectSprite(OutLine?SPRITE_TEE_HAND_OUTLINE:SPRITE_TEE_HAND, 0, 0, 0);
+		Graphics()->QuadsSetRotation(Angle);
+		IGraphics::CQuadItem QuadItem(HandPos.x, HandPos.y, 2*BaseSize, 2*BaseSize);
+		Graphics()->QuadsDraw(&QuadItem, 1);
 	}
 
 	Graphics()->QuadsSetRotation(0);
 	Graphics()->QuadsEnd();
 }
 
-inline float normalize_angular(float f)
+inline float NormalizeAngular(float f)
 {
 	return fmod(f+pi*2, pi*2);
 }
 
-inline float angular_mix_direction(float src, float dst) { return sinf(dst-src) >0?1:-1; }
-inline float angular_distance(float src, float dst) { return asinf(sinf(dst-src)); }
+inline float AngularMixDirection (float Src, float Dst) { return sinf(Dst-Src) >0?1:-1; }
+inline float AngularDistance(float Src, float Dst) { return asinf(sinf(Dst-Src)); }
 
-inline float angular_approach(float src, float dst, float amount)
+inline float AngularApproach(float Src, float Dst, float Amount)
 {
-	float d = angular_mix_direction(src, dst);
-	float n = src + amount*d;
-	if(angular_mix_direction(n, dst) != d)
-		return dst;
+	float d = AngularMixDirection (Src, Dst);
+	float n = Src + Amount*d;
+	if(AngularMixDirection (n, Dst) != d)
+		return Dst;
 	return n;
 }
 
-void PLAYERS::render_player(
-	const NETOBJ_CHARACTER *prev_char,
-	const NETOBJ_CHARACTER *player_char,
-	const NETOBJ_PLAYER_INFO *prev_info,
-	const NETOBJ_PLAYER_INFO *player_info
+void CPlayers::RenderHook(
+	const CNetObj_Character *pPrevChar,
+	const CNetObj_Character *pPlayerChar,
+	const CNetObj_PlayerInfo *pPrevInfo,
+	const CNetObj_PlayerInfo *pPlayerInfo
 	)
 {
-	NETOBJ_CHARACTER prev;
-	NETOBJ_CHARACTER player;
-	prev = *prev_char;
-	player = *player_char;
+	CNetObj_Character Prev;
+	CNetObj_Character Player;
+	Prev = *pPrevChar;
+	Player = *pPlayerChar;
 
-	NETOBJ_PLAYER_INFO info = *player_info;
-	TEE_RENDER_INFO render_info = gameclient.clients[info.cid].render_info;
+	CNetObj_PlayerInfo pInfo = *pPlayerInfo;
+	CTeeRenderInfo RenderInfo = m_pClient->m_aClients[pInfo.m_ClientId].m_RenderInfo;
 
 	// check for teamplay modes
-	bool is_teamplay = false;
-	bool new_tick = gameclient.new_tick;
-	if(gameclient.snap.gameobj)
-		is_teamplay = (gameclient.snap.gameobj->flags&GAMEFLAG_TEAMS) != 0;
+	bool IsTeamplay = false;
+	if(m_pClient->m_Snap.m_pGameobj)
+		IsTeamplay = (m_pClient->m_Snap.m_pGameobj->m_Flags&GAMEFLAG_TEAMS) != 0;
 
 	// check for ninja	
-	if (player.weapon == WEAPON_NINJA)
+	if (Player.m_Weapon == WEAPON_NINJA)
 	{
 		// change the skin for the player to the ninja
-		int skin = gameclient.skins->find("x_ninja");
-		if(skin != -1)
+		int Skin = m_pClient->m_pSkins->Find("x_ninja");
+		if(Skin != -1)
 		{
-			if(is_teamplay)
-				render_info.texture = gameclient.skins->get(skin)->color_texture;
+			if(IsTeamplay)
+				RenderInfo.m_Texture = m_pClient->m_pSkins->Get(Skin)->m_ColorTexture;
 			else
 			{
-				render_info.texture = gameclient.skins->get(skin)->org_texture;
-				render_info.color_body = vec4(1,1,1,1);
-				render_info.color_feet = vec4(1,1,1,1);
+				RenderInfo.m_Texture = m_pClient->m_pSkins->Get(Skin)->m_OrgTexture;
+				RenderInfo.m_ColorBody = vec4(1,1,1,1);
+				RenderInfo.m_ColorFeet = vec4(1,1,1,1);
+			}
+		}	
+	}
+
+	float IntraTick = Client()->IntraGameTick();
+
+	if(Player.m_Health < 0) // dont render dead players
+		return;
+
+	// set size
+	RenderInfo.m_Size = 64.0f;
+
+	
+	// use preditect players if needed
+	if(pInfo.m_Local && g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK)
+	{
+		if(!m_pClient->m_Snap.m_pLocalCharacter || (m_pClient->m_Snap.m_pLocalCharacter->m_Health < 0) || (m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver))
+		{
+		}
+		else
+		{
+			// apply predicted results
+			m_pClient->m_PredictedChar.Write(&Player);
+			m_pClient->m_PredictedPrevChar.Write(&Prev);
+			IntraTick = Client()->PredIntraGameTick();
+		}
+	}
+
+	vec2 Position = mix(vec2(Prev.m_X, Prev.m_Y), vec2(Player.m_X, Player.m_Y), IntraTick);
+
+	if(Prev.m_Health < 0) // Don't flicker from previous position
+		Position = vec2(Player.m_X, Player.m_Y);
+
+	// draw hook
+	if (Prev.m_HookState>0 && Player.m_HookState>0)
+	{
+		Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
+		Graphics()->QuadsBegin();
+		//Graphics()->QuadsBegin();
+
+		vec2 Pos = Position;
+		vec2 HookPos;
+		
+		if(pPlayerChar->m_HookedPlayer != -1)
+		{
+			if(m_pClient->m_Snap.m_pLocalInfo && pPlayerChar->m_HookedPlayer == m_pClient->m_Snap.m_pLocalInfo->m_ClientId)
+			{
+				if(Client()->State() == IClient::STATE_DEMOPLAYBACK) // only use prediction if needed
+					HookPos = vec2(m_pClient->m_LocalCharacterPos.x, m_pClient->m_LocalCharacterPos.y);
+				else
+					HookPos = mix(vec2(m_pClient->m_PredictedPrevChar.m_Pos.x, m_pClient->m_PredictedPrevChar.m_Pos.y),
+						vec2(m_pClient->m_PredictedChar.m_Pos.x, m_pClient->m_PredictedChar.m_Pos.y), Client()->PredIntraGameTick());
+			}
+			else
+				HookPos = mix(vec2(pPrevChar->m_HookX, pPrevChar->m_HookY), vec2(pPlayerChar->m_HookX, pPlayerChar->m_HookY), Client()->IntraGameTick());
+		}
+		else
+			HookPos = mix(vec2(Prev.m_HookX, Prev.m_HookY), vec2(Player.m_HookX, Player.m_HookY), IntraTick);
+
+		float d = distance(Pos, HookPos);
+		vec2 Dir = normalize(Pos-HookPos);
+
+		Graphics()->QuadsSetRotation(GetAngle(Dir)+pi);
+
+		// render head
+		RenderTools()->SelectSprite(SPRITE_HOOK_HEAD);
+		IGraphics::CQuadItem QuadItem(HookPos.x, HookPos.y, 24,16);
+		Graphics()->QuadsDraw(&QuadItem, 1);
+
+		// render chain
+		RenderTools()->SelectSprite(SPRITE_HOOK_CHAIN);
+		IGraphics::CQuadItem Array[1024];
+		int i = 0;
+		for(float f = 24; f < d && i < 1024; f += 24, i++)
+		{
+			vec2 p = HookPos + Dir*f;
+			Array[i] = IGraphics::CQuadItem(p.x, p.y,24,16);
+		}
+
+		Graphics()->QuadsDraw(Array, i);
+		Graphics()->QuadsSetRotation(0);
+		Graphics()->QuadsEnd();
+
+		RenderHand(&RenderInfo, Position, normalize(HookPos-Pos), -pi/2, vec2(20, 0));
+	}
+}
+
+void CPlayers::RenderPlayer(
+	const CNetObj_Character *pPrevChar,
+	const CNetObj_Character *pPlayerChar,
+	const CNetObj_PlayerInfo *pPrevInfo,
+	const CNetObj_PlayerInfo *pPlayerInfo
+	)
+{
+	CNetObj_Character Prev;
+	CNetObj_Character Player;
+	Prev = *pPrevChar;
+	Player = *pPlayerChar;
+
+	CNetObj_PlayerInfo pInfo = *pPlayerInfo;
+	CTeeRenderInfo RenderInfo = m_pClient->m_aClients[pInfo.m_ClientId].m_RenderInfo;
+
+	// check for teamplay modes
+	bool IsTeamplay = false;
+	bool NewTick = m_pClient->m_NewTick;
+	if(m_pClient->m_Snap.m_pGameobj)
+		IsTeamplay = (m_pClient->m_Snap.m_pGameobj->m_Flags&GAMEFLAG_TEAMS) != 0;
+
+	// check for ninja	
+	if (Player.m_Weapon == WEAPON_NINJA)
+	{
+		// change the skin for the player to the ninja
+		int Skin = m_pClient->m_pSkins->Find("x_ninja");
+		if(Skin != -1)
+		{
+			if(IsTeamplay)
+				RenderInfo.m_Texture = m_pClient->m_pSkins->Get(Skin)->m_ColorTexture;
+			else
+			{
+				RenderInfo.m_Texture = m_pClient->m_pSkins->Get(Skin)->m_OrgTexture;
+				RenderInfo.m_ColorBody = vec4(1,1,1,1);
+				RenderInfo.m_ColorFeet = vec4(1,1,1,1);
 			}
 		}	
 	}
 	
 	// set size
-	render_info.size = 64.0f;
+	RenderInfo.m_Size = 64.0f;
 
-	float intratick = client_intratick();
+	float IntraTick = Client()->IntraGameTick();
 	
-	if(player.health < 0) // dont render dead players
+	if(Player.m_Health < 0) // dont render dead players
 		return;
 
-	float angle = mix((float)prev.angle, (float)player.angle, intratick)/256.0f;
+	float Angle = mix((float)Prev.m_Angle, (float)Player.m_Angle, IntraTick)/256.0f;
 	
 	//float angle = 0;
 	
-	if(info.local && client_state() != CLIENTSTATE_DEMOPLAYBACK)
+	if(pInfo.m_Local && Client()->State() != IClient::STATE_DEMOPLAYBACK)
 	{
 		// just use the direct input if it's local player we are rendering
-		angle = get_angle(gameclient.controls->mouse_pos);
+		Angle = GetAngle(m_pClient->m_pControls->m_MousePos);
 	}
 	else
 	{
 		/*
-		float mixspeed = client_frametime()*2.5f;
+		float mixspeed = Client()->FrameTime()*2.5f;
 		if(player.attacktick != prev.attacktick) // shooting boosts the mixing speed
 			mixspeed *= 15.0f;
 		
 		// move the delta on a constant speed on a x^2 curve
-		float current = gameclient.clients[info.cid].angle;
+		float current = g_GameClient.m_aClients[info.cid].angle;
 		float target = player.angle/256.0f;
 		float delta = angular_distance(current, target);
 		float sign = delta < 0 ? -1 : 1;
@@ -153,342 +275,305 @@ void PLAYERS::render_player(
 		else
 			angle = angular_approach(current, target, fabs(delta-new_delta));
 
-		gameclient.clients[info.cid].angle = angle;*/
+		g_GameClient.m_aClients[info.cid].angle = angle;*/
 	}
 	
 	// use preditect players if needed
-	if(info.local && config.cl_predict && client_state() != CLIENTSTATE_DEMOPLAYBACK)
+	if(pInfo.m_Local && g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK)
 	{
-		if(!gameclient.snap.local_character || (gameclient.snap.local_character->health < 0) || (gameclient.snap.gameobj && gameclient.snap.gameobj->game_over))
+		if(!m_pClient->m_Snap.m_pLocalCharacter || (m_pClient->m_Snap.m_pLocalCharacter->m_Health < 0) || (m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver))
 		{
 		}
 		else
 		{
 			// apply predicted results
-			gameclient.predicted_char.write(&player);
-			gameclient.predicted_prev_char.write(&prev);
-			intratick = client_predintratick();
-			new_tick = gameclient.new_predicted_tick;
+			m_pClient->m_PredictedChar.Write(&Player);
+			m_pClient->m_PredictedPrevChar.Write(&Prev);
+			IntraTick = Client()->PredIntraGameTick();
+			NewTick = m_pClient->m_NewPredictedTick;
 		}
 	}
 	
-	vec2 direction = get_direction((int)(angle*256.0f));
-	vec2 position = mix(vec2(prev.x, prev.y), vec2(player.x, player.y), intratick);
-	vec2 vel = mix(vec2(prev.vx/256.0f, prev.vy/256.0f), vec2(player.vx/256.0f, player.vy/256.0f), intratick);
+	vec2 Direction = GetDirection((int)(Angle*256.0f));
+	vec2 Position = mix(vec2(Prev.m_X, Prev.m_Y), vec2(Player.m_X, Player.m_Y), IntraTick);
+	vec2 Vel = mix(vec2(Prev.m_VelX/256.0f, Prev.m_VelY/256.0f), vec2(Player.m_VelX/256.0f, Player.m_VelY/256.0f), IntraTick);
 	
-	gameclient.flow->add(position, vel*100.0f, 10.0f);
+	m_pClient->m_pFlow->Add(Position, Vel*100.0f, 10.0f);
 	
-	render_info.got_airjump = player.jumped&2?0:1;
+	RenderInfo.m_GotAirJump = Player.m_Jumped&2?0:1;
 	
 	
 	// detect events
-	if(new_tick)
+	if(NewTick)
 	{
 		// detect air jump
-		if(!render_info.got_airjump && !(prev.jumped&2))
-			gameclient.effects->air_jump(position);
+		if(!RenderInfo.m_GotAirJump && !(Prev.m_Jumped&2))
+			m_pClient->m_pEffects->AirJump(Position);
 	}
 
-	if(prev.health < 0) // Don't flicker from previous position
-		position = vec2(player.x, player.y);
+	if(Prev.m_Health < 0) // Don't flicker from previous position
+		Position = vec2(Player.m_X, Player.m_Y);
 
-	bool stationary = player.vx < 1 && player.vx > -1;
-	bool inair = col_check_point(player.x, player.y+16) == 0;
-	bool want_other_dir = (player.direction == -1 && vel.x > 0) || (player.direction == 1 && vel.x < 0);
+	bool Stationary = Player.m_VelX <= 1 && Player.m_VelX >= -1;
+	bool InAir = !Collision()->CheckPoint(Player.m_X, Player.m_Y+16);
+	bool WantOtherDir = (Player.m_Direction == -1 && Vel.x > 0) || (Player.m_Direction == 1 && Vel.x < 0);
 
 	// evaluate animation
-	float walk_time = fmod(position.x, 100.0f)/100.0f;
-	ANIMSTATE state;
-	state.set(&data->animations[ANIM_BASE], 0);
-
-	if(inair)
-		state.add(&data->animations[ANIM_INAIR], 0, 1.0f); // TODO: some sort of time here
-	else if(stationary)
-		state.add(&data->animations[ANIM_IDLE], 0, 1.0f); // TODO: some sort of time here
-	else if(!want_other_dir)
-		state.add(&data->animations[ANIM_WALK], walk_time, 1.0f);
-
-	if (player.weapon == WEAPON_HAMMER)
+	float WalkTime = fmod(Position.x, 100.0f)/100.0f;
+	CAnimState State;
+	State.Set(&g_pData->m_aAnimations[ANIM_BASE], 0);
+
+	if(InAir)
+		State.Add(&g_pData->m_aAnimations[ANIM_INAIR], 0, 1.0f); // TODO: some sort of time here
+	else if(Stationary)
+		State.Add(&g_pData->m_aAnimations[ANIM_IDLE], 0, 1.0f); // TODO: some sort of time here
+	else if(!WantOtherDir)
+		State.Add(&g_pData->m_aAnimations[ANIM_WALK], WalkTime, 1.0f);
+
+	if (Player.m_Weapon == WEAPON_HAMMER)
 	{
-		float ct = (client_prevtick()-player.attacktick)/(float)SERVER_TICK_SPEED + client_ticktime();
-		state.add(&data->animations[ANIM_HAMMER_SWING], clamp(ct*5.0f,0.0f,1.0f), 1.0f);
+		float ct = (Client()->PrevGameTick()-Player.m_AttackTick)/(float)SERVER_TICK_SPEED + Client()->GameTickTime();
+		State.Add(&g_pData->m_aAnimations[ANIM_HAMMER_SWING], clamp(ct*5.0f,0.0f,1.0f), 1.0f);
 	}
-	if (player.weapon == WEAPON_NINJA)
+	if (Player.m_Weapon == WEAPON_NINJA)
 	{
-		float ct = (client_prevtick()-player.attacktick)/(float)SERVER_TICK_SPEED + client_ticktime();
-		state.add(&data->animations[ANIM_NINJA_SWING], clamp(ct*2.0f,0.0f,1.0f), 1.0f);
+		float ct = (Client()->PrevGameTick()-Player.m_AttackTick)/(float)SERVER_TICK_SPEED + Client()->GameTickTime();
+		State.Add(&g_pData->m_aAnimations[ANIM_NINJA_SWING], clamp(ct*2.0f,0.0f,1.0f), 1.0f);
 	}
 	
 	// do skidding
-	if(!inair && want_other_dir && length(vel*50) > 500.0f)
+	if(!InAir && WantOtherDir && length(Vel*50) > 500.0f)
 	{
-		static int64 skid_sound_time = 0;
-		if(time_get()-skid_sound_time > time_freq()/10)
+		static int64 SkidSoundTime = 0;
+		if(time_get()-SkidSoundTime > time_freq()/10)
 		{
-			gameclient.sounds->play(SOUNDS::CHN_WORLD, SOUND_PLAYER_SKID, 0.25f, position);
-			skid_sound_time = time_get();
+			m_pClient->m_pSounds->Play(CSounds::CHN_WORLD, SOUND_PLAYER_SKID, 0.25f, Position);
+			SkidSoundTime = time_get();
 		}
 		
-		gameclient.effects->skidtrail(
-			position+vec2(-player.direction*6,12),
-			vec2(-player.direction*100*length(vel),-50)
+		m_pClient->m_pEffects->SkidTrail(
+			Position+vec2(-Player.m_Direction*6,12),
+			vec2(-Player.m_Direction*100*length(Vel),-50)
 		);
 	}
 
-	// draw hook
-	if (prev.hook_state>0 && player.hook_state>0)
-	{
-		Graphics()->TextureSet(data->images[IMAGE_GAME].id);
-		Graphics()->QuadsBegin();
-		//Graphics()->QuadsBegin();
-
-		vec2 pos = position;
-		vec2 hook_pos;
-		
-		if(player_char->hooked_player != -1)
-		{
-			if(gameclient.snap.local_info && player_char->hooked_player == gameclient.snap.local_info->cid)
-			{
-				hook_pos = mix(vec2(gameclient.predicted_prev_char.pos.x, gameclient.predicted_prev_char.pos.y),
-					vec2(gameclient.predicted_char.pos.x, gameclient.predicted_char.pos.y), client_predintratick());
-			}
-			else
-				hook_pos = mix(vec2(prev_char->hook_x, prev_char->hook_y), vec2(player_char->hook_x, player_char->hook_y), client_intratick());
-		}
-		else
-			hook_pos = mix(vec2(prev.hook_x, prev.hook_y), vec2(player.hook_x, player.hook_y), intratick);
-
-		float d = distance(pos, hook_pos);
-		vec2 dir = normalize(pos-hook_pos);
-
-		Graphics()->QuadsSetRotation(get_angle(dir)+pi);
-
-		// render head
-		RenderTools()->select_sprite(SPRITE_HOOK_HEAD);
-		Graphics()->QuadsDraw(hook_pos.x, hook_pos.y, 24,16);
-
-		// render chain
-		RenderTools()->select_sprite(SPRITE_HOOK_CHAIN);
-		int i = 0;
-		for(float f = 24; f < d && i < 1024; f += 24, i++)
-		{
-			vec2 p = hook_pos + dir*f;
-			Graphics()->QuadsDraw(p.x, p.y,24,16);
-		}
-
-		Graphics()->QuadsSetRotation(0);
-		Graphics()->QuadsEnd();
-
-		render_hand(&render_info, position, normalize(hook_pos-pos), -pi/2, vec2(20, 0));
-	}
-
 	// draw gun
 	{
-		Graphics()->TextureSet(data->images[IMAGE_GAME].id);
+		Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
 		Graphics()->QuadsBegin();
-		Graphics()->QuadsSetRotation(state.attach.angle*pi*2+angle);
+		Graphics()->QuadsSetRotation(State.GetAttach()->m_Angle*pi*2+Angle);
 
 		// normal weapons
-		int iw = clamp(player.weapon, 0, NUM_WEAPONS-1);
-		RenderTools()->select_sprite(data->weapons.id[iw].sprite_body, direction.x < 0 ? SPRITE_FLAG_FLIP_Y : 0);
+		int iw = clamp(Player.m_Weapon, 0, NUM_WEAPONS-1);
+		RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[iw].m_pSpriteBody, Direction.x < 0 ? SPRITE_FLAG_FLIP_Y : 0);
 
-		vec2 dir = direction;
-		float recoil = 0.0f;
+		vec2 Dir = Direction;
+		float Recoil = 0.0f;
 		vec2 p;
-		if (player.weapon == WEAPON_HAMMER)
+		if (Player.m_Weapon == WEAPON_HAMMER)
 		{
 			// Static position for hammer
-			p = position + vec2(state.attach.x, state.attach.y);
-			p.y += data->weapons.id[iw].offsety;
+			p = Position + vec2(State.GetAttach()->m_X, State.GetAttach()->m_Y);
+			p.y += g_pData->m_Weapons.m_aId[iw].m_Offsety;
 			// if attack is under way, bash stuffs
-			if(direction.x < 0)
+			if(Direction.x < 0)
 			{
-				Graphics()->QuadsSetRotation(-pi/2-state.attach.angle*pi*2);
-				p.x -= data->weapons.id[iw].offsetx;
+				Graphics()->QuadsSetRotation(-pi/2-State.GetAttach()->m_Angle*pi*2);
+				p.x -= g_pData->m_Weapons.m_aId[iw].m_Offsetx;
 			}
 			else
 			{
-				Graphics()->QuadsSetRotation(-pi/2+state.attach.angle*pi*2);
+				Graphics()->QuadsSetRotation(-pi/2+State.GetAttach()->m_Angle*pi*2);
 			}
-			RenderTools()->draw_sprite(p.x, p.y, data->weapons.id[iw].visual_size);
+			RenderTools()->DrawSprite(p.x, p.y, g_pData->m_Weapons.m_aId[iw].m_VisualSize);
 		}
-		else if (player.weapon == WEAPON_NINJA)
+		else if (Player.m_Weapon == WEAPON_NINJA)
 		{
-			p = position;
-			p.y += data->weapons.id[iw].offsety;
+			p = Position;
+			p.y += g_pData->m_Weapons.m_aId[iw].m_Offsety;
 
-			if(direction.x < 0)
+			if(Direction.x < 0)
 			{
-				Graphics()->QuadsSetRotation(-pi/2-state.attach.angle*pi*2);
-				p.x -= data->weapons.id[iw].offsetx;
-				gameclient.effects->powerupshine(p+vec2(32,0), vec2(32,12));
+				Graphics()->QuadsSetRotation(-pi/2-State.GetAttach()->m_Angle*pi*2);
+				p.x -= g_pData->m_Weapons.m_aId[iw].m_Offsetx;
+				m_pClient->m_pEffects->PowerupShine(p+vec2(32,0), vec2(32,12));
 			}
 			else
 			{
-				Graphics()->QuadsSetRotation(-pi/2+state.attach.angle*pi*2);
-				gameclient.effects->powerupshine(p-vec2(32,0), vec2(32,12));
+				Graphics()->QuadsSetRotation(-pi/2+State.GetAttach()->m_Angle*pi*2);
+				m_pClient->m_pEffects->PowerupShine(p-vec2(32,0), vec2(32,12));
 			}
-			RenderTools()->draw_sprite(p.x, p.y, data->weapons.id[iw].visual_size);
+			RenderTools()->DrawSprite(p.x, p.y, g_pData->m_Weapons.m_aId[iw].m_VisualSize);
 
 			// HADOKEN
-			if ((client_tick()-player.attacktick) <= (SERVER_TICK_SPEED / 6) && data->weapons.id[iw].num_sprite_muzzles)
+			if ((Client()->GameTick()-Player.m_AttackTick) <= (SERVER_TICK_SPEED / 6) && g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles)
 			{
-				int itex = rand() % data->weapons.id[iw].num_sprite_muzzles;
-				float alpha = 1.0f;
-				if (alpha > 0.0f && data->weapons.id[iw].sprite_muzzles[itex])
+				int IteX = rand() % g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles;
+				float Alpha = 1.0f;
+				if (Alpha > 0.0f && g_pData->m_Weapons.m_aId[iw].m_aSpriteMuzzles[IteX])
 				{
-					vec2 dir = vec2(player_char->x,player_char->y) - vec2(prev_char->x, prev_char->y);
-					dir = normalize(dir);
-					float hadokenangle = get_angle(dir);
-					Graphics()->QuadsSetRotation(hadokenangle);
+					vec2 Dir = vec2(pPlayerChar->m_X,pPlayerChar->m_Y) - vec2(pPrevChar->m_X, pPrevChar->m_Y);
+					Dir = normalize(Dir);
+					float HadOkenAngle  = GetAngle(Dir);
+					Graphics()->QuadsSetRotation(HadOkenAngle );
 					//float offsety = -data->weapons[iw].muzzleoffsety;
-					RenderTools()->select_sprite(data->weapons.id[iw].sprite_muzzles[itex], 0);
-					vec2 diry(-dir.y,dir.x);
-					p = position;
-					float offsetx = data->weapons.id[iw].muzzleoffsetx;
-					p -= dir * offsetx;
-					RenderTools()->draw_sprite(p.x, p.y, 160.0f);
+					RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[iw].m_aSpriteMuzzles[IteX], 0);
+					vec2 DirY(-Dir.y,Dir.x);
+					p = Position;
+					float OffsetX = g_pData->m_Weapons.m_aId[iw].m_Muzzleoffsetx;
+					p -= Dir * OffsetX;
+					RenderTools()->DrawSprite(p.x, p.y, 160.0f);
 				}
 			}
 		}
 		else
 		{
 			// TODO: should be an animation
-			recoil = 0;
-			float a = (client_tick()-player.attacktick+intratick)/5.0f;
+			Recoil = 0;
+			float a = (Client()->GameTick()-Player.m_AttackTick+IntraTick)/5.0f;
 			if(a < 1)
-				recoil = sinf(a*pi);
-			p = position + dir * data->weapons.id[iw].offsetx - dir*recoil*10.0f;
-			p.y += data->weapons.id[iw].offsety;
-			RenderTools()->draw_sprite(p.x, p.y, data->weapons.id[iw].visual_size);
+				Recoil = sinf(a*pi);
+			p = Position + Dir * g_pData->m_Weapons.m_aId[iw].m_Offsetx - Dir*Recoil*10.0f;
+			p.y += g_pData->m_Weapons.m_aId[iw].m_Offsety;
+			RenderTools()->DrawSprite(p.x, p.y, g_pData->m_Weapons.m_aId[iw].m_VisualSize);
 		}
 
-		if (player.weapon == WEAPON_GUN || player.weapon == WEAPON_SHOTGUN)
+		if (Player.m_Weapon == WEAPON_GUN || Player.m_Weapon == WEAPON_SHOTGUN)
 		{
 			// check if we're firing stuff
-			if(data->weapons.id[iw].num_sprite_muzzles)//prev.attackticks)
+			if(g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles)//prev.attackticks)
 			{
-				float alpha = 0.0f;
-				int phase1tick = (client_tick() - player.attacktick);
-				if (phase1tick < (data->weapons.id[iw].muzzleduration + 3))
+				float Alpha = 0.0f;
+				int Phase1Tick = (Client()->GameTick() - Player.m_AttackTick);
+				if (Phase1Tick < (g_pData->m_Weapons.m_aId[iw].m_Muzzleduration + 3))
 				{
-					float t = ((((float)phase1tick) + intratick)/(float)data->weapons.id[iw].muzzleduration);
-					alpha = LERP(2.0, 0.0f, min(1.0f,max(0.0f,t)));
+					float t = ((((float)Phase1Tick) + IntraTick)/(float)g_pData->m_Weapons.m_aId[iw].m_Muzzleduration);
+					Alpha = mix(2.0f, 0.0f, min(1.0f,max(0.0f,t)));
 				}
 
-				int itex = rand() % data->weapons.id[iw].num_sprite_muzzles;
-				if (alpha > 0.0f && data->weapons.id[iw].sprite_muzzles[itex])
+				int IteX = rand() % g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles;
+				if (Alpha > 0.0f && g_pData->m_Weapons.m_aId[iw].m_aSpriteMuzzles[IteX])
 				{
-					float offsety = -data->weapons.id[iw].muzzleoffsety;
-					RenderTools()->select_sprite(data->weapons.id[iw].sprite_muzzles[itex], direction.x < 0 ? SPRITE_FLAG_FLIP_Y : 0);
-					if(direction.x < 0)
-						offsety = -offsety;
+					float OffsetY = -g_pData->m_Weapons.m_aId[iw].m_Muzzleoffsety;
+					RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[iw].m_aSpriteMuzzles[IteX], Direction.x < 0 ? SPRITE_FLAG_FLIP_Y : 0);
+					if(Direction.x < 0)
+						OffsetY = -OffsetY;
 
-					vec2 diry(-dir.y,dir.x);
-					vec2 muzzlepos = p + dir * data->weapons.id[iw].muzzleoffsetx + diry * offsety;
+					vec2 DirY(-Dir.y,Dir.x);
+					vec2 MuzzlePos = p + Dir * g_pData->m_Weapons.m_aId[iw].m_Muzzleoffsetx + DirY * OffsetY;
 
-					RenderTools()->draw_sprite(muzzlepos.x, muzzlepos.y, data->weapons.id[iw].visual_size);
+					RenderTools()->DrawSprite(MuzzlePos.x, MuzzlePos.y, g_pData->m_Weapons.m_aId[iw].m_VisualSize);
 				}
 			}
 		}
 		Graphics()->QuadsEnd();
 
-		switch (player.weapon)
+		switch (Player.m_Weapon)
 		{
-			case WEAPON_GUN: render_hand(&render_info, p, direction, -3*pi/4, vec2(-15, 4)); break;
-			case WEAPON_SHOTGUN: render_hand(&render_info, p, direction, -pi/2, vec2(-5, 4)); break;
-			case WEAPON_GRENADE: render_hand(&render_info, p, direction, -pi/2, vec2(-4, 7)); break;
+			case WEAPON_GUN: RenderHand(&RenderInfo, p, Direction, -3*pi/4, vec2(-15, 4)); break;
+			case WEAPON_SHOTGUN: RenderHand(&RenderInfo, p, Direction, -pi/2, vec2(-5, 4)); break;
+			case WEAPON_GRENADE: RenderHand(&RenderInfo, p, Direction, -pi/2, vec2(-4, 7)); break;
 		}
 
 	}
 
 	// render the "shadow" tee
-	if(info.local && config.debug)
+	if(pInfo.m_Local && g_Config.m_Debug)
 	{
-		vec2 ghost_position = mix(vec2(prev_char->x, prev_char->y), vec2(player_char->x, player_char->y), client_intratick());
-		TEE_RENDER_INFO ghost = render_info;
-		ghost.color_body.a = 0.5f;
-		ghost.color_feet.a = 0.5f;
-		RenderTools()->RenderTee(&state, &ghost, player.emote, direction, ghost_position); // render ghost
+		vec2 GhostPosition = mix(vec2(pPrevChar->m_X, pPrevChar->m_Y), vec2(pPlayerChar->m_X, pPlayerChar->m_Y), Client()->IntraGameTick());
+		CTeeRenderInfo Ghost = RenderInfo;
+		Ghost.m_ColorBody.a = 0.5f;
+		Ghost.m_ColorFeet.a = 0.5f;
+		RenderTools()->RenderTee(&State, &Ghost, Player.m_Emote, Direction, GhostPosition); // render ghost
 	}
 
-	render_info.size = 64.0f; // force some settings
-	render_info.color_body.a = 1.0f;
-	render_info.color_feet.a = 1.0f;
-	RenderTools()->RenderTee(&state, &render_info, player.emote, direction, position);
+	RenderInfo.m_Size = 64.0f; // force some settings
+	RenderInfo.m_ColorBody.a = 1.0f;
+	RenderInfo.m_ColorFeet.a = 1.0f;
+	RenderTools()->RenderTee(&State, &RenderInfo, Player.m_Emote, Direction, Position);
 
-	if(player.player_state == PLAYERSTATE_CHATTING)
+	if(Player.m_PlayerState == PLAYERSTATE_CHATTING)
 	{
-		Graphics()->TextureSet(data->images[IMAGE_EMOTICONS].id);
+		Graphics()->TextureSet(g_pData->m_aImages[IMAGE_EMOTICONS].m_Id);
 		Graphics()->QuadsBegin();
-		RenderTools()->select_sprite(SPRITE_DOTDOT);
-		Graphics()->QuadsDraw(position.x + 24, position.y - 40, 64,64);
+		RenderTools()->SelectSprite(SPRITE_DOTDOT);
+		IGraphics::CQuadItem QuadItem(Position.x + 24, Position.y - 40, 64,64);
+		Graphics()->QuadsDraw(&QuadItem, 1);
 		Graphics()->QuadsEnd();
 	}
 
-	if (gameclient.clients[info.cid].emoticon_start != -1 && gameclient.clients[info.cid].emoticon_start + 2 * client_tickspeed() > client_tick())
+	if (m_pClient->m_aClients[pInfo.m_ClientId].m_EmoticonStart != -1 && m_pClient->m_aClients[pInfo.m_ClientId].m_EmoticonStart + 2 * Client()->GameTickSpeed() > Client()->GameTick())
 	{
-		Graphics()->TextureSet(data->images[IMAGE_EMOTICONS].id);
+		Graphics()->TextureSet(g_pData->m_aImages[IMAGE_EMOTICONS].m_Id);
 		Graphics()->QuadsBegin();
 
-		int since_start = client_tick() - gameclient.clients[info.cid].emoticon_start;
-		int from_end = gameclient.clients[info.cid].emoticon_start + 2 * client_tickspeed() - client_tick();
+		int SinceStart = Client()->GameTick() - m_pClient->m_aClients[pInfo.m_ClientId].m_EmoticonStart;
+		int FromEnd = m_pClient->m_aClients[pInfo.m_ClientId].m_EmoticonStart + 2 * Client()->GameTickSpeed() - Client()->GameTick();
 
 		float a = 1;
 
-		if (from_end < client_tickspeed() / 5)
-			a = from_end / (client_tickspeed() / 5.0);
+		if (FromEnd < Client()->GameTickSpeed() / 5)
+			a = FromEnd / (Client()->GameTickSpeed() / 5.0);
 
 		float h = 1;
-		if (since_start < client_tickspeed() / 10)
-			h = since_start / (client_tickspeed() / 10.0);
+		if (SinceStart < Client()->GameTickSpeed() / 10)
+			h = SinceStart / (Client()->GameTickSpeed() / 10.0);
 
-		float wiggle = 0;
-		if (since_start < client_tickspeed() / 5)
-			wiggle = since_start / (client_tickspeed() / 5.0);
+		float Wiggle = 0;
+		if (SinceStart < Client()->GameTickSpeed() / 5)
+			Wiggle = SinceStart / (Client()->GameTickSpeed() / 5.0);
 
-		float wiggle_angle = sin(5*wiggle);
+		float WiggleAngle = sinf(5*Wiggle);
 
-		Graphics()->QuadsSetRotation(pi/6*wiggle_angle);
+		Graphics()->QuadsSetRotation(pi/6*WiggleAngle);
 
 		Graphics()->SetColor(1.0f,1.0f,1.0f,a);
 		// client_datas::emoticon is an offset from the first emoticon
-		RenderTools()->select_sprite(SPRITE_OOP + gameclient.clients[info.cid].emoticon);
-		Graphics()->QuadsDraw(position.x, position.y - 23 - 32*h, 64, 64*h);
+		RenderTools()->SelectSprite(SPRITE_OOP + m_pClient->m_aClients[pInfo.m_ClientId].m_Emoticon);
+		IGraphics::CQuadItem QuadItem(Position.x, Position.y - 23 - 32*h, 64, 64*h);
+		Graphics()->QuadsDraw(&QuadItem, 1);
 		Graphics()->QuadsEnd();
 	}
 }
 
-void PLAYERS::on_render()
+void CPlayers::OnRender()
 {
 	// render other players in two passes, first pass we render the other, second pass we render our self
-	for(int p = 0; p < 2; p++)
+	for(int p = 0; p < 4; p++)
 	{
 		for(int i = 0; i < MAX_CLIENTS; i++)
 		{
 			// only render active characters
-			if(!gameclient.snap.characters[i].active)
+			if(!m_pClient->m_Snap.m_aCharacters[i].m_Active)
 				continue;
 
-			const void *prev_info = snap_find_item(SNAP_PREV, NETOBJTYPE_PLAYER_INFO, i);
-			const void *info = snap_find_item(SNAP_CURRENT, NETOBJTYPE_PLAYER_INFO, i);
+			const void *pPrevInfo = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_PLAYERINFO, i);
+			const void *pInfo = Client()->SnapFindItem(IClient::SNAP_CURRENT, NETOBJTYPE_PLAYERINFO, i);
 
-			if(prev_info && info)
+			if(pPrevInfo && pInfo)
 			{
 				//
-				bool local = ((const NETOBJ_PLAYER_INFO *)info)->local !=0;
-				if(p == 0 && local) continue;
-				if(p == 1 && !local) continue;
+				bool Local = ((const CNetObj_PlayerInfo *)pInfo)->m_Local !=0;
+				if((p % 2) == 0 && Local) continue;
+				if((p % 2) == 1 && !Local) continue;
 				
-				NETOBJ_CHARACTER prev_char = gameclient.snap.characters[i].prev;
-				NETOBJ_CHARACTER cur_char = gameclient.snap.characters[i].cur;
-
-				render_player(
-						&prev_char,
-						&cur_char,
-						(const NETOBJ_PLAYER_INFO *)prev_info,
-						(const NETOBJ_PLAYER_INFO *)info
-					);
+				CNetObj_Character PrevChar = m_pClient->m_Snap.m_aCharacters[i].m_Prev;
+				CNetObj_Character CurChar = m_pClient->m_Snap.m_aCharacters[i].m_Cur;
+
+				if(p<2)
+					RenderHook(
+							&PrevChar,
+							&CurChar,
+							(const CNetObj_PlayerInfo *)pPrevInfo,
+							(const CNetObj_PlayerInfo *)pInfo
+						);
+				else
+					RenderPlayer(
+							&PrevChar,
+							&CurChar,
+							(const CNetObj_PlayerInfo *)pPrevInfo,
+							(const CNetObj_PlayerInfo *)pInfo
+						);
 			}		
 		}
 	}
diff --git a/src/game/client/components/players.h b/src/game/client/components/players.h
new file mode 100644
index 00000000..57501380
--- /dev/null
+++ b/src/game/client/components/players.h
@@ -0,0 +1,25 @@
+#ifndef GAME_CLIENT_COMPONENTS_PLAYERS_H
+#define GAME_CLIENT_COMPONENTS_PLAYERS_H
+#include <game/client/component.h>
+
+class CPlayers : public CComponent
+{	
+	void RenderHand(class CTeeRenderInfo *pInfo, vec2 CenterPos, vec2 Dir, float AngleOffset, vec2 PostRotOffset);
+	void RenderPlayer(
+		const class CNetObj_Character *pPrevChar,
+		const class CNetObj_Character *pPlayerChar,
+		const class CNetObj_PlayerInfo *pPrevInfo,
+		const class CNetObj_PlayerInfo *pPlayerInfo
+	);	
+	void RenderHook(
+		const CNetObj_Character *pPrevChar,
+		const CNetObj_Character *pPlayerChar,
+		const CNetObj_PlayerInfo *pPrevInfo,
+		const CNetObj_PlayerInfo *pPlayerInfo
+	);
+	
+public:
+	virtual void OnRender();
+};
+
+#endif
diff --git a/src/game/client/components/players.hpp b/src/game/client/components/players.hpp
deleted file mode 100644
index bdce91de..00000000
--- a/src/game/client/components/players.hpp
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <game/client/component.hpp>
-
-class PLAYERS : public COMPONENT
-{	
-	void render_hand(class TEE_RENDER_INFO *info, vec2 center_pos, vec2 dir, float angle_offset, vec2 post_rot_offset);
-	void render_player(
-		const class NETOBJ_CHARACTER *prev_char,
-		const class NETOBJ_CHARACTER *player_char,
-		const class NETOBJ_PLAYER_INFO *prev_info,
-		const class NETOBJ_PLAYER_INFO *player_info
-	);	
-	
-public:
-	virtual void on_render();
-};
-
diff --git a/src/game/client/components/scoreboard.cpp b/src/game/client/components/scoreboard.cpp
index e8db1aed..b7e8aa9a 100644
--- a/src/game/client/components/scoreboard.cpp
+++ b/src/game/client/components/scoreboard.cpp
@@ -1,36 +1,37 @@
-#include <string.h>
-#include <engine/e_client_interface.h>
-#include <engine/client/graphics.h>
-#include <game/generated/g_protocol.hpp>
-#include <game/generated/gc_data.hpp>
-#include <game/client/gameclient.hpp>
-#include <game/client/animstate.hpp>
-#include <game/client/render.hpp>
-#include <game/client/components/motd.hpp>
-#include "scoreboard.hpp"
-
-
-SCOREBOARD::SCOREBOARD()
+#include <engine/graphics.h>
+#include <engine/textrender.h>
+#include <engine/shared/config.h>
+#include <game/generated/protocol.h>
+#include <game/generated/client_data.h>
+#include <game/client/gameclient.h>
+#include <game/client/animstate.h>
+#include <game/client/render.h>
+#include <game/client/components/motd.h>
+#include <game/localization.h>
+#include "scoreboard.h"
+
+
+CScoreboard::CScoreboard()
 {
-	on_reset();
+	OnReset();
 }
 
-void SCOREBOARD::con_key_scoreboard(void *result, void *user_data)
+void CScoreboard::ConKeyScoreboard(IConsole::IResult *pResult, void *pUserData)
 {
-	((SCOREBOARD *)user_data)->active = console_arg_int(result, 0) != 0;
+	((CScoreboard *)pUserData)->m_Active = pResult->GetInteger(0) != 0;
 }
 
-void SCOREBOARD::on_reset()
+void CScoreboard::OnReset()
 {
-	active = false;
+	m_Active = false;
 }
 
-void SCOREBOARD::on_console_init()
+void CScoreboard::OnConsoleInit()
 {
-	MACRO_REGISTER_COMMAND("+scoreboard", "", CFGFLAG_CLIENT, con_key_scoreboard, this, "Show scoreboard");
+	Console()->Register("+scoreboard", "", CFGFLAG_CLIENT, ConKeyScoreboard, this, "Show scoreboard");
 }
 
-void SCOREBOARD::render_goals(float x, float y, float w)
+void CScoreboard::RenderGoals(float x, float y, float w)
 {
 	float h = 50.0f;
 
@@ -38,74 +39,77 @@ void SCOREBOARD::render_goals(float x, float y, float w)
 	Graphics()->TextureSet(-1);
 	Graphics()->QuadsBegin();
 	Graphics()->SetColor(0,0,0,0.5f);
-	RenderTools()->draw_round_rect(x-10.f, y-10.f, w, h, 10.0f);
+	RenderTools()->DrawRoundRect(x-10.f, y-10.f, w, h, 10.0f);
 	Graphics()->QuadsEnd();
 
 	// render goals
 	//y = ystart+h-54;
 	float tw = 0.0f;
-	if(gameclient.snap.gameobj && gameclient.snap.gameobj->score_limit)
+	if(m_pClient->m_Snap.m_pGameobj)
 	{
-		char buf[64];
-		str_format(buf, sizeof(buf), "%s: %d", localize("Score limit"), gameclient.snap.gameobj->score_limit);
-		gfx_text(0, x+20.0f, y, 22.0f, buf, -1);
-		tw += gfx_text_width(0, 22.0f, buf, -1);
-	}
-	if(gameclient.snap.gameobj && gameclient.snap.gameobj->time_limit)
-	{
-		char buf[64];
-		str_format(buf, sizeof(buf), "%s: %d min", localize("Time limit"), gameclient.snap.gameobj->time_limit);
-		gfx_text(0, x+220.0f, y, 22.0f, buf, -1);
-		tw += gfx_text_width(0, 22.0f, buf, -1);
-	}
-	if(gameclient.snap.gameobj && gameclient.snap.gameobj->round_num && gameclient.snap.gameobj->round_current)
-	{
-		char buf[64];
-		str_format(buf, sizeof(buf), "%s %d/%d", localize("Round"), gameclient.snap.gameobj->round_current, gameclient.snap.gameobj->round_num);
-		gfx_text(0, x+450.0f, y, 22.0f, buf, -1);
-		
-	/*[48c3fd4c][game/scoreboard]: timelimit x:219.428558
-	[48c3fd4c][game/scoreboard]: round x:453.142822*/
+		if(m_pClient->m_Snap.m_pGameobj->m_ScoreLimit)
+		{
+			char aBuf[64];
+			str_format(aBuf, sizeof(aBuf), "%s: %d", Localize("Score limit"), m_pClient->m_Snap.m_pGameobj->m_ScoreLimit);
+			TextRender()->Text(0, x+20.0f, y, 22.0f, aBuf, -1);
+			tw += TextRender()->TextWidth(0, 22.0f, aBuf, -1);
+		}
+		if(m_pClient->m_Snap.m_pGameobj->m_TimeLimit)
+		{
+			char aBuf[64];
+			str_format(aBuf, sizeof(aBuf), "%s: %d min", Localize("Time limit"), m_pClient->m_Snap.m_pGameobj->m_TimeLimit);
+			TextRender()->Text(0, x+220.0f, y, 22.0f, aBuf, -1);
+			tw += TextRender()->TextWidth(0, 22.0f, aBuf, -1);
+		}
+		if(m_pClient->m_Snap.m_pGameobj->m_RoundNum && m_pClient->m_Snap.m_pGameobj->m_RoundCurrent)
+		{
+			char aBuf[64];
+			str_format(aBuf, sizeof(aBuf), "%s %d/%d", Localize("Round"), m_pClient->m_Snap.m_pGameobj->m_RoundCurrent, m_pClient->m_Snap.m_pGameobj->m_RoundNum);
+			TextRender()->Text(0, x+450.0f, y, 22.0f, aBuf, -1);
+			
+		/*[48c3fd4c][game/scoreboard]: timelimit x:219.428558
+		[48c3fd4c][game/scoreboard]: round x:453.142822*/
+		}
 	}
 }
 
-void SCOREBOARD::render_spectators(float x, float y, float w)
+void CScoreboard::RenderSpectators(float x, float y, float w)
 {
-	char buffer[1024*4];
-	int count = 0;
+	char aBuffer[1024*4];
+	int Count = 0;
 	float h = 120.0f;
 	
-	str_format(buffer, sizeof(buffer), "%s: ", localize("Spectators"));
+	str_format(aBuffer, sizeof(aBuffer), "%s: ", Localize("Spectators"));
 
 	Graphics()->BlendNormal();
 	Graphics()->TextureSet(-1);
 	Graphics()->QuadsBegin();
 	Graphics()->SetColor(0,0,0,0.5f);
-	RenderTools()->draw_round_rect(x-10.f, y-10.f, w, h, 10.0f);
+	RenderTools()->DrawRoundRect(x-10.f, y-10.f, w, h, 10.0f);
 	Graphics()->QuadsEnd();
 	
-	for(int i = 0; i < snap_num_items(SNAP_CURRENT); i++)
+	for(int i = 0; i < Client()->SnapNumItems(IClient::SNAP_CURRENT); i++)
 	{
-		SNAP_ITEM item;
-		const void *data = snap_get_item(SNAP_CURRENT, i, &item);
+		IClient::CSnapItem Item;
+		const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item);
 
-		if(item.type == NETOBJTYPE_PLAYER_INFO)
+		if(Item.m_Type == NETOBJTYPE_PLAYERINFO)
 		{
-			const NETOBJ_PLAYER_INFO *info = (const NETOBJ_PLAYER_INFO *)data;
-			if(info->team == -1)
+			const CNetObj_PlayerInfo *pInfo = (const CNetObj_PlayerInfo *)pData;
+			if(pInfo->m_Team == -1)
 			{
-				if(count)
-					strcat(buffer, ", ");
-				strcat(buffer, gameclient.clients[info->cid].name);
-				count++;
+				if(Count)
+					str_append(aBuffer, ", ", sizeof(aBuffer));
+				str_append(aBuffer, m_pClient->m_aClients[pInfo->m_ClientId].m_aName, sizeof(aBuffer));
+				Count++;
 			}
 		}
 	}
 	
-	gfx_text(0, x+10, y, 32, buffer, (int)w-20);
+	TextRender()->Text(0, x+10, y, 32, aBuffer, (int)w-20);
 }
 
-void SCOREBOARD::render_scoreboard(float x, float y, float w, int team, const char *title)
+void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const char *pTitle)
 {
 	//float ystart = y;
 	float h = 750.0f;
@@ -114,202 +118,203 @@ void SCOREBOARD::render_scoreboard(float x, float y, float w, int team, const ch
 	Graphics()->TextureSet(-1);
 	Graphics()->QuadsBegin();
 	Graphics()->SetColor(0,0,0,0.5f);
-	RenderTools()->draw_round_rect(x-10.f, y-10.f, w, h, 17.0f);
+	RenderTools()->DrawRoundRect(x-10.f, y-10.f, w, h, 17.0f);
 	Graphics()->QuadsEnd();
 
 	// render title
-	if(!title)
+	if(!pTitle)
 	{
-		if(gameclient.snap.gameobj->game_over)
-			title = localize("Game over");
+		if(m_pClient->m_Snap.m_pGameobj->m_GameOver)
+			pTitle = Localize("Game over");
 		else
-			title = localize("Score board");
+			pTitle = Localize("Score board");
 	}
 
-	float tw = gfx_text_width(0, 48, title, -1);
+	float tw = TextRender()->TextWidth(0, 48, pTitle, -1);
 
-	if(team == -1)
+	if(Team == -1)
 	{
-		gfx_text(0, x+w/2-tw/2, y, 48, title, -1);
+		TextRender()->Text(0, x+w/2-tw/2, y, 48, pTitle, -1);
 	}
 	else
 	{
-		gfx_text(0, x+10, y, 48, title, -1);
+		TextRender()->Text(0, x+10, y, 48, pTitle, -1);
 
-		if(gameclient.snap.gameobj)
+		if(m_pClient->m_Snap.m_pGameobj)
 		{
-			char buf[128];
-			int score = team ? gameclient.snap.gameobj->teamscore_blue : gameclient.snap.gameobj->teamscore_red;
-			str_format(buf, sizeof(buf), "%d", score);
-			tw = gfx_text_width(0, 48, buf, -1);
-			gfx_text(0, x+w-tw-30, y, 48, buf, -1);
+			char aBuf[128];
+			int Score = Team ? m_pClient->m_Snap.m_pGameobj->m_TeamscoreBlue : m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed;
+			str_format(aBuf, sizeof(aBuf), "%d", Score);
+			tw = TextRender()->TextWidth(0, 48, aBuf, -1);
+			TextRender()->Text(0, x+w-tw-30, y, 48, aBuf, -1);
 		}
 	}
 
 	y += 54.0f;
 
 	// find players
-	const NETOBJ_PLAYER_INFO *players[MAX_CLIENTS] = {0};
-	int num_players = 0;
-	for(int i = 0; i < snap_num_items(SNAP_CURRENT); i++)
+	const CNetObj_PlayerInfo *paPlayers[MAX_CLIENTS] = {0};
+	int NumPlayers = 0;
+	for(int i = 0; i < Client()->SnapNumItems(IClient::SNAP_CURRENT); i++)
 	{
-		SNAP_ITEM item;
-		const void *data = snap_get_item(SNAP_CURRENT, i, &item);
+		IClient::CSnapItem Item;
+		const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item);
 
-		if(item.type == NETOBJTYPE_PLAYER_INFO)
+		if(Item.m_Type == NETOBJTYPE_PLAYERINFO)
 		{
-			const NETOBJ_PLAYER_INFO *info = (const NETOBJ_PLAYER_INFO *)data;
-			if(info->team == team)
+			const CNetObj_PlayerInfo *pInfo = (const CNetObj_PlayerInfo *)pData;
+			if(pInfo->m_Team == Team)
 			{
-				players[num_players] = info;
-				num_players++;
+				paPlayers[NumPlayers] = pInfo;
+				NumPlayers++;
 			}
 		}
 	}
 
 	// sort players
-	for(int k = 0; k < num_players; k++) // ffs, bubblesort
+	for(int k = 0; k < NumPlayers; k++) // ffs, bubblesort
 	{
-		for(int i = 0; i < num_players-k-1; i++)
+		for(int i = 0; i < NumPlayers-k-1; i++)
 		{
-			if(players[i]->score < players[i+1]->score)
+			if(paPlayers[i]->m_Score < paPlayers[i+1]->m_Score)
 			{
-				const NETOBJ_PLAYER_INFO *tmp = players[i];
-				players[i] = players[i+1];
-				players[i+1] = tmp;
+				const CNetObj_PlayerInfo *pTmp = paPlayers[i];
+				paPlayers[i] = paPlayers[i+1];
+				paPlayers[i+1] = pTmp;
 			}
 		}
 	}
 
 	// render headlines
-	gfx_text(0, x+10, y, 24.0f, localize("Score"), -1);
-	gfx_text(0, x+125, y, 24.0f, localize("Name"), -1);
-	gfx_text(0, x+w-70, y, 24.0f, localize("Ping"), -1);
+	TextRender()->Text(0, x+10, y, 24.0f, Localize("Score"), -1);
+	TextRender()->Text(0, x+125, y, 24.0f, Localize("Name"), -1);
+	TextRender()->Text(0, x+w-70, y, 24.0f, Localize("Ping"), -1);
 	y += 29.0f;
 
-	float font_size = 35.0f;
-	float line_height = 50.0f;
-	float tee_sizemod = 1.0f;
-	float tee_offset = 0.0f;
+	float FontSize = 35.0f;
+	float LineHeight = 50.0f;
+	float TeeSizeMod = 1.0f;
+	float TeeOffset = 0.0f;
 	
-	if(num_players > 13)
+	if(NumPlayers > 13)
 	{
-		font_size = 30.0f;
-		line_height = 40.0f;
-		tee_sizemod = 0.8f;
-		tee_offset = -5.0f;
+		FontSize = 30.0f;
+		LineHeight = 40.0f;
+		TeeSizeMod = 0.8f;
+		TeeOffset = -5.0f;
 	}
 	
 	// render player scores
-	for(int i = 0; i < num_players; i++)
+	for(int i = 0; i < NumPlayers; i++)
 	{
-		const NETOBJ_PLAYER_INFO *info = players[i];
+		const CNetObj_PlayerInfo *pInfo = paPlayers[i];
 
 		// make sure that we render the correct team
 
-		char buf[128];
-		if(info->local)
+		char aBuf[128];
+		if(pInfo->m_Local)
 		{
 			// background so it's easy to find the local player
 			Graphics()->TextureSet(-1);
 			Graphics()->QuadsBegin();
 			Graphics()->SetColor(1,1,1,0.25f);
-			RenderTools()->draw_round_rect(x, y, w-20, line_height*0.95f, 17.0f);
+			RenderTools()->DrawRoundRect(x, y, w-20, LineHeight*0.95f, 17.0f);
 			Graphics()->QuadsEnd();
 		}
 
-		str_format(buf, sizeof(buf), "%4d", info->score);
-		gfx_text(0, x+60-gfx_text_width(0, font_size,buf,-1), y, font_size, buf, -1);
+		str_format(aBuf, sizeof(aBuf), "%4d", pInfo->m_Score);
+		TextRender()->Text(0, x+60-TextRender()->TextWidth(0, FontSize,aBuf,-1), y, FontSize, aBuf, -1);
 		
-		gfx_text(0, x+128, y, font_size, gameclient.clients[info->cid].name, -1);
+		TextRender()->Text(0, x+128, y, FontSize, m_pClient->m_aClients[pInfo->m_ClientId].m_aName, -1);
 
-		str_format(buf, sizeof(buf), "%4d", info->latency);
-		float tw = gfx_text_width(0, font_size, buf, -1);
-		gfx_text(0, x+w-tw-35, y, font_size, buf, -1);
+		str_format(aBuf, sizeof(aBuf), "%4d", pInfo->m_Latency);
+		float tw = TextRender()->TextWidth(0, FontSize, aBuf, -1);
+		TextRender()->Text(0, x+w-tw-35, y, FontSize, aBuf, -1);
 
 		// render avatar
-		if((gameclient.snap.flags[0] && gameclient.snap.flags[0]->carried_by == info->cid) ||
-			(gameclient.snap.flags[1] && gameclient.snap.flags[1]->carried_by == info->cid))
+		if((m_pClient->m_Snap.m_paFlags[0] && m_pClient->m_Snap.m_paFlags[0]->m_CarriedBy == pInfo->m_ClientId) ||
+			(m_pClient->m_Snap.m_paFlags[1] && m_pClient->m_Snap.m_paFlags[1]->m_CarriedBy == pInfo->m_ClientId))
 		{
 			Graphics()->BlendNormal();
-			Graphics()->TextureSet(data->images[IMAGE_GAME].id);
+			Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
 			Graphics()->QuadsBegin();
 
-			if(info->team == 0) RenderTools()->select_sprite(SPRITE_FLAG_BLUE, SPRITE_FLAG_FLIP_X);
-			else RenderTools()->select_sprite(SPRITE_FLAG_RED, SPRITE_FLAG_FLIP_X);
+			if(pInfo->m_Team == 0) RenderTools()->SelectSprite(SPRITE_FLAG_BLUE, SPRITE_FLAG_FLIP_X);
+			else RenderTools()->SelectSprite(SPRITE_FLAG_RED, SPRITE_FLAG_FLIP_X);
 			
 			float size = 64.0f;
-			Graphics()->QuadsDrawTL(x+55, y-15, size/2, size);
+			IGraphics::CQuadItem QuadItem(x+55, y-15, size/2, size);
+			Graphics()->QuadsDrawTL(&QuadItem, 1);
 			Graphics()->QuadsEnd();
 		}
 		
-		TEE_RENDER_INFO teeinfo = gameclient.clients[info->cid].render_info;
-		teeinfo.size *= tee_sizemod;
-		RenderTools()->RenderTee(ANIMSTATE::get_idle(), &teeinfo, EMOTE_NORMAL, vec2(1,0), vec2(x+90, y+28+tee_offset));
+		CTeeRenderInfo TeeInfo = m_pClient->m_aClients[pInfo->m_ClientId].m_RenderInfo;
+		TeeInfo.m_Size *= TeeSizeMod;
+		RenderTools()->RenderTee(CAnimState::GetIdle(), &TeeInfo, EMOTE_NORMAL, vec2(1,0), vec2(x+90, y+28+TeeOffset));
 
 		
-		y += line_height;
+		y += LineHeight;
 	}
 }
 
-void SCOREBOARD::on_render()
+void CScoreboard::OnRender()
 {
-	bool do_scoreboard = false;
+	bool DoScoreBoard = false;
 
 	// if we activly wanna look on the scoreboard	
-	if(active)
-		do_scoreboard = true;
+	if(m_Active)
+		DoScoreBoard = true;
 		
-	if(gameclient.snap.local_info && gameclient.snap.local_info->team != -1)
+	if(m_pClient->m_Snap.m_pLocalInfo && m_pClient->m_Snap.m_pLocalInfo->m_Team != -1)
 	{
 		// we are not a spectator, check if we are ead
-		if(!gameclient.snap.local_character || gameclient.snap.local_character->health < 0)
-			do_scoreboard = true;
+		if(!m_pClient->m_Snap.m_pLocalCharacter || m_pClient->m_Snap.m_pLocalCharacter->m_Health < 0)
+			DoScoreBoard = true;
 	}
 
 	// if we the game is over
-	if(gameclient.snap.gameobj && gameclient.snap.gameobj->game_over)
-		do_scoreboard = true;
+	if(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver)
+		DoScoreBoard = true;
 		
-	if(!do_scoreboard)
+	if(!DoScoreBoard)
 		return;
 		
 	// if the score board is active, then we should clear the motd message aswell
-	if(active)
-		gameclient.motd->clear();
+	if(m_Active)
+		m_pClient->m_pMotd->Clear();
 	
 
-	float width = 400*3.0f*Graphics()->ScreenAspect();
-	float height = 400*3.0f;
+	float Width = 400*3.0f*Graphics()->ScreenAspect();
+	float Height = 400*3.0f;
 	
-	Graphics()->MapScreen(0, 0, width, height);
+	Graphics()->MapScreen(0, 0, Width, Height);
 
 	float w = 650.0f;
 
-	if(gameclient.snap.gameobj && !(gameclient.snap.gameobj->flags&GAMEFLAG_TEAMS))
+	if(m_pClient->m_Snap.m_pGameobj && !(m_pClient->m_Snap.m_pGameobj->m_Flags&GAMEFLAG_TEAMS))
 	{
-		render_scoreboard(width/2-w/2, 150.0f, w, 0, 0);
+		RenderScoreboard(Width/2-w/2, 150.0f, w, 0, 0);
 		//render_scoreboard(gameobj, 0, 0, -1, 0);
 	}
 	else
 	{
 			
-		if(gameclient.snap.gameobj && gameclient.snap.gameobj->game_over)
+		if(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver)
 		{
-			const char *text = localize("Draw!");
-			if(gameclient.snap.gameobj->teamscore_red > gameclient.snap.gameobj->teamscore_blue)
-				text = localize("Red team wins!");
-			else if(gameclient.snap.gameobj->teamscore_blue > gameclient.snap.gameobj->teamscore_red)
-				text = localize("Blue team wins!");
+			const char *pText = Localize("Draw!");
+			if(m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed > m_pClient->m_Snap.m_pGameobj->m_TeamscoreBlue)
+				pText = Localize("Red team wins!");
+			else if(m_pClient->m_Snap.m_pGameobj->m_TeamscoreBlue > m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed)
+				pText = Localize("Blue team wins!");
 				
-			float w = gfx_text_width(0, 92.0f, text, -1);
-			gfx_text(0, width/2-w/2, 45, 92.0f, text, -1);
+			float w = TextRender()->TextWidth(0, 92.0f, pText, -1);
+			TextRender()->Text(0, Width/2-w/2, 45, 92.0f, pText, -1);
 		}
 		
-		render_scoreboard(width/2-w-20, 150.0f, w, 0, localize("Red team"));
-		render_scoreboard(width/2 + 20, 150.0f, w, 1, localize("Blue team"));
+		RenderScoreboard(Width/2-w-20, 150.0f, w, 0, Localize("Red team"));
+		RenderScoreboard(Width/2 + 20, 150.0f, w, 1, Localize("Blue team"));
 	}
 
-	render_goals(width/2-w/2, 150+750+25, w);
-	render_spectators(width/2-w/2, 150+750+25+50+25, w);
+	RenderGoals(Width/2-w/2, 150+750+25, w);
+	RenderSpectators(Width/2-w/2, 150+750+25+50+25, w);
 }
diff --git a/src/game/client/components/scoreboard.h b/src/game/client/components/scoreboard.h
new file mode 100644
index 00000000..5aa2f0a7
--- /dev/null
+++ b/src/game/client/components/scoreboard.h
@@ -0,0 +1,22 @@
+#ifndef GAME_CLIENT_COMPONENTS_SCOREBOARD_H
+#define GAME_CLIENT_COMPONENTS_SCOREBOARD_H
+#include <game/client/component.h>
+
+class CScoreboard : public CComponent
+{
+	void RenderGoals(float x, float y, float w);
+	void RenderSpectators(float x, float y, float w);
+	void RenderScoreboard(float x, float y, float w, int Team, const char *pTitle);
+
+	static void ConKeyScoreboard(IConsole::IResult *pResult, void *pUserData);
+	
+	bool m_Active;
+	
+public:
+	CScoreboard();
+	virtual void OnReset();
+	virtual void OnConsoleInit();
+	virtual void OnRender();
+};
+
+#endif
diff --git a/src/game/client/components/scoreboard.hpp b/src/game/client/components/scoreboard.hpp
deleted file mode 100644
index 222dab9d..00000000
--- a/src/game/client/components/scoreboard.hpp
+++ /dev/null
@@ -1,19 +0,0 @@
-#include <game/client/component.hpp>
-
-class SCOREBOARD : public COMPONENT
-{
-	void render_goals(float x, float y, float w);
-	void render_spectators(float x, float y, float w);
-	void render_scoreboard(float x, float y, float w, int team, const char *title);
-
-	static void con_key_scoreboard(void *result, void *user_data);
-	
-	bool active;
-	
-public:
-	SCOREBOARD();
-	virtual void on_reset();
-	virtual void on_console_init();
-	virtual void on_render();
-};
-
diff --git a/src/game/client/components/skins.cpp b/src/game/client/components/skins.cpp
index ad3607a1..582adb10 100644
--- a/src/game/client/components/skins.cpp
+++ b/src/game/client/components/skins.cpp
@@ -1,153 +1,150 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <string.h>
-#include <stdio.h>
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
 #include <math.h>
 
 #include <base/system.h>
-#include <base/math.hpp>
+#include <base/math.h>
 
-#include <engine/client/graphics.h>
-#include <engine/e_client_interface.h>
+#include <engine/graphics.h>
+#include <engine/storage.h>
+#include <engine/shared/engine.h>
 
-#include <engine/e_engine.h>
+#include "skins.h"
 
-#include "skins.hpp"
-
-SKINS::SKINS()
+CSkins::CSkins()
 {
-	num_skins = 0;
+	m_NumSkins = 0;
 }
 
-void SKINS::skinscan(const char *name, int is_dir, void *user)
+void CSkins::SkinScan(const char *pName, int IsDir, void *pUser)
 {
-	SKINS *self = (SKINS *)user;
-	int l = strlen(name);
-	if(l < 4 || is_dir || self->num_skins == MAX_SKINS)
+	CSkins *pSelf = (CSkins *)pUser;
+	int l = str_length(pName);
+	if(l < 4 || IsDir || pSelf->m_NumSkins == MAX_SKINS)
 		return;
-	if(strcmp(name+l-4, ".png") != 0)
+	if(str_comp(pName+l-4, ".png") != 0)
 		return;
 		
-	char buf[512];
-	str_format(buf, sizeof(buf), "skins/%s", name);
-	IMAGE_INFO info;
-	if(!self->Graphics()->LoadPNG(&info, buf))
+	char aBuf[512];
+	str_format(aBuf, sizeof(aBuf), "skins/%s", pName);
+	CImageInfo Info;
+	if(!pSelf->Graphics()->LoadPNG(&Info, aBuf))
 	{
-		dbg_msg("game", "failed to load skin from %s", name);
+		dbg_msg("game", "failed to load skin from %s", pName);
 		return;
 	}
 	
-	self->skins[self->num_skins].org_texture = self->Graphics()->LoadTextureRaw(info.width, info.height, info.format, info.data, info.format, 0);
+	pSelf->m_aSkins[pSelf->m_NumSkins].m_OrgTexture = pSelf->Graphics()->LoadTextureRaw(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, Info.m_Format, 0);
 	
-	int body_size = 96; // body size
-	unsigned char *d = (unsigned char *)info.data;
-	int pitch = info.width*4;
+	int BodySize = 96; // body size
+	unsigned char *d = (unsigned char *)Info.m_pData;
+	int Pitch = Info.m_Width*4;
 
 	// dig out blood color
 	{
-		int colors[3] = {0};
-		for(int y = 0; y < body_size; y++)
-			for(int x = 0; x < body_size; x++)
+		int aColors[3] = {0};
+		for(int y = 0; y < BodySize; y++)
+			for(int x = 0; x < BodySize; x++)
 			{
-				if(d[y*pitch+x*4+3] > 128)
+				if(d[y*Pitch+x*4+3] > 128)
 				{
-					colors[0] += d[y*pitch+x*4+0];
-					colors[1] += d[y*pitch+x*4+1];
-					colors[2] += d[y*pitch+x*4+2];
+					aColors[0] += d[y*Pitch+x*4+0];
+					aColors[1] += d[y*Pitch+x*4+1];
+					aColors[2] += d[y*Pitch+x*4+2];
 				}
 			}
 			
-		self->skins[self->num_skins].blood_color = normalize(vec3(colors[0], colors[1], colors[2]));
+		pSelf->m_aSkins[pSelf->m_NumSkins].m_BloodColor = normalize(vec3(aColors[0], aColors[1], aColors[2]));
 	}
 	
 	// create colorless version
-	int step = info.format == IMG_RGBA ? 4 : 3;
+	int Step = Info.m_Format == CImageInfo::FORMAT_RGBA ? 4 : 3;
 
 	// make the texture gray scale
-	for(int i = 0; i < info.width*info.height; i++)
+	for(int i = 0; i < Info.m_Width*Info.m_Height; i++)
 	{
-		int v = (d[i*step]+d[i*step+1]+d[i*step+2])/3;
-		d[i*step] = v;
-		d[i*step+1] = v;
-		d[i*step+2] = v;
+		int v = (d[i*Step]+d[i*Step+1]+d[i*Step+2])/3;
+		d[i*Step] = v;
+		d[i*Step+1] = v;
+		d[i*Step+2] = v;
 	}
 
 	
 	if(1)
 	{
-		int freq[256] = {0};
-		int org_weight = 0;
-		int new_weight = 192;
+		int Freq[256] = {0};
+		int OrgWeight = 0;
+		int NewWeight = 192;
 		
 		// find most common frequence
-		for(int y = 0; y < body_size; y++)
-			for(int x = 0; x < body_size; x++)
+		for(int y = 0; y < BodySize; y++)
+			for(int x = 0; x < BodySize; x++)
 			{
-				if(d[y*pitch+x*4+3] > 128)
-					freq[d[y*pitch+x*4]]++;
+				if(d[y*Pitch+x*4+3] > 128)
+					Freq[d[y*Pitch+x*4]]++;
 			}
 		
 		for(int i = 1; i < 256; i++)
 		{
-			if(freq[org_weight] < freq[i])
-				org_weight = i;
+			if(Freq[OrgWeight] < Freq[i])
+				OrgWeight = i;
 		}
 
 		// reorder
-		int inv_org_weight = 255-org_weight;
-		int inv_new_weight = 255-new_weight;
-		for(int y = 0; y < body_size; y++)
-			for(int x = 0; x < body_size; x++)
+		int InvOrgWeight = 255-OrgWeight;
+		int InvNewWeight = 255-NewWeight;
+		for(int y = 0; y < BodySize; y++)
+			for(int x = 0; x < BodySize; x++)
 			{
-				int v = d[y*pitch+x*4];
-				if(v <= org_weight)
-					v = (int)(((v/(float)org_weight) * new_weight));
+				int v = d[y*Pitch+x*4];
+				if(v <= OrgWeight)
+					v = (int)(((v/(float)OrgWeight) * NewWeight));
 				else
-					v = (int)(((v-org_weight)/(float)inv_org_weight)*inv_new_weight + new_weight);
-				d[y*pitch+x*4] = v;
-				d[y*pitch+x*4+1] = v;
-				d[y*pitch+x*4+2] = v;
+					v = (int)(((v-OrgWeight)/(float)InvOrgWeight)*InvNewWeight + NewWeight);
+				d[y*Pitch+x*4] = v;
+				d[y*Pitch+x*4+1] = v;
+				d[y*Pitch+x*4+2] = v;
 			}
 	}
 	
-	self->skins[self->num_skins].color_texture = self->Graphics()->LoadTextureRaw(info.width, info.height, info.format, info.data, info.format, 0);
-	mem_free(info.data);
+	pSelf->m_aSkins[pSelf->m_NumSkins].m_ColorTexture = pSelf->Graphics()->LoadTextureRaw(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, Info.m_Format, 0);
+	mem_free(Info.m_pData);
 
 	// set skin data	
-	strncpy(self->skins[self->num_skins].name, name, min((int)sizeof(self->skins[self->num_skins].name),l-4));
-	dbg_msg("game", "load skin %s", self->skins[self->num_skins].name);
-	self->num_skins++;
+	str_copy(pSelf->m_aSkins[pSelf->m_NumSkins].m_aName, pName, min((int)sizeof(pSelf->m_aSkins[pSelf->m_NumSkins].m_aName),l-3));
+	dbg_msg("game", "load skin %s", pSelf->m_aSkins[pSelf->m_NumSkins].m_aName);
+	pSelf->m_NumSkins++;
 }
 
 
-void SKINS::init()
+void CSkins::Init()
 {
 	// load skins
-	num_skins = 0;
-	engine_listdir(LISTDIRTYPE_ALL, "skins", skinscan, this);
+	m_NumSkins = 0;
+	Storage()->ListDirectory(IStorage::TYPE_ALL, "skins", SkinScan, this);
 }
 
-int SKINS::num()
+int CSkins::Num()
 {
-	return num_skins;	
+	return m_NumSkins;	
 }
 
-const SKINS::SKIN *SKINS::get(int index)
+const CSkins::CSkin *CSkins::Get(int Index)
 {
-	return &skins[index%num_skins];
+	return &m_aSkins[Index%m_NumSkins];
 }
 
-int SKINS::find(const char *name)
+int CSkins::Find(const char *pName)
 {
-	for(int i = 0; i < num_skins; i++)
+	for(int i = 0; i < m_NumSkins; i++)
 	{
-		if(strcmp(skins[i].name, name) == 0)
+		if(str_comp(m_aSkins[i].m_aName, pName) == 0)
 			return i;
 	}
 	return -1;
 }
 
 // these converter functions were nicked from some random internet pages
-static float hue_to_rgb(float v1, float v2, float h)
+static float HueToRgb(float v1, float v2, float h)
 {
    if(h < 0) h += 1;
    if(h > 1) h -= 1;
@@ -157,16 +154,16 @@ static float hue_to_rgb(float v1, float v2, float h)
    return v1;
 }
 
-static vec3 hsl_to_rgb(vec3 in)
+static vec3 HslToRgb(vec3 in)
 {
 	float v1, v2;
-	vec3 out;
+	vec3 Out;
 
 	if(in.s == 0)
 	{
-		out.r = in.l;
-		out.g = in.l;
-		out.b = in.l;
+		Out.r = in.l;
+		Out.g = in.l;
+		Out.b = in.l;
 	}
 	else
 	{
@@ -177,16 +174,16 @@ static vec3 hsl_to_rgb(vec3 in)
 
 		v1 = 2 * in.l - v2;
 
-		out.r = hue_to_rgb(v1, v2, in.h + (1.0f/3.0f));
-		out.g = hue_to_rgb(v1, v2, in.h);
-		out.b = hue_to_rgb(v1, v2, in.h - (1.0f/3.0f));
+		Out.r = HueToRgb(v1, v2, in.h + (1.0f/3.0f));
+		Out.g = HueToRgb(v1, v2, in.h);
+		Out.b = HueToRgb(v1, v2, in.h - (1.0f/3.0f));
 	} 
 
-	return out;
+	return Out;
 }
 
-vec4 SKINS::get_color(int v)
+vec4 CSkins::GetColor(int v)
 {
-	vec3 r = hsl_to_rgb(vec3((v>>16)/255.0f, ((v>>8)&0xff)/255.0f, 0.5f+(v&0xff)/255.0f*0.5f));
+	vec3 r = HslToRgb(vec3(((v>>16)&0xff)/255.0f, ((v>>8)&0xff)/255.0f, 0.5f+(v&0xff)/255.0f*0.5f));
 	return vec4(r.r, r.g, r.b, 1.0f);
 }
diff --git a/src/game/client/components/skins.h b/src/game/client/components/skins.h
new file mode 100644
index 00000000..f733140f
--- /dev/null
+++ b/src/game/client/components/skins.h
@@ -0,0 +1,39 @@
+#ifndef GAME_CLIENT_COMPONENTS_SKINS_H
+#define GAME_CLIENT_COMPONENTS_SKINS_H
+#include <base/vmath.h>
+#include <game/client/component.h>
+
+class CSkins : public CComponent
+{
+public:
+	// do this better and nicer
+	struct CSkin
+	{
+		int m_OrgTexture;
+		int m_ColorTexture;
+		char m_aName[31];
+		char m_aTerm[1];
+		vec3 m_BloodColor;
+	} ;
+
+	CSkins();
+	
+	void Init();
+	
+	vec4 GetColor(int v);
+	int Num();
+	const CSkin *Get(int Index);
+	int Find(const char *pName);
+	
+private:
+	enum
+	{
+		MAX_SKINS=256,
+	};
+
+	CSkin m_aSkins[MAX_SKINS];
+	int m_NumSkins;
+
+	static void SkinScan(const char *pName, int IsDir, void *pUser);
+};
+#endif
diff --git a/src/game/client/components/skins.hpp b/src/game/client/components/skins.hpp
deleted file mode 100644
index 078fd71d..00000000
--- a/src/game/client/components/skins.hpp
+++ /dev/null
@@ -1,36 +0,0 @@
-#include <base/vmath.hpp>
-#include <game/client/component.hpp>
-
-class SKINS : public COMPONENT
-{
-public:
-	// do this better and nicer
-	typedef struct 
-	{
-		int org_texture;
-		int color_texture;
-		char name[31];
-		char term[1];
-		vec3 blood_color;
-	} SKIN;
-
-	SKINS();
-	
-	void init();
-	
-	vec4 get_color(int v);
-	int num();
-	const SKIN *get(int index);
-	int find(const char *name);
-	
-private:
-	enum
-	{
-		MAX_SKINS=256,
-	};
-
-	SKIN skins[MAX_SKINS];
-	int num_skins;
-
-	static void skinscan(const char *name, int is_dir, void *user);
-};
diff --git a/src/game/client/components/sounds.cpp b/src/game/client/components/sounds.cpp
index dfa7e31b..84e45efa 100644
--- a/src/game/client/components/sounds.cpp
+++ b/src/game/client/components/sounds.cpp
@@ -1,54 +1,91 @@
-#include <engine/e_client_interface.h>
-#include <game/generated/gc_data.hpp>
-#include <game/client/gameclient.hpp>
-#include <game/client/components/camera.hpp>
-#include "sounds.hpp"
+#include <engine/sound.h>
+#include <game/generated/client_data.h>
+#include <game/client/gameclient.h>
+#include <game/client/components/camera.h>
+#include "sounds.h"
 
-void SOUNDS::on_init()
+void CSounds::OnInit()
 {
 	// setup sound channels
-	snd_set_channel(SOUNDS::CHN_GUI, 1.0f, 0.0f);
-	snd_set_channel(SOUNDS::CHN_MUSIC, 1.0f, 0.0f);
-	snd_set_channel(SOUNDS::CHN_WORLD, 0.9f, 1.0f);
-	snd_set_channel(SOUNDS::CHN_GLOBAL, 1.0f, 0.0f);
+	Sound()->SetChannel(CSounds::CHN_GUI, 1.0f, 0.0f);
+	Sound()->SetChannel(CSounds::CHN_MUSIC, 1.0f, 0.0f);
+	Sound()->SetChannel(CSounds::CHN_WORLD, 0.9f, 1.0f);
+	Sound()->SetChannel(CSounds::CHN_GLOBAL, 1.0f, 0.0f);
 
-	snd_set_listener_pos(0.0f, 0.0f);
+	Sound()->SetListenerPos(0.0f, 0.0f);
+
+	ClearQueue();
+}
+
+void CSounds::OnReset()
+{
+	Sound()->StopAll();
+	ClearQueue();
 }
 
-void SOUNDS::on_render()
+void CSounds::OnRender()
 {
 	// set listner pos
-	snd_set_listener_pos(gameclient.camera->center.x, gameclient.camera->center.y);
+	Sound()->SetListenerPos(m_pClient->m_pCamera->m_Center.x, m_pClient->m_pCamera->m_Center.y);
+
+	// play sound from queue
+	if(m_QueuePos > 0)
+	{
+		int64 Now =  time_get();
+		if(m_QueueWaitTime <= Now)
+		{
+			Play(CHN_GLOBAL, m_aQueue[0], 1.0f, vec2(0,0));
+			m_QueueWaitTime = Now+time_freq()*3/10; // wait 300ms before playing the next one
+			if(--m_QueuePos > 0)
+				mem_move(m_aQueue, m_aQueue+1, m_QueuePos*sizeof(int));
+		}
+	}
 }
 
-void SOUNDS::play_and_record(int chn, int setid, float vol, vec2 pos)
+void CSounds::ClearQueue()
 {
-	NETMSG_SV_SOUNDGLOBAL msg;
-	msg.soundid = setid;
-	msg.pack(MSGFLAG_NOSEND|MSGFLAG_RECORD);
-	client_send_msg();
+	mem_zero(m_aQueue, sizeof(m_aQueue));
+	m_QueuePos = 0;
+	m_QueueWaitTime = time_get();
+}
+
+void CSounds::Enqueue(int SetId)
+{
+	// add sound to the queue
+	if(m_QueuePos < QUEUE_SIZE)
+		m_aQueue[m_QueuePos++] = SetId;
+}
+
+void CSounds::PlayAndRecord(int Chn, int SetId, float Vol, vec2 Pos)
+{
+	CNetMsg_Sv_SoundGlobal Msg;
+	Msg.m_Soundid = SetId;
+	Client()->SendPackMsg(&Msg, MSGFLAG_NOSEND|MSGFLAG_RECORD);
 	
-	play(chn, setid, vol, pos);
+	Play(Chn, SetId, Vol, Pos);
 }
 
-void SOUNDS::play(int chn, int setid, float vol, vec2 pos)
+void CSounds::Play(int Chn, int SetId, float Vol, vec2 Pos)
 {
-	SOUNDSET *set = &data->sounds[setid];
+	if(SetId < 0 || SetId >= g_pData->m_NumSounds)
+		return;
+
+	SOUNDSET *pSet = &g_pData->m_aSounds[SetId];
 
-	if(!set->num_sounds)
+	if(!pSet->m_NumSounds)
 		return;
 
-	if(set->num_sounds == 1)
+	if(pSet->m_NumSounds == 1)
 	{
-		snd_play_at(chn, set->sounds[0].id, 0, pos.x, pos.y);
+		Sound()->PlayAt(Chn, pSet->m_aSounds[0].m_Id, 0, Pos.x, Pos.y);
 		return;
 	}
 
 	// play a random one
 	int id;
 	do {
-		id = rand() % set->num_sounds;
-	} while(id == set->last);
-	snd_play_at(chn, set->sounds[id].id, 0, pos.x, pos.y);
-	set->last = id;
+		id = rand() % pSet->m_NumSounds;
+	} while(id == pSet->m_Last);
+	Sound()->PlayAt(Chn, pSet->m_aSounds[id].m_Id, 0, Pos.x, Pos.y);
+	pSet->m_Last = id;
 }
diff --git a/src/game/client/components/sounds.h b/src/game/client/components/sounds.h
new file mode 100644
index 00000000..ce74b85e
--- /dev/null
+++ b/src/game/client/components/sounds.h
@@ -0,0 +1,36 @@
+#ifndef GAME_CLIENT_COMPONENTS_SOUNDS_H
+#define GAME_CLIENT_COMPONENTS_SOUNDS_H
+#include <game/client/component.h>
+
+class CSounds : public CComponent
+{
+	enum
+	{
+		QUEUE_SIZE = 32,
+	};
+	int m_aQueue[QUEUE_SIZE];
+	int m_QueuePos;
+	int64 m_QueueWaitTime;
+
+public:
+	// sound channels
+	enum
+	{
+		CHN_GUI=0,
+		CHN_MUSIC,
+		CHN_WORLD,
+		CHN_GLOBAL,
+	};
+
+	virtual void OnInit();
+	virtual void OnReset();
+	virtual void OnRender();
+	
+	void ClearQueue();
+	void Enqueue(int SetId);
+	void Play(int Channel, int SetId, float Vol, vec2 Pos);
+	void PlayAndRecord(int Channel, int SetId, float Vol, vec2 Pos);
+};
+
+
+#endif
diff --git a/src/game/client/components/sounds.hpp b/src/game/client/components/sounds.hpp
deleted file mode 100644
index 95ddb1ec..00000000
--- a/src/game/client/components/sounds.hpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <game/client/component.hpp>
-
-class SOUNDS : public COMPONENT
-{
-public:
-	// sound channels
-	enum
-	{
-		CHN_GUI=0,
-		CHN_MUSIC,
-		CHN_WORLD,
-		CHN_GLOBAL,
-	};
-
-	virtual void on_init();
-	virtual void on_render();
-	
-	void play(int chn, int setid, float vol, vec2 pos);
-	void play_and_record(int chn, int setid, float vol, vec2 pos);
-};
-
-
diff --git a/src/game/client/components/voting.cpp b/src/game/client/components/voting.cpp
index dcf5c954..17c0fe31 100644
--- a/src/game/client/components/voting.cpp
+++ b/src/game/client/components/voting.cpp
@@ -1,200 +1,219 @@
-#include <engine/e_client_interface.h>
-#include <game/generated/g_protocol.hpp>
-#include <base/vmath.hpp>
-#include <game/client/render.hpp>
-//#include <game/client/gameclient.hpp>
-#include "voting.hpp"
-
-void VOTING::con_callvote(void *result, void *user_data)
+#include <engine/shared/config.h>
+
+#include <game/generated/protocol.h>
+#include <base/vmath.h>
+#include <game/client/render.h>
+//#include <game/client/gameclient.h>
+#include "voting.h"
+
+void CVoting::ConCallvote(IConsole::IResult *pResult, void *pUserData)
+{
+	CVoting *pSelf = (CVoting*)pUserData;
+	pSelf->Callvote(pResult->GetString(0), pResult->GetString(1));
+}
+
+void CVoting::ConVote(IConsole::IResult *pResult, void *pUserData)
+{
+	CVoting *pSelf = (CVoting *)pUserData;
+	if(str_comp_nocase(pResult->GetString(0), "yes") == 0)
+		pSelf->Vote(1);
+	else if(str_comp_nocase(pResult->GetString(0), "no") == 0)
+		pSelf->Vote(-1);
+}
+
+void CVoting::Callvote(const char *pType, const char *pValue)
 {
-	VOTING *self = (VOTING*)user_data;
-	self->callvote(console_arg_string(result, 0), console_arg_string(result, 1));
+	CNetMsg_Cl_CallVote Msg = {0};
+	Msg.m_Type = pType;
+	Msg.m_Value = pValue;
+	Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
 }
 
-void VOTING::con_vote(void *result, void *user_data)
+void CVoting::CallvoteKick(int ClientId)
 {
-	VOTING *self = (VOTING *)user_data;
-	if(str_comp_nocase(console_arg_string(result, 0), "yes") == 0)
-		self->vote(1);
-	else if(str_comp_nocase(console_arg_string(result, 0), "no") == 0)
-		self->vote(-1);
+	char Buf[32];
+	str_format(Buf, sizeof(Buf), "%d", ClientId);
+	Callvote("kick", Buf);
 }
 
-void VOTING::callvote(const char *type, const char *value)
+void CVoting::CallvoteOption(int OptionId)
 {
-	NETMSG_CL_CALLVOTE msg = {0};
-	msg.type = type;
-	msg.value = value;
-	msg.pack(MSGFLAG_VITAL);
-	client_send_msg();
+	CVoteOption *pOption = m_pFirst;
+	while(pOption && OptionId >= 0)
+	{
+		if(OptionId == 0)
+		{
+			Callvote("option", pOption->m_aCommand);
+			break;
+		}
+		
+		OptionId--;
+		pOption = pOption->m_pNext;
+	}
 }
 
-void VOTING::callvote_kick(int client_id)
+void CVoting::ForcevoteKick(int ClientId)
 {
-	char buf[32];
-	str_format(buf, sizeof(buf), "%d", client_id);
-	callvote("kick", buf);
+	char Buf[32];
+	str_format(Buf, sizeof(Buf), "kick %d", ClientId);
+	Client()->Rcon(Buf);
 }
 
-void VOTING::callvote_option(int option_id)
+void CVoting::ForcevoteOption(int OptionId)
 {
-	VOTEOPTION *option = this->first;
-	while(option && option_id >= 0)
+	CVoteOption *pOption = m_pFirst;
+	while(pOption && OptionId >= 0)
 	{
-		if(option_id == 0)
+		if(OptionId == 0)
 		{
-			callvote("option", option->command);
+			Client()->Rcon(pOption->m_aCommand);
 			break;
 		}
 		
-		option_id--;
-		option = option->next;
+		OptionId--;
+		pOption = pOption->m_pNext;
 	}
 }
 
-void VOTING::vote(int v)
+void CVoting::Vote(int v)
 {
-	NETMSG_CL_VOTE msg = {v};
-	msg.pack(MSGFLAG_VITAL);
-	client_send_msg();
+	CNetMsg_Cl_Vote Msg = {v};
+	Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
 }
 
-VOTING::VOTING()
+CVoting::CVoting()
 {
-	heap = 0;
-	clearoptions();
-	on_reset();
+	ClearOptions();
+	OnReset();
 }
 
 
-void VOTING::clearoptions()
+void CVoting::ClearOptions()
 {
-	if(heap)
-		memheap_destroy(heap);
-	heap = memheap_create();
+	m_Heap.Reset();
 	
-	first = 0;
-	last = 0;
+	m_pFirst = 0;
+	m_pLast = 0;
 }
 
-void VOTING::on_reset()
+void CVoting::OnReset()
 {
-	closetime = 0;
-	description[0] = 0;
-	command[0] = 0;
-	yes = no = pass = total = 0;
-	voted = 0;
+	m_Closetime = 0;
+	m_aDescription[0] = 0;
+	m_aCommand[0] = 0;
+	m_Yes = m_No = m_Pass = m_Total = 0;
+	m_Voted = 0;
 }
 
-void VOTING::on_console_init()
+void CVoting::OnConsoleInit()
 {
-	MACRO_REGISTER_COMMAND("callvote", "sr", CFGFLAG_CLIENT, con_callvote, this, "Call vote");
-	MACRO_REGISTER_COMMAND("vote", "r", CFGFLAG_CLIENT, con_vote, this, "Vote yes/no");
+	Console()->Register("callvote", "sr", CFGFLAG_CLIENT, ConCallvote, this, "Call vote");
+	Console()->Register("vote", "r", CFGFLAG_CLIENT, ConVote, this, "Vote yes/no");
 }
 
-void VOTING::on_message(int msgtype, void *rawmsg)
+void CVoting::OnMessage(int MsgType, void *pRawMsg)
 {
-	if(msgtype == NETMSGTYPE_SV_VOTE_SET)
+	if(MsgType == NETMSGTYPE_SV_VOTESET)
 	{
-		NETMSG_SV_VOTE_SET *msg = (NETMSG_SV_VOTE_SET *)rawmsg;
-		if(msg->timeout)
+		CNetMsg_Sv_VoteSet *pMsg = (CNetMsg_Sv_VoteSet *)pRawMsg;
+		if(pMsg->m_Timeout)
 		{
-			on_reset();
-			str_copy(description, msg->description, sizeof(description));
-			str_copy(command, msg->command, sizeof(description));
-			closetime = time_get() + time_freq() * msg->timeout;
+			OnReset();
+			str_copy(m_aDescription, pMsg->m_pDescription, sizeof(m_aDescription));
+			str_copy(m_aCommand, pMsg->m_pCommand, sizeof(m_aCommand));
+			m_Closetime = time_get() + time_freq() * pMsg->m_Timeout;
 		}
 		else
-			on_reset();
+			OnReset();
 	}
-	else if(msgtype == NETMSGTYPE_SV_VOTE_STATUS)
+	else if(MsgType == NETMSGTYPE_SV_VOTESTATUS)
 	{
-		NETMSG_SV_VOTE_STATUS *msg = (NETMSG_SV_VOTE_STATUS *)rawmsg;
-		yes = msg->yes;
-		no = msg->no;
-		pass = msg->pass;
-		total = msg->total;
+		CNetMsg_Sv_VoteStatus *pMsg = (CNetMsg_Sv_VoteStatus *)pRawMsg;
+		m_Yes = pMsg->m_Yes;
+		m_No = pMsg->m_No;
+		m_Pass = pMsg->m_Pass;
+		m_Total = pMsg->m_Total;
 	}	
-	else if(msgtype == NETMSGTYPE_SV_VOTE_CLEAROPTIONS)
+	else if(MsgType == NETMSGTYPE_SV_VOTECLEAROPTIONS)
 	{
-		clearoptions();
+		ClearOptions();
 	}
-	else if(msgtype == NETMSGTYPE_SV_VOTE_OPTION)
+	else if(MsgType == NETMSGTYPE_SV_VOTEOPTION)
 	{
-		NETMSG_SV_VOTE_OPTION *msg = (NETMSG_SV_VOTE_OPTION *)rawmsg;
-		int len = str_length(msg->command);
+		CNetMsg_Sv_VoteOption *pMsg = (CNetMsg_Sv_VoteOption *)pRawMsg;
+		int Len = str_length(pMsg->m_pCommand);
 	
-		VOTEOPTION *option = (VOTEOPTION *)memheap_allocate(heap, sizeof(VOTEOPTION) + len);
-		option->next = 0;
-		option->prev = last;
-		if(option->prev)
-			option->prev->next = option;
-		last = option;
-		if(!first)
-			first = option;
+		CVoteOption *pOption = (CVoteOption *)m_Heap.Allocate(sizeof(CVoteOption) + Len);
+		pOption->m_pNext = 0;
+		pOption->m_pPrev = m_pLast;
+		if(pOption->m_pPrev)
+			pOption->m_pPrev->m_pNext = pOption;
+		m_pLast = pOption;
+		if(!m_pFirst)
+			m_pFirst = pOption;
 		
-		mem_copy(option->command, msg->command, len+1);
+		mem_copy(pOption->m_aCommand, pMsg->m_pCommand, Len+1);
 
 	}
 }
 
-void VOTING::on_render()
+void CVoting::OnRender()
 {
 }
 
 
-void VOTING::render_bars(CUIRect bars, bool text)
+void CVoting::RenderBars(CUIRect Bars, bool Text)
 {
-	RenderTools()->DrawUIRect(&bars, vec4(0.8f,0.8f,0.8f,0.5f), CUI::CORNER_ALL, bars.h/3);
+	RenderTools()->DrawUIRect(&Bars, vec4(0.8f,0.8f,0.8f,0.5f), CUI::CORNER_ALL, Bars.h/3);
 	
-	CUIRect splitter = bars;
-	splitter.x = splitter.x+splitter.w/2;
-	splitter.w = splitter.h/2.0f;
-	splitter.x -= splitter.w/2;
-	RenderTools()->DrawUIRect(&splitter, vec4(0.4f,0.4f,0.4f,0.5f), CUI::CORNER_ALL, splitter.h/4);
+	CUIRect Splitter = Bars;
+	Splitter.x = Splitter.x+Splitter.w/2;
+	Splitter.w = Splitter.h/2.0f;
+	Splitter.x -= Splitter.w/2;
+	RenderTools()->DrawUIRect(&Splitter, vec4(0.4f,0.4f,0.4f,0.5f), CUI::CORNER_ALL, Splitter.h/4);
 			
-	if(total)
+	if(m_Total)
 	{
-		CUIRect pass_area = bars;
-		if(yes)
+		CUIRect PassArea = Bars;
+		if(m_Yes)
 		{
-			CUIRect yes_area = bars;
-			yes_area.w *= yes/(float)total;
-			RenderTools()->DrawUIRect(&yes_area, vec4(0.2f,0.9f,0.2f,0.85f), CUI::CORNER_ALL, bars.h/3);
+			CUIRect YesArea = Bars;
+			YesArea.w *= m_Yes/(float)m_Total;
+			RenderTools()->DrawUIRect(&YesArea, vec4(0.2f,0.9f,0.2f,0.85f), CUI::CORNER_ALL, Bars.h/3);
 			
-			if(text)
+			if(Text)
 			{
-				char buf[256];
-				str_format(buf, sizeof(buf), "%d", yes);
-				UI()->DoLabel(&yes_area, buf, bars.h*0.75f, 0);
+				char Buf[256];
+				str_format(Buf, sizeof(Buf), "%d", m_Yes);
+				UI()->DoLabel(&YesArea, Buf, Bars.h*0.75f, 0);
 			}
 			
-			pass_area.x += yes_area.w;
-			pass_area.w -= yes_area.w;
+			PassArea.x += YesArea.w;
+			PassArea.w -= YesArea.w;
 		}
 		
-		if(no)
+		if(m_No)
 		{
-			CUIRect no_area = bars;
-			no_area.w *= no/(float)total;
-			no_area.x = (bars.x + bars.w)-no_area.w;
-			RenderTools()->DrawUIRect(&no_area, vec4(0.9f,0.2f,0.2f,0.85f), CUI::CORNER_ALL, bars.h/3);
+			CUIRect NoArea = Bars;
+			NoArea.w *= m_No/(float)m_Total;
+			NoArea.x = (Bars.x + Bars.w)-NoArea.w;
+			RenderTools()->DrawUIRect(&NoArea, vec4(0.9f,0.2f,0.2f,0.85f), CUI::CORNER_ALL, Bars.h/3);
 			
-			if(text)
+			if(Text)
 			{
-				char buf[256];
-				str_format(buf, sizeof(buf), "%d", no);
-				UI()->DoLabel(&no_area, buf, bars.h*0.75f, 0);
+				char Buf[256];
+				str_format(Buf, sizeof(Buf), "%d", m_No);
+				UI()->DoLabel(&NoArea, Buf, Bars.h*0.75f, 0);
 			}
 
-			pass_area.w -= no_area.w;
+			PassArea.w -= NoArea.w;
 		}
 
-		if(text && pass)
+		if(Text && m_Pass)
 		{
-			char buf[256];
-			str_format(buf, sizeof(buf), "%d", pass);
-			UI()->DoLabel(&pass_area, buf, bars.h*0.75f, 0);
+			char Buf[256];
+			str_format(Buf, sizeof(Buf), "%d", m_Pass);
+			UI()->DoLabel(&PassArea, Buf, Bars.h*0.75f, 0);
 		}
 	}	
 }
diff --git a/src/game/client/components/voting.h b/src/game/client/components/voting.h
new file mode 100644
index 00000000..1f5d2fc5
--- /dev/null
+++ b/src/game/client/components/voting.h
@@ -0,0 +1,58 @@
+#ifndef GAME_CLIENT_COMPONENTS_VOTING_H
+#define GAME_CLIENT_COMPONENTS_VOTING_H
+#include <game/client/component.h>
+#include <game/client/ui.h>
+#include <engine/shared/memheap.h>
+
+class CVoting : public CComponent
+{
+	CHeap m_Heap;
+
+	static void ConCallvote(IConsole::IResult *pResult, void *pUserData);
+	static void ConVote(IConsole::IResult *pResult, void *pUserData);
+	
+	int64 m_Closetime;
+	char m_aDescription[512];
+	char m_aCommand[512];
+	int m_Voted;
+	
+	void ClearOptions();
+	void Callvote(const char *pType, const char *pValue);
+	
+public:
+
+	struct CVoteOption
+	{
+		CVoteOption *m_pNext;
+		CVoteOption *m_pPrev;
+		char m_aCommand[1];
+	};
+	
+	CVoteOption *m_pFirst;
+	CVoteOption *m_pLast;
+
+	CVoting();
+	virtual void OnReset();
+	virtual void OnConsoleInit();
+	virtual void OnMessage(int Msgtype, void *pRawMsg);
+	virtual void OnRender();
+	
+	void RenderBars(CUIRect Bars, bool Text);
+	
+	void CallvoteKick(int ClientId);
+	void CallvoteOption(int Option);
+	void ForcevoteKick(int ClientId);
+	void ForcevoteOption(int Option);
+	
+	void Vote(int v); // -1 = no, 1 = yes
+	
+	int SecondsLeft() { return (m_Closetime - time_get())/time_freq(); }
+	bool IsVoting() { return m_Closetime != 0; }
+	int TakenChoice() const { return m_Voted; }
+	const char *VoteDescription() const { return m_aDescription; }
+	const char *VoteCommand() const { return m_aCommand; }
+	
+	int m_Yes, m_No, m_Pass, m_Total;
+};
+
+#endif
diff --git a/src/game/client/components/voting.hpp b/src/game/client/components/voting.hpp
deleted file mode 100644
index e04e1840..00000000
--- a/src/game/client/components/voting.hpp
+++ /dev/null
@@ -1,52 +0,0 @@
-#include <game/client/component.hpp>
-#include <game/client/ui.hpp>
-#include <engine/e_memheap.h>
-
-class VOTING : public COMPONENT
-{
-	HEAP *heap;
-
-	static void con_callvote(void *result, void *user_data);
-	static void con_vote(void *result, void *user_data);
-	
-	int64 closetime;
-	char description[512];
-	char command[512];
-	int voted;
-	
-	void clearoptions();
-	void callvote(const char *type, const char *value);
-	
-public:
-
-	struct VOTEOPTION
-	{
-		VOTEOPTION *next;
-		VOTEOPTION *prev;
-		char command[1];
-	};
-	VOTEOPTION *first;
-	VOTEOPTION *last;
-
-	VOTING();
-	virtual void on_reset();
-	virtual void on_console_init();
-	virtual void on_message(int msgtype, void *rawmsg);
-	virtual void on_render();
-	
-	void render_bars(CUIRect bars, bool text);
-	
-	void callvote_kick(int client_id);
-	void callvote_option(int option);
-	
-	void vote(int v); // -1 = no, 1 = yes
-	
-	int seconds_left() { return (closetime - time_get())/time_freq(); }
-	bool is_voting() { return closetime != 0; }
-	int taken_choice() const { return voted; }
-	const char *vote_description() const { return description; }
-	const char *vote_command() const { return command; }
-	
-	int yes, no, pass, total;
-};
-
diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp
index 25a42620..d59a7a04 100644
--- a/src/game/client/gameclient.cpp
+++ b/src/game/client/gameclient.cpp
@@ -1,82 +1,87 @@
-#include <string.h>
-#include <engine/e_client_interface.h>
-#include <engine/client/graphics.h>
-#include <engine/e_demorec.h>
-
-#include <game/generated/g_protocol.hpp>
-#include <game/generated/gc_data.hpp>
-
-#include <game/layers.hpp>
-#include <game/localization.hpp>
-#include "render.hpp"
-
-#include "gameclient.hpp"
-
-#include "components/binds.hpp"
-#include "components/broadcast.hpp"
-#include "components/camera.hpp"
-#include "components/chat.hpp"
-#include "components/console.hpp"
-#include "components/controls.hpp"
-#include "components/damageind.hpp"
-#include "components/debughud.hpp"
-#include "components/effects.hpp"
-#include "components/emoticon.hpp"
-#include "components/flow.hpp"
-#include "components/hud.hpp"
-#include "components/items.hpp"
-#include "components/killmessages.hpp"
-#include "components/mapimages.hpp"
-#include "components/maplayers.hpp"
-#include "components/menus.hpp"
-#include "components/motd.hpp"
-#include "components/particles.hpp"
-#include "components/players.hpp"
-#include "components/nameplates.hpp"
-#include "components/scoreboard.hpp"
-#include "components/skins.hpp"
-#include "components/sounds.hpp"
-#include "components/voting.hpp"
-
-GAMECLIENT gameclient;
+#include <engine/graphics.h>
+#include <engine/textrender.h>
+#include <engine/sound.h>
+#include <engine/demo.h>
+#include <engine/map.h>
+#include <engine/storage.h>
+#include <engine/serverbrowser.h>
+#include <engine/shared/demorec.h>
+#include <engine/shared/config.h>
+
+#include <game/generated/protocol.h>
+#include <game/generated/client_data.h>
+
+#include <game/localization.h>
+#include <game/version.h>
+#include "render.h"
+
+#include "gameclient.h"
+
+#include "components/binds.h"
+#include "components/broadcast.h"
+#include "components/camera.h"
+#include "components/chat.h"
+#include "components/console.h"
+#include "components/controls.h"
+#include "components/damageind.h"
+#include "components/debughud.h"
+#include "components/effects.h"
+#include "components/emoticon.h"
+#include "components/flow.h"
+#include "components/hud.h"
+#include "components/items.h"
+#include "components/killmessages.h"
+#include "components/mapimages.h"
+#include "components/maplayers.h"
+#include "components/menus.h"
+#include "components/motd.h"
+#include "components/particles.h"
+#include "components/players.h"
+#include "components/nameplates.h"
+#include "components/scoreboard.h"
+#include "components/skins.h"
+#include "components/sounds.h"
+#include "components/voting.h"
+
+CGameClient g_GameClient;
 
 // instanciate all systems
-static KILLMESSAGES killmessages;
-static CAMERA camera;
-static CHAT chat;
-static MOTD motd;
-static BROADCAST broadcast;
-static CONSOLE console;
-static BINDS binds;
-static PARTICLES particles;
-static MENUS menus;
-static SKINS skins;
-static FLOW flow;
-static HUD hud;
-static DEBUGHUD debughud;
-static CONTROLS controls;
-static EFFECTS effects;
-static SCOREBOARD scoreboard;
-static SOUNDS sounds;
-static EMOTICON emoticon;
-static DAMAGEIND damageind;
-static VOTING voting;
-
-static PLAYERS players;
-static NAMEPLATES nameplates;
-static ITEMS items;
-static MAPIMAGES mapimages;
-
-static MAPLAYERS maplayers_background(MAPLAYERS::TYPE_BACKGROUND);
-static MAPLAYERS maplayers_foreground(MAPLAYERS::TYPE_FOREGROUND);
-
-GAMECLIENT::STACK::STACK() { num = 0; }
-void GAMECLIENT::STACK::add(class COMPONENT *component) { components[num++] = component; }
-
-static int load_current;
-static int load_total;
-
-static void load_sounds_thread(void *do_render)
+static CKillMessages gs_KillMessages;
+static CCamera gs_Camera;
+static CChat gs_Chat;
+static CMotd gs_Motd;
+static CBroadcast gs_Broadcast;
+static CGameConsole gs_GameConsole;
+static CBinds gs_Binds;
+static CParticles gs_Particles;
+static CMenus gs_Menus;
+static CSkins gs_Skins;
+static CFlow gs_Flow;
+static CHud gs_Hud;
+static CDebugHud gs_DebugHud;
+static CControls gs_Controls;
+static CEffects gs_Effects;
+static CScoreboard gs_Scoreboard;
+static CSounds gs_Sounds;
+static CEmoticon gs_Emoticon;
+static CDamageInd gsDamageInd;
+static CVoting gs_Voting;
+
+static CPlayers gs_Players;
+static CNamePlates gs_NamePlates;
+static CItems gs_Items;
+static CMapImages gs_MapImages;
+
+static CMapLayers gs_MapLayersBackGround(CMapLayers::TYPE_BACKGROUND);
+static CMapLayers gs_MapLayersForeGround(CMapLayers::TYPE_FOREGROUND);
+
+CGameClient::CStack::CStack() { m_Num = 0; }
+void CGameClient::CStack::Add(class CComponent *pComponent) { m_paComponents[m_Num++] = pComponent; }
+
+static int gs_LoadCurrent;
+static int gs_LoadTotal;
+
+/*static void load_sounds_thread(void *do_render)
 {
 	// load sounds
 	for(int s = 0; s < data->num_sounds; s++)
@@ -85,274 +90,235 @@ static void load_sounds_thread(void *do_render)
 			gameclient.menus->render_loading(load_current/(float)load_total);
 		for(int i = 0; i < data->sounds[s].num_sounds; i++)
 		{
-			int id = snd_load_wv(data->sounds[s].sounds[i].filename);
+			int id = Sound()->LoadWV(data->sounds[s].sounds[i].filename);
 			data->sounds[s].sounds[i].id = id;
 		}
 
 		if(do_render)
 			load_current++;
 	}
-}
+}*/
 
-static void con_serverdummy(void *result, void *user_data)
+static void ConServerDummy(IConsole::IResult *pResult, void *pUserData)
 {
 	dbg_msg("client", "this command is not available on the client");
 }
 
-#include <base/tl/sorted_array.hpp>
-
-void GAMECLIENT::on_console_init()
-{
-	if(0)
-	{
-		int ints[4] = {0,1,2,3};
-		for(int s = 1; s < 4; s++)
-		{
-			//s = 2;
-			plain_range_sorted<int> test_sorted_range(ints, ints+s);
-			plain_range_sorted<int> res1, res2;
-			
-			//res2 = partition_binary(test_sorted_range, 1);
-		
-			//for(int i = 0; i < 4; i++)
-			//	dbg_assert(partition_linear(test_sorted_range, i).front() == i, "partition linear failed");
-				
-				
-			dbg_msg("", "size %d", s);
-
-			for(int i = -1; i < 5; i++)
-			{
-				res1 = partition_linear(test_sorted_range, i);
-				dbg_msg("", "\tlin %d == %d", i, res1.empty()?-1:res1.front());
+#include <base/tl/sorted_array.h>
 
-				res2 = partition_binary(test_sorted_range, i);
-				dbg_msg("", "\tbin %d == %d", i, res2.empty()?-1:res2.front());
-				//dbg_assert(partition_binary(plain_range_sorted<int>(ints, ints+6), i).front() == i+1, "partition binary failed");
-			}
-		} //*/
+const char *CGameClient::Version() { return GAME_VERSION; }
+const char *CGameClient::NetVersion() { return GAME_NETVERSION; }
+const char *CGameClient::GetItemName(int Type) { return m_NetObjHandler.GetObjName(Type); }
 
-		sorted_array<int> test;
-		test.add(4);
-		test.add(1);
-		
-		for(int i = 0; i < 100; i++)
-		{
-			int this_add = rand();
-			test.add(this_add);
-			if(!sort_verify(test.all()))
-			{
-				dbg_msg("", "error inserting %d", this_add);
-				for(sorted_array<int>::range r = test.all(); !r.empty(); r.pop_front())
-					dbg_msg("", "%d", r.front());
-				exit(-1);
-			}
-		}/*
-			
-		
-		test.add(1);
-		test.add(4);
-		test.add(3);
-		test.add(4);
-		test.add(3);
-		test.add(2);
-		//test.insert(1, 1);
-		for(sorted_array<int>::range r = test.all(); !r.empty(); r.pop_front())
-			dbg_msg("", "%d", r.front());
-			*/
-			
-		sort_verify(test.all());
-		/*
-		for(int i = 0; i < 15; i++)
-		{
-			dbg_msg("", "found %d == %d", i, !find_binary(test.all(), i).empty());
-		}*/
-		
-		exit(-1);
-	}
+void CGameClient::OnConsoleInit()
+{
+	m_pClient = Kernel()->RequestInterface<IClient>();
+	m_pGraphics = Kernel()->RequestInterface<IGraphics>();
+	m_pTextRender = Kernel()->RequestInterface<ITextRender>();
+	m_pSound = Kernel()->RequestInterface<ISound>();
+	m_pInput = Kernel()->RequestInterface<IInput>();
+	m_pConsole = Kernel()->RequestInterface<IConsole>();
+	m_pStorage = Kernel()->RequestInterface<IStorage>();
+	m_pDemoPlayer = Kernel()->RequestInterface<IDemoPlayer>();
+	m_pServerBrowser = Kernel()->RequestInterface<IServerBrowser>();
 	
 	// setup pointers
-	binds = &::binds;
-	console = &::console;
-	particles = &::particles;
-	menus = &::menus;
-	skins = &::skins;
-	chat = &::chat;
-	flow = &::flow;
-	camera = &::camera;
-	controls = &::controls;
-	effects = &::effects;
-	sounds = &::sounds;
-	motd = &::motd;
-	damageind = &::damageind;
-	mapimages = &::mapimages;
-	voting = &::voting;
+	m_pBinds = &::gs_Binds;
+	m_pGameConsole = &::gs_GameConsole;
+	m_pParticles = &::gs_Particles;
+	m_pMenus = &::gs_Menus;
+	m_pSkins = &::gs_Skins;
+	m_pChat = &::gs_Chat;
+	m_pFlow = &::gs_Flow;
+	m_pCamera = &::gs_Camera;
+	m_pControls = &::gs_Controls;
+	m_pEffects = &::gs_Effects;
+	m_pSounds = &::gs_Sounds;
+	m_pMotd = &::gs_Motd;
+	m_pDamageind = &::gsDamageInd;
+	m_pMapimages = &::gs_MapImages;
+	m_pVoting = &::gs_Voting;
 	
 	// make a list of all the systems, make sure to add them in the corrent render order
-	all.add(skins);
-	all.add(mapimages);
-	all.add(effects); // doesn't render anything, just updates effects
-	all.add(particles);
-	all.add(binds);
-	all.add(controls);
-	all.add(camera);
-	all.add(sounds);
-	all.add(voting);
-	all.add(particles); // doesn't render anything, just updates all the particles
-	
-	all.add(&maplayers_background); // first to render
-	all.add(&particles->render_trail);
-	all.add(&particles->render_explosions);
-	all.add(&items);
-	all.add(&players);
-	all.add(&maplayers_foreground);
-	all.add(&nameplates);
-	all.add(&particles->render_general);
-	all.add(damageind);
-	all.add(&hud);
-	all.add(&emoticon);
-	all.add(&killmessages);
-	all.add(chat);
-	all.add(&broadcast);
-	all.add(&debughud);
-	all.add(&scoreboard);
-	all.add(motd);
-	all.add(menus);
-	all.add(console);
+	m_All.Add(m_pSkins);
+	m_All.Add(m_pMapimages);
+	m_All.Add(m_pEffects); // doesn't render anything, just updates effects
+	m_All.Add(m_pParticles);
+	m_All.Add(m_pBinds);
+	m_All.Add(m_pControls);
+	m_All.Add(m_pCamera);
+	m_All.Add(m_pSounds);
+	m_All.Add(m_pVoting);
+	m_All.Add(m_pParticles); // doesn't render anything, just updates all the particles
+	
+	m_All.Add(&gs_MapLayersBackGround); // first to render
+	m_All.Add(&m_pParticles->m_RenderTrail);
+	m_All.Add(&m_pParticles->m_RenderExplosions);
+	m_All.Add(&gs_Items);
+	m_All.Add(&gs_Players);
+	m_All.Add(&gs_MapLayersForeGround);
+	m_All.Add(&gs_NamePlates);
+	m_All.Add(&m_pParticles->m_RenderGeneral);
+	m_All.Add(m_pDamageind);
+	m_All.Add(&gs_Hud);
+	m_All.Add(&gs_Emoticon);
+	m_All.Add(&gs_KillMessages);
+	m_All.Add(m_pChat);
+	m_All.Add(&gs_Broadcast);
+	m_All.Add(&gs_DebugHud);
+	m_All.Add(&gs_Scoreboard);
+	m_All.Add(m_pMotd);
+	m_All.Add(m_pMenus);
+	m_All.Add(m_pGameConsole);
 	
 	// build the input stack
-	input.add(&menus->binder); // this will take over all input when we want to bind a key
-	input.add(&binds->special_binds);
-	input.add(console);
-	input.add(chat); // chat has higher prio due to tha you can quit it by pressing esc
-	input.add(motd); // for pressing esc to remove it
-	input.add(menus);
-	input.add(&emoticon);
-	input.add(controls);
-	input.add(binds);
+	m_Input.Add(&m_pMenus->m_Binder); // this will take over all input when we want to bind a key
+	m_Input.Add(&m_pBinds->m_SpecialBinds);
+	m_Input.Add(m_pGameConsole);
+	m_Input.Add(m_pChat); // chat has higher prio due to tha you can quit it by pressing esc
+	m_Input.Add(m_pMotd); // for pressing esc to remove it
+	m_Input.Add(m_pMenus);
+	m_Input.Add(&gs_Emoticon);
+	m_Input.Add(m_pControls);
+	m_Input.Add(m_pBinds);
 	
 	// add the some console commands
-	MACRO_REGISTER_COMMAND("team", "i", CFGFLAG_CLIENT, con_team, this, "Switch team");
-	MACRO_REGISTER_COMMAND("kill", "", CFGFLAG_CLIENT, con_kill, this, "Kill yourself");
+	Console()->Register("team", "i", CFGFLAG_CLIENT, ConTeam, this, "Switch team");
+	Console()->Register("kill", "", CFGFLAG_CLIENT, ConKill, this, "Kill yourself");
 	
 	// register server dummy commands for tab completion
-	MACRO_REGISTER_COMMAND("tune", "si", CFGFLAG_SERVER, con_serverdummy, 0, "Tune variable to value");
-	MACRO_REGISTER_COMMAND("tune_reset", "", CFGFLAG_SERVER, con_serverdummy, 0, "Reset tuning");
-	MACRO_REGISTER_COMMAND("tune_dump", "", CFGFLAG_SERVER, con_serverdummy, 0, "Dump tuning");
-	MACRO_REGISTER_COMMAND("change_map", "r", CFGFLAG_SERVER, con_serverdummy, 0, "Change map");
-	MACRO_REGISTER_COMMAND("restart", "?i", CFGFLAG_SERVER, con_serverdummy, 0, "Restart in x seconds");
-	MACRO_REGISTER_COMMAND("broadcast", "r", CFGFLAG_SERVER, con_serverdummy, 0, "Broadcast message");
-	/*MACRO_REGISTER_COMMAND("say", "r", CFGFLAG_SERVER, con_serverdummy, 0);*/
-	MACRO_REGISTER_COMMAND("set_team", "ii", CFGFLAG_SERVER, con_serverdummy, 0, "Set team of player to team");
-	MACRO_REGISTER_COMMAND("addvote", "r", CFGFLAG_SERVER, con_serverdummy, 0, "Add a voting option");
-	/*MACRO_REGISTER_COMMAND("vote", "", CFGFLAG_SERVER, con_serverdummy, 0);*/
+	Console()->Register("tune", "si", CFGFLAG_SERVER, ConServerDummy, 0, "Tune variable to value");
+	Console()->Register("tune_reset", "", CFGFLAG_SERVER, ConServerDummy, 0, "Reset tuning");
+	Console()->Register("tune_dump", "", CFGFLAG_SERVER, ConServerDummy, 0, "Dump tuning");
+	Console()->Register("change_map", "r", CFGFLAG_SERVER, ConServerDummy, 0, "Change map");
+	Console()->Register("restart", "?i", CFGFLAG_SERVER, ConServerDummy, 0, "Restart in x seconds");
+	Console()->Register("broadcast", "r", CFGFLAG_SERVER, ConServerDummy, 0, "Broadcast message");
+	//MACRO_REGISTER_COMMAND("say", "r", CFGFLAG_SERVER, con_serverdummy, 0);
+	Console()->Register("set_team", "ii", CFGFLAG_SERVER, ConServerDummy, 0, "Set team of player to team");
+	Console()->Register("addvote", "r", CFGFLAG_SERVER, ConServerDummy, 0, "Add a voting option");
+	//MACRO_REGISTER_COMMAND("vote", "", CFGFLAG_SERVER, con_serverdummy, 0);
+
+
+	// propagate pointers
+	m_UI.SetGraphics(Graphics(), TextRender());
+	m_RenderTools.m_pGraphics = Graphics();
+	m_RenderTools.m_pUI = UI();
+	for(int i = 0; i < m_All.m_Num; i++)
+		m_All.m_paComponents[i]->m_pClient = this;
 	
 	// let all the other components register their console commands
-	for(int i = 0; i < all.num; i++)
-		all.components[i]->on_console_init();
+	for(int i = 0; i < m_All.m_Num; i++)
+		m_All.m_paComponents[i]->OnConsoleInit();
 	
 	
 	//
-	{ static COMMANDCHAIN chain; console_chain_command("player_name", &chain, conchain_special_infoupdate, this); }
-	{ static COMMANDCHAIN chain; console_chain_command("player_use_custom_color", &chain, conchain_special_infoupdate, this); }
-	{ static COMMANDCHAIN chain; console_chain_command("player_color_body", &chain, conchain_special_infoupdate, this); }
-	{ static COMMANDCHAIN chain; console_chain_command("player_color_feet", &chain, conchain_special_infoupdate, this); }
-	{ static COMMANDCHAIN chain; console_chain_command("player_skin", &chain, conchain_special_infoupdate, this); }
-	
-	
-	
+	Console()->Chain("player_name", ConchainSpecialInfoupdate, this);
+	Console()->Chain("player_use_custom_color", ConchainSpecialInfoupdate, this);
+	Console()->Chain("player_color_body", ConchainSpecialInfoupdate, this);
+	Console()->Chain("player_color_feet", ConchainSpecialInfoupdate, this);
+	Console()->Chain("player_skin", ConchainSpecialInfoupdate, this);
 	
 	//
-	suppress_events = false;
+	m_SuppressEvents = false;
 }
 
-void GAMECLIENT::on_init()
+void CGameClient::OnInit()
 {
-	// set the language
-	localization.load(config.cl_languagefile);
+	//m_pServerBrowser = Kernel()->RequestInterface<IServerBrowser>();
 	
-	// propagate pointers
-	m_UI.SetGraphics(Graphics());
-	m_RenderTools.m_pGraphics = Graphics();
-	m_RenderTools.m_pUI = UI();
-	for(int i = 0; i < all.num; i++)
-		all.components[i]->client = this;
+	// set the language
+	g_Localization.Load(g_Config.m_ClLanguagefile);
 	
 	// init all components
-	for(int i = 0; i < all.num; i++)
-		all.components[i]->on_init();
+	for(int i = 0; i < m_All.m_Num; i++)
+		m_All.m_paComponents[i]->OnInit();
 	
 	// setup item sizes
 	for(int i = 0; i < NUM_NETOBJTYPES; i++)
-		snap_set_staticsize(i, netobj_get_size(i));
+		Client()->SnapSetStaticsize(i, m_NetObjHandler.GetObjSize(i));
 	
-	int64 start = time_get();
+	int64 Start = time_get();
 	
 	// load default font	
-	static FONT *default_font;
+	static CFont *pDefaultFont;
 	//default_font = gfx_font_load("data/fonts/sazanami-gothic.ttf");
-	default_font = gfx_font_load("data/fonts/vera.ttf");
-	gfx_text_set_default_font(default_font);
+	pDefaultFont = TextRender()->LoadFont("data/fonts/vera.ttf");
+	TextRender()->SetDefaultFont(pDefaultFont);
 
-	config.cl_threadsoundloading = 0;
+	g_Config.m_ClThreadsoundloading = 0;
 
 	// setup load amount
-	load_total = data->num_images;
-	load_current = 0;
-	if(!config.cl_threadsoundloading)
-		load_total += data->num_sounds;
+	gs_LoadTotal = g_pData->m_NumImages;
+	gs_LoadCurrent = 0;
+	if(!g_Config.m_ClThreadsoundloading)
+		gs_LoadTotal += g_pData->m_NumSounds;
 	
 	// load textures
-	for(int i = 0; i < data->num_images; i++)
+	for(int i = 0; i < g_pData->m_NumImages; i++)
 	{
-		gameclient.menus->render_loading(load_current/load_total);
-		data->images[i].id = Graphics()->LoadTexture(data->images[i].filename, IMG_AUTO, 0);
-		load_current++;
+		g_GameClient.m_pMenus->RenderLoading(gs_LoadCurrent/gs_LoadTotal);
+		g_pData->m_aImages[i].m_Id = Graphics()->LoadTexture(g_pData->m_aImages[i].m_pFilename, CImageInfo::FORMAT_AUTO, 0);
+		gs_LoadCurrent++;
 	}
 
-	::skins.init();
+	::gs_Skins.Init();
+	
 	
-	if(config.cl_threadsoundloading)
+	// TODO: Refactor: fix threaded loading of sounds again
+	// load sounds
+	{
+		bool DoRender = true;
+		for(int s = 0; s < g_pData->m_NumSounds; s++)
+		{
+			if(DoRender)
+				g_GameClient.m_pMenus->RenderLoading(gs_LoadCurrent/(float)gs_LoadTotal);
+			for(int i = 0; i < g_pData->m_aSounds[s].m_NumSounds; i++)
+			{
+				int id = Sound()->LoadWV(g_pData->m_aSounds[s].m_aSounds[i].m_pFilename);
+				g_pData->m_aSounds[s].m_aSounds[i].m_Id = id;
+			}
+
+			if(DoRender)
+				gs_LoadCurrent++;
+		}
+	}
+		
+	/*if(config.cl_threadsoundloading)
 		thread_create(load_sounds_thread, 0);
 	else
-		load_sounds_thread((void*)1);
+		load_sounds_thread((void*)1);*/
 
-	for(int i = 0; i < all.num; i++)
-		all.components[i]->on_reset();
+	for(int i = 0; i < m_All.m_Num; i++)
+		m_All.m_paComponents[i]->OnReset();
 	
-	int64 end = time_get();
-	dbg_msg("", "%f.2ms", ((end-start)*1000)/(float)time_freq());
+	int64 End = time_get();
+	dbg_msg("", "%f.2ms", ((End-Start)*1000)/(float)time_freq());
 	
-	servermode = SERVERMODE_PURE;
+	m_ServerMode = SERVERMODE_PURE;
 }
 
-void GAMECLIENT::on_save()
-{
-	for(int i = 0; i < all.num; i++)
-		all.components[i]->on_save();
-}
-
-void GAMECLIENT::dispatch_input()
+void CGameClient::DispatchInput()
 {
 	// handle mouse movement
 	int x=0, y=0;
-	inp_mouse_relative(&x, &y);
+	Input()->MouseRelative(&x, &y);
 	if(x || y)
 	{
-		for(int h = 0; h < input.num; h++)
+		for(int h = 0; h < m_Input.m_Num; h++)
 		{
-			if(input.components[h]->on_mousemove(x, y))
+			if(m_Input.m_paComponents[h]->OnMouseMove(x, y))
 				break;
 		}
 	}
 	
 	// handle key presses
-	for(int i = 0; i < inp_num_events(); i++)
+	for(int i = 0; i < Input()->NumEvents(); i++)
 	{
-		INPUT_EVENT e = inp_get_event(i);
+		IInput::CEvent e = Input()->GetEvent(i);
 		
-		for(int h = 0; h < input.num; h++)
+		for(int h = 0; h < m_Input.m_Num; h++)
 		{
-			if(input.components[h]->on_input(e))
+			if(m_Input.m_paComponents[h]->OnInput(e))
 			{
 				//dbg_msg("", "%d char=%d key=%d flags=%d", h, e.ch, e.key, e.flags);
 				break;
@@ -361,102 +327,104 @@ void GAMECLIENT::dispatch_input()
 	}
 	
 	// clear all events for this frame
-	inp_clear_events();	
+	Input()->ClearEvents();	
 }
 
 
-int GAMECLIENT::on_snapinput(int *data)
+int CGameClient::OnSnapInput(int *pData)
 {
-	return controls->snapinput(data);
+	return m_pControls->SnapInput(pData);
 }
 
-void GAMECLIENT::on_connected()
+void CGameClient::OnConnected()
 {
-	layers_init();
-	col_init();
-	RenderTools()->render_tilemap_generate_skip();
+	m_Layers.Init(Kernel());
+	m_Collision.Init(Layers());
+	
+	RenderTools()->RenderTilemapGenerateSkip(Layers());
 
-	for(int i = 0; i < all.num; i++)
+	for(int i = 0; i < m_All.m_Num; i++)
 	{
-		all.components[i]->on_mapload();
-		all.components[i]->on_reset();
+		m_All.m_paComponents[i]->OnMapLoad();
+		m_All.m_paComponents[i]->OnReset();
 	}
 	
-	SERVER_INFO current_server_info;
-	client_serverinfo(&current_server_info);
+	CServerInfo CurrentServerInfo;
+	Client()->GetServerInfo(&CurrentServerInfo);
 	
-	servermode = SERVERMODE_PURE;
+	m_ServerMode = SERVERMODE_PURE;
+	m_LastSendInfo = 0;
 	
 	// send the inital info
-	send_info(true);
+	SendInfo(true);
 }
 
-void GAMECLIENT::on_reset()
+void CGameClient::OnReset()
 {
 	// clear out the invalid pointers
-	last_new_predicted_tick = -1;
-	mem_zero(&gameclient.snap, sizeof(gameclient.snap));
+	m_LastNewPredictedTick = -1;
+	mem_zero(&g_GameClient.m_Snap, sizeof(g_GameClient.m_Snap));
 
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
-		clients[i].name[0] = 0;
-		clients[i].skin_id = 0;
-		clients[i].team = 0;
-		clients[i].angle = 0;
-		clients[i].emoticon = 0;
-		clients[i].emoticon_start = -1;
-		clients[i].skin_info.texture = gameclient.skins->get(0)->color_texture;
-		clients[i].skin_info.color_body = vec4(1,1,1,1);
-		clients[i].skin_info.color_feet = vec4(1,1,1,1);
-		clients[i].update_render_info();
+		m_aClients[i].m_aName[0] = 0;
+		m_aClients[i].m_SkinId = 0;
+		m_aClients[i].m_Team = 0;
+		m_aClients[i].m_Angle = 0;
+		m_aClients[i].m_Emoticon = 0;
+		m_aClients[i].m_EmoticonStart = -1;
+		m_aClients[i].m_SkinInfo.m_Texture = g_GameClient.m_pSkins->Get(0)->m_ColorTexture;
+		m_aClients[i].m_SkinInfo.m_ColorBody = vec4(1,1,1,1);
+		m_aClients[i].m_SkinInfo.m_ColorFeet = vec4(1,1,1,1);
+		m_aClients[i].UpdateRenderInfo();
 	}
 	
-	for(int i = 0; i < all.num; i++)
-		all.components[i]->on_reset();
+	for(int i = 0; i < m_All.m_Num; i++)
+		m_All.m_paComponents[i]->OnReset();
 }
 
 
-void GAMECLIENT::update_local_character_pos()
+void CGameClient::UpdateLocalCharacterPos()
 {
-	if(config.cl_predict && client_state() != CLIENTSTATE_DEMOPLAYBACK)
+	if(g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK)
 	{
-		if(!snap.local_character || (snap.local_character->health < 0) || (snap.gameobj && snap.gameobj->game_over))
+		if(!m_Snap.m_pLocalCharacter || (m_Snap.m_pLocalCharacter->m_Health < 0) || (m_Snap.m_pGameobj && m_Snap.m_pGameobj->m_GameOver))
 		{
 			// don't use predicted
 		}
 		else
-			local_character_pos = mix(predicted_prev_char.pos, predicted_char.pos, client_predintratick());
+			m_LocalCharacterPos = mix(m_PredictedPrevChar.m_Pos, m_PredictedChar.m_Pos, Client()->PredIntraGameTick());
 	}
-	else if(snap.local_character && snap.local_prev_character)
+	else if(m_Snap.m_pLocalCharacter && m_Snap.m_pLocalPrevCharacter)
 	{
-		local_character_pos = mix(
-			vec2(snap.local_prev_character->x, snap.local_prev_character->y),
-			vec2(snap.local_character->x, snap.local_character->y), client_intratick());
+		m_LocalCharacterPos = mix(
+			vec2(m_Snap.m_pLocalPrevCharacter->m_X, m_Snap.m_pLocalPrevCharacter->m_Y),
+			vec2(m_Snap.m_pLocalCharacter->m_X, m_Snap.m_pLocalCharacter->m_Y), Client()->IntraGameTick());
 	}
 }
 
 
-static void evolve(NETOBJ_CHARACTER *character, int tick)
+static void Evolve(CNetObj_Character *pCharacter, int Tick)
 {
-	WORLD_CORE tempworld;
-	CHARACTER_CORE tempcore;
-	mem_zero(&tempcore, sizeof(tempcore));
-	tempcore.world = &tempworld;
-	tempcore.read(character);
+	CWorldCore TempWorld;
+	CCharacterCore TempCore;
+	mem_zero(&TempCore, sizeof(TempCore));
+	TempCore.Init(&TempWorld, g_GameClient.Collision());
+	TempCore.Read(pCharacter);
 	
-	while(character->tick < tick)
+	while(pCharacter->m_Tick < Tick)
 	{
-		character->tick++;
-		tempcore.tick(false);
-		tempcore.move();
-		tempcore.quantize();
+		pCharacter->m_Tick++;
+		TempCore.Tick(false);
+		TempCore.Move();
+		TempCore.Quantize();
 	}
 
-	tempcore.write(character);
+	TempCore.Write(pCharacter);
 }
 
 
-void GAMECLIENT::on_render()
+void CGameClient::OnRender()
 {
 	/*Graphics()->Clear(1,0,0);
 	
@@ -474,25 +442,41 @@ void GAMECLIENT::on_render()
 	return;*/
 	
 	// update the local character position
-	update_local_character_pos();
+	UpdateLocalCharacterPos();
 	
 	// dispatch all input to systems
-	dispatch_input();
+	DispatchInput();
 	
 	// render all systems
-	for(int i = 0; i < all.num; i++)
-		all.components[i]->on_render();
+	for(int i = 0; i < m_All.m_Num; i++)
+		m_All.m_paComponents[i]->OnRender();
 		
 	// clear new tick flags
-	new_tick = false;
-	new_predicted_tick = false;
+	m_NewTick = false;
+	m_NewPredictedTick = false;
+
+	// check if client info has to be resent
+	if(m_LastSendInfo && Client()->State() == IClient::STATE_ONLINE && !m_pMenus->IsActive() && m_LastSendInfo+time_freq()*5 < time_get())
+	{
+		// resend if client info differs
+		if(str_comp(g_Config.m_PlayerName, m_aClients[m_Snap.m_LocalCid].m_aName) ||
+			str_comp(g_Config.m_PlayerSkin, m_aClients[m_Snap.m_LocalCid].m_aSkinName) ||
+			(g_GameClient.m_Snap.m_pGameobj && !(g_GameClient.m_Snap.m_pGameobj->m_Flags&GAMEFLAG_TEAMS) &&	// no teamgame?
+			(g_Config.m_PlayerUseCustomColor != m_aClients[m_Snap.m_LocalCid].m_UseCustomColor ||
+			g_Config.m_PlayerColorBody != m_aClients[m_Snap.m_LocalCid].m_ColorBody ||
+			g_Config.m_PlayerColorFeet != m_aClients[m_Snap.m_LocalCid].m_ColorFeet)))
+		{
+			SendInfo(false);
+		}
+		m_LastSendInfo = 0;
+	}
 }
 
-void GAMECLIENT::on_message(int msgtype)
+void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker)
 {
 	
 	// special messages
-	if(msgtype == NETMSGTYPE_SV_EXTRAPROJECTILE)
+	if(MsgId == NETMSGTYPE_SV_EXTRAPROJECTILE)
 	{
 		/*
 		int num = msg_unpack_int();
@@ -515,497 +499,492 @@ void GAMECLIENT::on_message(int msgtype)
 		
 		return;*/
 	}
-	else if(msgtype == NETMSGTYPE_SV_TUNEPARAMS)
+	else if(MsgId == NETMSGTYPE_SV_TUNEPARAMS)
 	{
 		// unpack the new tuning
-		TUNING_PARAMS new_tuning;
-		int *params = (int *)&new_tuning;
-		for(unsigned i = 0; i < sizeof(TUNING_PARAMS)/sizeof(int); i++)
-			params[i] = msg_unpack_int();
+		CTuningParams NewTuning;
+		int *pParams = (int *)&NewTuning;
+		for(unsigned i = 0; i < sizeof(CTuningParams)/sizeof(int); i++)
+			pParams[i] = pUnpacker->GetInt();
 
 		// check for unpacking errors
-		if(msg_unpack_error())
+		if(pUnpacker->Error())
 			return;
 		
-		servermode = SERVERMODE_PURE;
+		m_ServerMode = SERVERMODE_PURE;
 			
 		// apply new tuning
-		tuning = new_tuning;
+		m_Tuning = NewTuning;
 		return;
 	}
 	
-	void *rawmsg = netmsg_secure_unpack(msgtype);
-	if(!rawmsg)
+	void *pRawMsg = m_NetObjHandler.SecureUnpackMsg(MsgId, pUnpacker);
+	if(!pRawMsg)
 	{
-		dbg_msg("client", "dropped weird message '%s' (%d), failed on '%s'", netmsg_get_name(msgtype), msgtype, netmsg_failed_on());
+		dbg_msg("client", "dropped weird message '%s' (%d), failed on '%s'", m_NetObjHandler.GetMsgName(MsgId), MsgId, m_NetObjHandler.FailedMsgOn());
 		return;
 	}
 
 	// TODO: this should be done smarter
-	for(int i = 0; i < all.num; i++)
-		all.components[i]->on_message(msgtype, rawmsg);
+	for(int i = 0; i < m_All.m_Num; i++)
+		m_All.m_paComponents[i]->OnMessage(MsgId, pRawMsg);
 	
-	if(msgtype == NETMSGTYPE_SV_READYTOENTER)
+	if(MsgId == NETMSGTYPE_SV_READYTOENTER)
 	{
-		client_entergame();
+		Client()->EnterGame();
 	}
-	else if (msgtype == NETMSGTYPE_SV_EMOTICON)
+	else if (MsgId == NETMSGTYPE_SV_EMOTICON)
 	{
-		NETMSG_SV_EMOTICON *msg = (NETMSG_SV_EMOTICON *)rawmsg;
+		CNetMsg_Sv_Emoticon *pMsg = (CNetMsg_Sv_Emoticon *)pRawMsg;
 
 		// apply
-		clients[msg->cid].emoticon = msg->emoticon;
-		clients[msg->cid].emoticon_start = client_tick();
+		m_aClients[pMsg->m_Cid].m_Emoticon = pMsg->m_Emoticon;
+		m_aClients[pMsg->m_Cid].m_EmoticonStart = Client()->GameTick();
 	}
-	else if(msgtype == NETMSGTYPE_SV_SOUNDGLOBAL)
+	else if(MsgId == NETMSGTYPE_SV_SOUNDGLOBAL)
 	{
-		if(suppress_events)
+		if(m_SuppressEvents)
 			return;
 			
-		NETMSG_SV_SOUNDGLOBAL *msg = (NETMSG_SV_SOUNDGLOBAL *)rawmsg;
-		gameclient.sounds->play(SOUNDS::CHN_GLOBAL, msg->soundid, 1.0f, vec2(0,0));
+		CNetMsg_Sv_SoundGlobal *pMsg = (CNetMsg_Sv_SoundGlobal *)pRawMsg;
+		g_GameClient.m_pSounds->Enqueue(pMsg->m_Soundid);
 	}		
 }
 
-void GAMECLIENT::on_statechange(int new_state, int old_state)
+void CGameClient::OnStateChange(int NewState, int OldState)
 {
-	if(demorec_isrecording())
-		demorec_record_stop();
-
-	// reset everything
-	on_reset();
+	// reset everything when not already connected (to keep gathered stuff)
+	if(NewState < IClient::STATE_ONLINE)
+		OnReset();
 	
 	// then change the state
-	for(int i = 0; i < all.num; i++)
-		all.components[i]->on_statechange(new_state, old_state);
+	for(int i = 0; i < m_All.m_Num; i++)
+		m_All.m_paComponents[i]->OnStateChange(NewState, OldState);
 }
 
+void CGameClient::OnShutdown() {}
+void CGameClient::OnEnterGame() {}
 
+void CGameClient::OnRconLine(const char *pLine)
+{
+	m_pGameConsole->PrintLine(1, pLine);
+}
 
-void GAMECLIENT::process_events()
+void CGameClient::ProcessEvents()
 {
-	if(suppress_events)
+	if(m_SuppressEvents)
 		return;
 	
-	int snaptype = SNAP_CURRENT;
-	int num = snap_num_items(snaptype);
-	for(int index = 0; index < num; index++)
+	int SnapType = IClient::SNAP_CURRENT;
+	int Num = Client()->SnapNumItems(SnapType);
+	for(int Index = 0; Index < Num; Index++)
 	{
-		SNAP_ITEM item;
-		const void *data = snap_get_item(snaptype, index, &item);
+		IClient::CSnapItem Item;
+		const void *pData = Client()->SnapGetItem(SnapType, Index, &Item);
 
-		if(item.type == NETEVENTTYPE_DAMAGEIND)
+		if(Item.m_Type == NETEVENTTYPE_DAMAGEIND)
 		{
-			NETEVENT_DAMAGEIND *ev = (NETEVENT_DAMAGEIND *)data;
-			gameclient.effects->damage_indicator(vec2(ev->x, ev->y), get_direction(ev->angle));
+			NETEVENT_DAMAGEIND *ev = (NETEVENT_DAMAGEIND *)pData;
+			g_GameClient.m_pEffects->DamageIndicator(vec2(ev->m_X, ev->m_Y), GetDirection(ev->m_Angle));
 		}
-		else if(item.type == NETEVENTTYPE_EXPLOSION)
+		else if(Item.m_Type == NETEVENTTYPE_EXPLOSION)
 		{
-			NETEVENT_EXPLOSION *ev = (NETEVENT_EXPLOSION *)data;
-			gameclient.effects->explosion(vec2(ev->x, ev->y));
+			NETEVENT_EXPLOSION *ev = (NETEVENT_EXPLOSION *)pData;
+			g_GameClient.m_pEffects->Explosion(vec2(ev->m_X, ev->m_Y));
 		}
-		else if(item.type == NETEVENTTYPE_HAMMERHIT)
+		else if(Item.m_Type == NETEVENTTYPE_HAMMERHIT)
 		{
-			NETEVENT_HAMMERHIT *ev = (NETEVENT_HAMMERHIT *)data;
-			gameclient.effects->hammerhit(vec2(ev->x, ev->y));
+			NETEVENT_HAMMERHIT *ev = (NETEVENT_HAMMERHIT *)pData;
+			g_GameClient.m_pEffects->HammerHit(vec2(ev->m_X, ev->m_Y));
 		}
-		else if(item.type == NETEVENTTYPE_SPAWN)
+		else if(Item.m_Type == NETEVENTTYPE_SPAWN)
 		{
-			NETEVENT_SPAWN *ev = (NETEVENT_SPAWN *)data;
-			gameclient.effects->playerspawn(vec2(ev->x, ev->y));
+			NETEVENT_SPAWN *ev = (NETEVENT_SPAWN *)pData;
+			g_GameClient.m_pEffects->PlayerSpawn(vec2(ev->m_X, ev->m_Y));
 		}
-		else if(item.type == NETEVENTTYPE_DEATH)
+		else if(Item.m_Type == NETEVENTTYPE_DEATH)
 		{
-			NETEVENT_DEATH *ev = (NETEVENT_DEATH *)data;
-			gameclient.effects->playerdeath(vec2(ev->x, ev->y), ev->cid);
+			NETEVENT_DEATH *ev = (NETEVENT_DEATH *)pData;
+			g_GameClient.m_pEffects->PlayerDeath(vec2(ev->m_X, ev->m_Y), ev->m_ClientId);
 		}
-		else if(item.type == NETEVENTTYPE_SOUNDWORLD)
+		else if(Item.m_Type == NETEVENTTYPE_SOUNDWORLD)
 		{
-			NETEVENT_SOUNDWORLD *ev = (NETEVENT_SOUNDWORLD *)data;
-			gameclient.sounds->play(SOUNDS::CHN_WORLD, ev->soundid, 1.0f, vec2(ev->x, ev->y));
+			NETEVENT_SOUNDWORLD *ev = (NETEVENT_SOUNDWORLD *)pData;
+			g_GameClient.m_pSounds->Play(CSounds::CHN_WORLD, ev->m_SoundId, 1.0f, vec2(ev->m_X, ev->m_Y));
 		}
 	}
 }
 
-void GAMECLIENT::on_snapshot()
+void CGameClient::OnNewSnapshot()
 {
-	new_tick = true;
+	m_NewTick = true;
 	
 	// clear out the invalid pointers
-	mem_zero(&gameclient.snap, sizeof(gameclient.snap));
-	snap.local_cid = -1;
+	mem_zero(&g_GameClient.m_Snap, sizeof(g_GameClient.m_Snap));
+	m_Snap.m_LocalCid = -1;
 
 	// secure snapshot
 	{
-		int num = snap_num_items(SNAP_CURRENT);
-		for(int index = 0; index < num; index++)
+		int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT);
+		for(int Index = 0; Index < Num; Index++)
 		{
-			SNAP_ITEM item;
-			void *data = snap_get_item(SNAP_CURRENT, index, &item);
-			if(netobj_validate(item.type, data, item.datasize) != 0)
+			IClient::CSnapItem Item;
+			void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, Index, &Item);
+			if(m_NetObjHandler.ValidateObj(Item.m_Type, pData, Item.m_DataSize) != 0)
 			{
-				if(config.debug)
-					dbg_msg("game", "invalidated index=%d type=%d (%s) size=%d id=%d", index, item.type, netobj_get_name(item.type), item.datasize, item.id);
-				snap_invalidate_item(SNAP_CURRENT, index);
+				if(g_Config.m_Debug)
+					dbg_msg("game", "invalidated index=%d type=%d (%s) size=%d id=%d", Index, Item.m_Type, m_NetObjHandler.GetObjName(Item.m_Type), Item.m_DataSize, Item.m_Id);
+				Client()->SnapInvalidateItem(IClient::SNAP_CURRENT, Index);
 			}
 		}
 	}
 		
-	process_events();
+	ProcessEvents();
 
-	if(config.dbg_stress)
+	if(g_Config.m_DbgStress)
 	{
-		if((client_tick()%100) == 0)
+		if((Client()->GameTick()%100) == 0)
 		{
-			char message[64];
-			int msglen = rand()%(sizeof(message)-1);
-			for(int i = 0; i < msglen; i++)
-				message[i] = 'a'+(rand()%('z'-'a'));
-			message[msglen] = 0;
+			char aMessage[64];
+			int MsgLen = rand()%(sizeof(aMessage)-1);
+			for(int i = 0; i < MsgLen; i++)
+				aMessage[i] = 'a'+(rand()%('z'-'a'));
+			aMessage[MsgLen] = 0;
 				
-			NETMSG_CL_SAY msg;
-			msg.team = rand()&1;
-			msg.message = message;
-			msg.pack(MSGFLAG_VITAL);
-			client_send_msg();
+			CNetMsg_Cl_Say Msg;
+			Msg.m_Team = rand()&1;
+			Msg.m_pMessage = aMessage;
+			Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
 		}
 	}
 
 	// go trough all the items in the snapshot and gather the info we want
 	{
-		snap.team_size[0] = snap.team_size[1] = 0;
+		m_Snap.m_aTeamSize[0] = m_Snap.m_aTeamSize[1] = 0;
 		
-		int num = snap_num_items(SNAP_CURRENT);
-		for(int i = 0; i < num; i++)
+		int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT);
+		for(int i = 0; i < Num; i++)
 		{
-			SNAP_ITEM item;
-			const void *data = snap_get_item(SNAP_CURRENT, i, &item);
+			IClient::CSnapItem Item;
+			const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item);
 
-			if(item.type == NETOBJTYPE_CLIENT_INFO)
+			if(Item.m_Type == NETOBJTYPE_CLIENTINFO)
 			{
-				const NETOBJ_CLIENT_INFO *info = (const NETOBJ_CLIENT_INFO *)data;
-				int cid = item.id;
-				ints_to_str(&info->name0, 6, clients[cid].name);
-				ints_to_str(&info->skin0, 6, clients[cid].skin_name);
+				const CNetObj_ClientInfo *pInfo = (const CNetObj_ClientInfo *)pData;
+				int Cid = Item.m_Id;
+				IntsToStr(&pInfo->m_Name0, 6, m_aClients[Cid].m_aName);
+				IntsToStr(&pInfo->m_Skin0, 6, m_aClients[Cid].m_aSkinName);
 				
-				clients[cid].use_custom_color = info->use_custom_color;
-				clients[cid].color_body = info->color_body;
-				clients[cid].color_feet = info->color_feet;
+				m_aClients[Cid].m_UseCustomColor = pInfo->m_UseCustomColor;
+				m_aClients[Cid].m_ColorBody = pInfo->m_ColorBody;
+				m_aClients[Cid].m_ColorFeet = pInfo->m_ColorFeet;
 				
 				// prepare the info
-				if(clients[cid].skin_name[0] == 'x' || clients[cid].skin_name[1] == '_')
-					str_copy(clients[cid].skin_name, "default", 64);
+				if(m_aClients[Cid].m_aSkinName[0] == 'x' || m_aClients[Cid].m_aSkinName[1] == '_')
+					str_copy(m_aClients[Cid].m_aSkinName, "default", 64);
 					
-				clients[cid].skin_info.color_body = skins->get_color(clients[cid].color_body);
-				clients[cid].skin_info.color_feet = skins->get_color(clients[cid].color_feet);
-				clients[cid].skin_info.size = 64;
+				m_aClients[Cid].m_SkinInfo.m_ColorBody = m_pSkins->GetColor(m_aClients[Cid].m_ColorBody);
+				m_aClients[Cid].m_SkinInfo.m_ColorFeet = m_pSkins->GetColor(m_aClients[Cid].m_ColorFeet);
+				m_aClients[Cid].m_SkinInfo.m_Size = 64;
 				
 				// find new skin
-				clients[cid].skin_id = gameclient.skins->find(clients[cid].skin_name);
-				if(clients[cid].skin_id < 0)
+				m_aClients[Cid].m_SkinId = g_GameClient.m_pSkins->Find(m_aClients[Cid].m_aSkinName);
+				if(m_aClients[Cid].m_SkinId < 0)
 				{
-					clients[cid].skin_id = gameclient.skins->find("default");
-					if(clients[cid].skin_id < 0)
-						clients[cid].skin_id = 0;
+					m_aClients[Cid].m_SkinId = g_GameClient.m_pSkins->Find("default");
+					if(m_aClients[Cid].m_SkinId < 0)
+						m_aClients[Cid].m_SkinId = 0;
 				}
 				
-				if(clients[cid].use_custom_color)
-					clients[cid].skin_info.texture = gameclient.skins->get(clients[cid].skin_id)->color_texture;
+				if(m_aClients[Cid].m_UseCustomColor)
+					m_aClients[Cid].m_SkinInfo.m_Texture = g_GameClient.m_pSkins->Get(m_aClients[Cid].m_SkinId)->m_ColorTexture;
 				else
 				{
-					clients[cid].skin_info.texture = gameclient.skins->get(clients[cid].skin_id)->org_texture;
-					clients[cid].skin_info.color_body = vec4(1,1,1,1);
-					clients[cid].skin_info.color_feet = vec4(1,1,1,1);
+					m_aClients[Cid].m_SkinInfo.m_Texture = g_GameClient.m_pSkins->Get(m_aClients[Cid].m_SkinId)->m_OrgTexture;
+					m_aClients[Cid].m_SkinInfo.m_ColorBody = vec4(1,1,1,1);
+					m_aClients[Cid].m_SkinInfo.m_ColorFeet = vec4(1,1,1,1);
 				}
 
-				clients[cid].update_render_info();
-				gameclient.snap.num_players++;
+				m_aClients[Cid].UpdateRenderInfo();
+				g_GameClient.m_Snap.m_NumPlayers++;
 				
 			}
-			else if(item.type == NETOBJTYPE_PLAYER_INFO)
+			else if(Item.m_Type == NETOBJTYPE_PLAYERINFO)
 			{
-				const NETOBJ_PLAYER_INFO *info = (const NETOBJ_PLAYER_INFO *)data;
+				const CNetObj_PlayerInfo *pInfo = (const CNetObj_PlayerInfo *)pData;
 				
-				clients[info->cid].team = info->team;
-				snap.player_infos[info->cid] = info;
+				m_aClients[pInfo->m_ClientId].m_Team = pInfo->m_Team;
+				m_Snap.m_paPlayerInfos[pInfo->m_ClientId] = pInfo;
 				
-				if(info->local)
+				if(pInfo->m_Local)
 				{
-					snap.local_cid = item.id;
-					snap.local_info = info;
+					m_Snap.m_LocalCid = Item.m_Id;
+					m_Snap.m_pLocalInfo = pInfo;
 					
-					if (info->team == -1)
-						snap.spectate = true;
+					if (pInfo->m_Team == -1)
+						m_Snap.m_Spectate = true;
 				}
 				
 				// calculate team-balance
-				if(info->team != -1)
-					snap.team_size[info->team]++;
+				if(pInfo->m_Team != -1)
+					m_Snap.m_aTeamSize[pInfo->m_Team]++;
 				
 			}
-			else if(item.type == NETOBJTYPE_CHARACTER)
+			else if(Item.m_Type == NETOBJTYPE_CHARACTER)
 			{
-				const void *old = snap_find_item(SNAP_PREV, NETOBJTYPE_CHARACTER, item.id);
-				if(old)
+				const void *pOld = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_CHARACTER, Item.m_Id);
+				if(pOld)
 				{
-					snap.characters[item.id].active = true;
-					snap.characters[item.id].prev = *((const NETOBJ_CHARACTER *)old);
-					snap.characters[item.id].cur = *((const NETOBJ_CHARACTER *)data);
-
-					if(snap.characters[item.id].prev.tick)
-						evolve(&snap.characters[item.id].prev, client_prevtick());
-					if(snap.characters[item.id].cur.tick)
-						evolve(&snap.characters[item.id].cur, client_tick());
+					m_Snap.m_aCharacters[Item.m_Id].m_Active = true;
+					m_Snap.m_aCharacters[Item.m_Id].m_Prev = *((const CNetObj_Character *)pOld);
+					m_Snap.m_aCharacters[Item.m_Id].m_Cur = *((const CNetObj_Character *)pData);
+
+					if(m_Snap.m_aCharacters[Item.m_Id].m_Prev.m_Tick)
+						Evolve(&m_Snap.m_aCharacters[Item.m_Id].m_Prev, Client()->PrevGameTick());
+					if(m_Snap.m_aCharacters[Item.m_Id].m_Cur.m_Tick)
+						Evolve(&m_Snap.m_aCharacters[Item.m_Id].m_Cur, Client()->GameTick());
 				}
 			}
-			else if(item.type == NETOBJTYPE_GAME)
-				snap.gameobj = (NETOBJ_GAME *)data;
-			else if(item.type == NETOBJTYPE_FLAG)
-				snap.flags[item.id%2] = (const NETOBJ_FLAG *)data;
+			else if(Item.m_Type == NETOBJTYPE_GAME)
+				m_Snap.m_pGameobj = (CNetObj_Game *)pData;
+			else if(Item.m_Type == NETOBJTYPE_FLAG)
+				m_Snap.m_paFlags[Item.m_Id%2] = (const CNetObj_Flag *)pData;
 		}
 	}
 	
 	// setup local pointers
-	if(snap.local_cid >= 0)
+	if(m_Snap.m_LocalCid >= 0)
 	{
-		SNAPSTATE::CHARACTERINFO *c = &snap.characters[snap.local_cid];
-		if(c->active)
+		CSnapState::CCharacterInfo *c = &m_Snap.m_aCharacters[m_Snap.m_LocalCid];
+		if(c->m_Active)
 		{
-			snap.local_character = &c->cur;
-			snap.local_prev_character = &c->prev;
-			local_character_pos = vec2(snap.local_character->x, snap.local_character->y);
+			m_Snap.m_pLocalCharacter = &c->m_Cur;
+			m_Snap.m_pLocalPrevCharacter = &c->m_Prev;
+			m_LocalCharacterPos = vec2(m_Snap.m_pLocalCharacter->m_X, m_Snap.m_pLocalCharacter->m_Y);
 		}
 	}
 	else
-		snap.spectate = true;
+		m_Snap.m_Spectate = true;
 	
-	TUNING_PARAMS standard_tuning;
-	SERVER_INFO current_server_info;
-	client_serverinfo(&current_server_info);
-	if(current_server_info.gametype[0] != '0')
+	CTuningParams StandardTuning;
+	CServerInfo CurrentServerInfo;
+	Client()->GetServerInfo(&CurrentServerInfo);
+	if(CurrentServerInfo.m_aGameType[0] != '0')
 	{
-		if(strcmp(current_server_info.gametype, "DM") != 0 && strcmp(current_server_info.gametype, "TDM") != 0 && strcmp(current_server_info.gametype, "CTF") != 0)
-			servermode = SERVERMODE_MOD;
-		else if(memcmp(&standard_tuning, &tuning, sizeof(TUNING_PARAMS)) == 0)
-			servermode = SERVERMODE_PURE;
+		if(str_comp(CurrentServerInfo.m_aGameType, "DM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "TDM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "CTF") != 0)
+			m_ServerMode = SERVERMODE_MOD;
+		else if(mem_comp(&StandardTuning, &m_Tuning, sizeof(CTuningParams)) == 0)
+			m_ServerMode = SERVERMODE_PURE;
 		else
-			servermode = SERVERMODE_PUREMOD;
+			m_ServerMode = SERVERMODE_PUREMOD;
 	}
 	
 
 	// update render info
 	for(int i = 0; i < MAX_CLIENTS; i++)
-		clients[i].update_render_info();
+		m_aClients[i].UpdateRenderInfo();
 }
 
-void GAMECLIENT::on_predict()
+void CGameClient::OnPredict()
 {
 	// store the previous values so we can detect prediction errors
-	CHARACTER_CORE before_prev_char = predicted_prev_char;
-	CHARACTER_CORE before_char = predicted_char;
+	CCharacterCore BeforePrevChar = m_PredictedPrevChar;
+	CCharacterCore BeforeChar = m_PredictedChar;
 
 	// we can't predict without our own id or own character
-	if(snap.local_cid == -1 || !snap.characters[snap.local_cid].active)
+	if(m_Snap.m_LocalCid == -1 || !m_Snap.m_aCharacters[m_Snap.m_LocalCid].m_Active)
 		return;
 	
 	// don't predict anything if we are paused
-	if(snap.gameobj && snap.gameobj->paused)
+	if(m_Snap.m_pGameobj && m_Snap.m_pGameobj->m_Paused)
 	{
-		if(snap.local_character)
-			predicted_char.read(snap.local_character);
-		if(snap.local_prev_character)
-			predicted_prev_char.read(snap.local_prev_character);
+		if(m_Snap.m_pLocalCharacter)
+			m_PredictedChar.Read(m_Snap.m_pLocalCharacter);
+		if(m_Snap.m_pLocalPrevCharacter)
+			m_PredictedPrevChar.Read(m_Snap.m_pLocalPrevCharacter);
 		return;
 	}
 
 	// repredict character
-	WORLD_CORE world;
-	world.tuning = tuning;
+	CWorldCore World;
+	World.m_Tuning = m_Tuning;
 
 	// search for players
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
-		if(!snap.characters[i].active)
+		if(!m_Snap.m_aCharacters[i].m_Active)
 			continue;
 			
-		gameclient.clients[i].predicted.world = &world;
-		world.characters[i] = &gameclient.clients[i].predicted;
-		gameclient.clients[i].predicted.read(&snap.characters[i].cur);
+		g_GameClient.m_aClients[i].m_Predicted.Init(&World, Collision());
+		World.m_apCharacters[i] = &g_GameClient.m_aClients[i].m_Predicted;
+		g_GameClient.m_aClients[i].m_Predicted.Read(&m_Snap.m_aCharacters[i].m_Cur);
 	}
 	
 	// predict
-	for(int tick = client_tick()+1; tick <= client_predtick(); tick++)
+	for(int Tick = Client()->GameTick()+1; Tick <= Client()->PredGameTick(); Tick++)
 	{
 		// fetch the local
-		if(tick == client_predtick() && world.characters[snap.local_cid])
-			predicted_prev_char = *world.characters[snap.local_cid];
+		if(Tick == Client()->PredGameTick() && World.m_apCharacters[m_Snap.m_LocalCid])
+			m_PredictedPrevChar = *World.m_apCharacters[m_Snap.m_LocalCid];
 		
 		// first calculate where everyone should move
 		for(int c = 0; c < MAX_CLIENTS; c++)
 		{
-			if(!world.characters[c])
+			if(!World.m_apCharacters[c])
 				continue;
 
-			mem_zero(&world.characters[c]->input, sizeof(world.characters[c]->input));
-			if(snap.local_cid == c)
+			mem_zero(&World.m_apCharacters[c]->m_Input, sizeof(World.m_apCharacters[c]->m_Input));
+			if(m_Snap.m_LocalCid == c)
 			{
 				// apply player input
-				int *input = client_get_input(tick);
-				if(input)
-					world.characters[c]->input = *((NETOBJ_PLAYER_INPUT*)input);
-				world.characters[c]->tick(true);
+				int *pInput = Client()->GetInput(Tick);
+				if(pInput)
+					World.m_apCharacters[c]->m_Input = *((CNetObj_PlayerInput*)pInput);
+				World.m_apCharacters[c]->Tick(true);
 			}
 			else
-				world.characters[c]->tick(false);
+				World.m_apCharacters[c]->Tick(false);
 
 		}
 
 		// move all players and quantize their data
 		for(int c = 0; c < MAX_CLIENTS; c++)
 		{
-			if(!world.characters[c])
+			if(!World.m_apCharacters[c])
 				continue;
 
-			world.characters[c]->move();
-			world.characters[c]->quantize();
+			World.m_apCharacters[c]->Move();
+			World.m_apCharacters[c]->Quantize();
 		}
 		
 		// check if we want to trigger effects
-		if(tick > last_new_predicted_tick)
+		if(Tick > m_LastNewPredictedTick)
 		{
-			last_new_predicted_tick = tick;
-			new_predicted_tick = true;
+			m_LastNewPredictedTick = Tick;
+			m_NewPredictedTick = true;
 			
-			if(snap.local_cid != -1 && world.characters[snap.local_cid])
+			if(m_Snap.m_LocalCid != -1 && World.m_apCharacters[m_Snap.m_LocalCid])
 			{
-				vec2 pos = world.characters[snap.local_cid]->pos;
-				int events = world.characters[snap.local_cid]->triggered_events;
-				if(events&COREEVENT_GROUND_JUMP) gameclient.sounds->play_and_record(SOUNDS::CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, pos);
+				vec2 Pos = World.m_apCharacters[m_Snap.m_LocalCid]->m_Pos;
+				int Events = World.m_apCharacters[m_Snap.m_LocalCid]->m_TriggeredEvents;
+				if(Events&COREEVENT_GROUND_JUMP) g_GameClient.m_pSounds->PlayAndRecord(CSounds::CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, Pos);
 				
 				/*if(events&COREEVENT_AIR_JUMP)
 				{
-					gameclient.effects->air_jump(pos);
-					gameclient.sounds->play_and_record(SOUNDS::CHN_WORLD, SOUND_PLAYER_AIRJUMP, 1.0f, pos);
+					GameClient.effects->air_jump(pos);
+					GameClient.sounds->play_and_record(SOUNDS::CHN_WORLD, SOUND_PLAYER_AIRJUMP, 1.0f, pos);
 				}*/
 				
 				//if(events&COREEVENT_HOOK_LAUNCH) snd_play_random(CHN_WORLD, SOUND_HOOK_LOOP, 1.0f, pos);
 				//if(events&COREEVENT_HOOK_ATTACH_PLAYER) snd_play_random(CHN_WORLD, SOUND_HOOK_ATTACH_PLAYER, 1.0f, pos);
-				if(events&COREEVENT_HOOK_ATTACH_GROUND) gameclient.sounds->play_and_record(SOUNDS::CHN_WORLD, SOUND_HOOK_ATTACH_GROUND, 1.0f, pos);
-				if(events&COREEVENT_HOOK_HIT_NOHOOK) gameclient.sounds->play_and_record(SOUNDS::CHN_WORLD, SOUND_HOOK_NOATTACH, 1.0f, pos);
+				if(Events&COREEVENT_HOOK_ATTACH_GROUND) g_GameClient.m_pSounds->PlayAndRecord(CSounds::CHN_WORLD, SOUND_HOOK_ATTACH_GROUND, 1.0f, Pos);
+				if(Events&COREEVENT_HOOK_HIT_NOHOOK) g_GameClient.m_pSounds->PlayAndRecord(CSounds::CHN_WORLD, SOUND_HOOK_NOATTACH, 1.0f, Pos);
 				//if(events&COREEVENT_HOOK_RETRACT) snd_play_random(CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, pos);
 			}
 		}
 		
-		if(tick == client_predtick() && world.characters[snap.local_cid])
-			predicted_char = *world.characters[snap.local_cid];
+		if(Tick == Client()->PredGameTick() && World.m_apCharacters[m_Snap.m_LocalCid])
+			m_PredictedChar = *World.m_apCharacters[m_Snap.m_LocalCid];
 	}
 	
-	if(config.debug && config.cl_predict && predicted_tick == client_predtick())
+	if(g_Config.m_Debug && g_Config.m_ClPredict && m_PredictedTick == Client()->PredGameTick())
 	{
-		NETOBJ_CHARACTER_CORE before = {0}, now = {0}, before_prev = {0}, now_prev = {0};
-		before_char.write(&before);
-		before_prev_char.write(&before_prev);
-		predicted_char.write(&now);
-		predicted_prev_char.write(&now_prev);
+		CNetObj_CharacterCore Before = {0}, Now = {0}, BeforePrev = {0}, NowPrev = {0};
+		BeforeChar.Write(&Before);
+		BeforePrevChar.Write(&BeforePrev);
+		m_PredictedChar.Write(&Now);
+		m_PredictedPrevChar.Write(&NowPrev);
 
-		if(mem_comp(&before, &now, sizeof(NETOBJ_CHARACTER_CORE)) != 0)
+		if(mem_comp(&Before, &Now, sizeof(CNetObj_CharacterCore)) != 0)
 		{
 			dbg_msg("client", "prediction error");
-			for(unsigned i = 0; i < sizeof(NETOBJ_CHARACTER_CORE)/sizeof(int); i++)
-				if(((int *)&before)[i] != ((int *)&now)[i])
+			for(unsigned i = 0; i < sizeof(CNetObj_CharacterCore)/sizeof(int); i++)
+				if(((int *)&Before)[i] != ((int *)&Now)[i])
 				{
-					dbg_msg("", "\t%d %d %d  (%d %d)", i, ((int *)&before)[i], ((int *)&now)[i], ((int *)&before_prev)[i], ((int *)&now_prev)[i]);
+					dbg_msg("", "\t%d %d %d  (%d %d)", i, ((int *)&Before)[i], ((int *)&Now)[i], ((int *)&BeforePrev)[i], ((int *)&NowPrev)[i]);
 				}
 		}
 	}
 	
-	predicted_tick = client_predtick();
+	m_PredictedTick = Client()->PredGameTick();
 }
 
-void GAMECLIENT::CLIENT_DATA::update_render_info()
+void CGameClient::CClientData::UpdateRenderInfo()
 {
-	render_info = skin_info;
+	m_RenderInfo = m_SkinInfo;
 
 	// force team colors
-	if(gameclient.snap.gameobj && gameclient.snap.gameobj->flags&GAMEFLAG_TEAMS)
+	if(g_GameClient.m_Snap.m_pGameobj && g_GameClient.m_Snap.m_pGameobj->m_Flags&GAMEFLAG_TEAMS)
 	{
-		const int team_colors[2] = {65387, 10223467};
-		if(team >= 0 || team <= 1)
+		const int TeamColors[2] = {65387, 10223467};
+		if(m_Team >= 0 || m_Team <= 1)
 		{
-			render_info.texture = gameclient.skins->get(skin_id)->color_texture;
-			render_info.color_body = gameclient.skins->get_color(team_colors[team]);
-			render_info.color_feet = gameclient.skins->get_color(team_colors[team]);
+			m_RenderInfo.m_Texture = g_GameClient.m_pSkins->Get(m_SkinId)->m_ColorTexture;
+			m_RenderInfo.m_ColorBody = g_GameClient.m_pSkins->GetColor(TeamColors[m_Team]);
+			m_RenderInfo.m_ColorFeet = g_GameClient.m_pSkins->GetColor(TeamColors[m_Team]);
 		}
 	}		
 }
 
-void GAMECLIENT::send_switch_team(int team)
+void CGameClient::SendSwitchTeam(int Team)
 {
-	NETMSG_CL_SETTEAM msg;
-	msg.team = team;
-	msg.pack(MSGFLAG_VITAL);
-	client_send_msg();	
+	CNetMsg_Cl_SetTeam Msg;
+	Msg.m_Team = Team;
+	Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);	
 }
 
-void GAMECLIENT::send_info(bool start)
+void CGameClient::SendInfo(bool Start)
 {
-	if(start)
+	if(Start)
 	{
-		NETMSG_CL_STARTINFO msg;
-		msg.name = config.player_name;
-		msg.skin = config.player_skin;
-		msg.use_custom_color = config.player_use_custom_color;
-		msg.color_body = config.player_color_body;
-		msg.color_feet = config.player_color_feet;
-		msg.pack(MSGFLAG_VITAL);
+		CNetMsg_Cl_StartInfo Msg;
+		Msg.m_pName = g_Config.m_PlayerName;
+		Msg.m_pSkin = g_Config.m_PlayerSkin;
+		Msg.m_UseCustomColor = g_Config.m_PlayerUseCustomColor;
+		Msg.m_ColorBody = g_Config.m_PlayerColorBody;
+		Msg.m_ColorFeet = g_Config.m_PlayerColorFeet;
+		Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);	
 	}
 	else
 	{
-		NETMSG_CL_CHANGEINFO msg;
-		msg.name = config.player_name;
-		msg.skin = config.player_skin;
-		msg.use_custom_color = config.player_use_custom_color;
-		msg.color_body = config.player_color_body;
-		msg.color_feet = config.player_color_feet;
-		msg.pack(MSGFLAG_VITAL);
+		CNetMsg_Cl_ChangeInfo Msg;
+		Msg.m_pName = g_Config.m_PlayerName;
+		Msg.m_pSkin = g_Config.m_PlayerSkin;
+		Msg.m_UseCustomColor = g_Config.m_PlayerUseCustomColor;
+		Msg.m_ColorBody = g_Config.m_PlayerColorBody;
+		Msg.m_ColorFeet = g_Config.m_PlayerColorFeet;
+		Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
+
+		// activate timer to resend the info if it gets filtered
+		if(!m_LastSendInfo || m_LastSendInfo+time_freq()*5 < time_get())
+			m_LastSendInfo = time_get();
 	}
-	client_send_msg();
 }
 
-void GAMECLIENT::send_kill(int client_id)
+void CGameClient::SendKill(int ClientId)
 {
-	NETMSG_CL_KILL msg;
-	msg.pack(MSGFLAG_VITAL);
-	client_send_msg();
+	CNetMsg_Cl_Kill Msg;
+	Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);	
 }
 
-void GAMECLIENT::con_team(void *result, void *user_data)
+void CGameClient::ConTeam(IConsole::IResult *pResult, void *pUserData)
 {
-	((GAMECLIENT*)user_data)->send_switch_team(console_arg_int(result, 0));
+	((CGameClient*)pUserData)->SendSwitchTeam(pResult->GetInteger(0));
 }
 
-void GAMECLIENT::con_kill(void *result, void *user_data)
+void CGameClient::ConKill(IConsole::IResult *pResult, void *pUserData)
 {
-	((GAMECLIENT*)user_data)->send_kill(-1);
+	((CGameClient*)pUserData)->SendKill(-1);
 }
 
-void GAMECLIENT::conchain_special_infoupdate(void *result, void *user_data, CONSOLE_CALLBACK cb, void *cbuser)
+void CGameClient::ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
 {
-	cb(result, cbuser);
-	if(console_arg_num(result))
-		((GAMECLIENT*)user_data)->send_info(false);
-}
-
-void GAMECLIENT::SetEngine(class IEngine *pEngine)
-{
-	m_pEngine = pEngine;
-	
-	// digg out some pointers
-	m_pGraphics = m_pEngine->Graphics();
+	pfnCallback(pResult, pCallbackUserData);
+	if(pResult->NumArguments())
+		((CGameClient*)pUserData)->SendInfo(false);
 }
 
-IGameClient *CreateGameClient(IEngine *pEngine)
+IGameClient *CreateGameClient()
 {
-	gameclient.SetEngine(pEngine);
-	return &gameclient;
+	return &g_GameClient;
 }
diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h
new file mode 100644
index 00000000..b91b4b50
--- /dev/null
+++ b/src/game/client/gameclient.h
@@ -0,0 +1,208 @@
+#ifndef GAME_CLIENT_GAMECLIENT_H
+#define GAME_CLIENT_GAMECLIENT_H
+
+#include <base/vmath.h>
+#include <engine/client.h>
+#include <engine/console.h>
+#include <game/layers.h>
+#include <game/gamecore.h>
+#include "render.h"
+
+class CGameClient : public IGameClient
+{
+	class CStack
+	{
+	public:
+		enum
+		{
+			MAX_COMPONENTS = 64,
+		};
+	
+		CStack();
+		void Add(class CComponent *pComponent);
+		
+		class CComponent *m_paComponents[MAX_COMPONENTS];
+		int m_Num;
+	};
+	
+	CStack m_All;
+	CStack m_Input;
+	CNetObjHandler m_NetObjHandler;
+	
+	class IInput *m_pInput;
+	class IGraphics *m_pGraphics;
+	class ITextRender *m_pTextRender;
+	class IClient *m_pClient;
+	class ISound *m_pSound;
+	class IConsole *m_pConsole;
+	class IStorage *m_pStorage;
+	class IDemoPlayer *m_pDemoPlayer;
+	class IServerBrowser *m_pServerBrowser;
+	
+	CLayers m_Layers;
+	class CCollision m_Collision;
+	CUI m_UI;
+	
+	void DispatchInput();
+	void ProcessEvents();
+	void UpdateLocalCharacterPos();
+
+	int m_PredictedTick;
+	int m_LastNewPredictedTick;
+
+	int64 m_LastSendInfo;
+
+	static void ConTeam(IConsole::IResult *pResult, void *pUserData);
+	static void ConKill(IConsole::IResult *pResult, void *pUserData);
+	
+	static void ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
+	
+public:
+	IKernel *Kernel() { return IInterface::Kernel(); }
+	class IGraphics *Graphics() const { return m_pGraphics; }
+	class IClient *Client() const { return m_pClient; }
+	class CUI *UI() { return &m_UI; }
+	class ISound *Sound() const { return m_pSound; }
+	class IInput *Input() const { return m_pInput; }
+	class IStorage *Storage() const { return m_pStorage; }
+	class IConsole *Console() { return m_pConsole; }
+	class ITextRender *TextRender() const { return m_pTextRender; }
+	class IDemoPlayer *DemoPlayer() const { return m_pDemoPlayer; }
+	class IServerBrowser *ServerBrowser() const { return m_pServerBrowser; }
+	class CRenderTools *RenderTools() { return &m_RenderTools; }
+	class CLayers *Layers() { return &m_Layers; };
+	class CCollision *Collision() { return &m_Collision; };
+	
+
+	bool m_SuppressEvents;
+	bool m_NewTick;
+	bool m_NewPredictedTick;
+
+	// TODO: move this
+	CTuningParams m_Tuning;
+	
+	enum
+	{
+		SERVERMODE_PURE=0,
+		SERVERMODE_MOD,
+		SERVERMODE_PUREMOD,
+	};
+	int m_ServerMode;
+
+	vec2 m_LocalCharacterPos;
+
+	// predicted players
+	CCharacterCore m_PredictedPrevChar;
+	CCharacterCore m_PredictedChar;
+
+	// snap pointers
+	struct CSnapState
+	{
+		const CNetObj_Character *m_pLocalCharacter;
+		const CNetObj_Character *m_pLocalPrevCharacter;
+		const CNetObj_PlayerInfo *m_pLocalInfo;
+		const CNetObj_Flag *m_paFlags[2];
+		const CNetObj_Game *m_pGameobj;
+
+		const CNetObj_PlayerInfo *m_paPlayerInfos[MAX_CLIENTS];
+		const CNetObj_PlayerInfo *m_paInfoByScore[MAX_CLIENTS];
+		
+		int m_LocalCid;
+		int m_NumPlayers;
+		int m_aTeamSize[2];
+		bool m_Spectate;
+		
+		//
+		struct CCharacterInfo
+		{
+			bool m_Active;
+			
+			// snapshots
+			CNetObj_Character m_Prev;
+			CNetObj_Character m_Cur;
+			
+			// interpolated position
+			vec2 m_Position;
+		};
+		
+		CCharacterInfo m_aCharacters[MAX_CLIENTS];
+	};
+
+	CSnapState m_Snap;
+	
+	// client data
+	struct CClientData
+	{
+		int m_UseCustomColor;
+		int m_ColorBody;
+		int m_ColorFeet;
+		
+		char m_aName[64];
+		char m_aSkinName[64];
+		int m_SkinId;
+		int m_SkinColor;
+		int m_Team;
+		int m_Emoticon;
+		int m_EmoticonStart;
+		CCharacterCore m_Predicted;
+		
+		CTeeRenderInfo m_SkinInfo; // this is what the server reports
+		CTeeRenderInfo m_RenderInfo; // this is what we use
+		
+		float m_Angle;
+		
+		void UpdateRenderInfo();
+	};
+
+	CClientData m_aClients[MAX_CLIENTS];
+	
+	CRenderTools m_RenderTools;
+	
+	void OnReset();
+
+	// hooks
+	virtual void OnConnected();
+	virtual void OnRender();
+	virtual void OnInit();
+	virtual void OnConsoleInit();
+	virtual void OnStateChange(int NewState, int OldState);
+	virtual void OnMessage(int MsgId, CUnpacker *pUnpacker);
+	virtual void OnNewSnapshot();
+	virtual void OnPredict();
+	virtual int OnSnapInput(int *pData);
+	virtual void OnShutdown();
+	virtual void OnEnterGame();
+	virtual void OnRconLine(const char *pLine);
+	
+	virtual const char *GetItemName(int Type);
+	virtual const char *Version();
+	virtual const char *NetVersion();
+	
+	
+	// actions
+	// TODO: move these
+	void SendSwitchTeam(int Team);
+	void SendInfo(bool Start);
+	void SendKill(int ClientId);
+	
+	// pointers to all systems
+	class CGameConsole *m_pGameConsole;
+	class CBinds *m_pBinds;
+	class CParticles *m_pParticles;
+	class CMenus *m_pMenus;
+	class CSkins *m_pSkins;
+	class CFlow *m_pFlow;
+	class CChat *m_pChat;
+	class CDamageInd *m_pDamageind;
+	class CCamera *m_pCamera;
+	class CControls *m_pControls;
+	class CEffects *m_pEffects;
+	class CSounds *m_pSounds;
+	class CMotd *m_pMotd;
+	class CMapImages *m_pMapimages;
+	class CVoting *m_pVoting;
+};
+
+extern const char *Localize(const char *Str);
+
+#endif
diff --git a/src/game/client/gameclient.hpp b/src/game/client/gameclient.hpp
deleted file mode 100644
index 1da40de0..00000000
--- a/src/game/client/gameclient.hpp
+++ /dev/null
@@ -1,181 +0,0 @@
-#ifndef FILE_GAMECLIENT_HPP
-#define FILE_GAMECLIENT_HPP
-
-#include <base/vmath.hpp>
-#include <engine/e_console.h>
-#include <engine/client/client.h>
-#include <game/gamecore.hpp>
-#include "render.hpp"
-
-class GAMECLIENT : public IGameClient
-{
-	class STACK
-	{
-	public:
-		enum
-		{
-			MAX_COMPONENTS = 64,
-		};
-	
-		STACK();
-		void add(class COMPONENT *component);
-		
-		class COMPONENT *components[MAX_COMPONENTS];
-		int num;
-	};
-	
-	STACK all;
-	STACK input;
-	
-	class IGraphics *m_pGraphics;
-	class IEngine *m_pEngine;
-	CUI m_UI;
-	
-	void dispatch_input();
-	void process_events();
-	void update_local_character_pos();
-
-	int predicted_tick;
-	int last_new_predicted_tick;
-
-	static void con_team(void *result, void *user_data);
-	static void con_kill(void *result, void *user_data);
-	
-	static void conchain_special_infoupdate(void *result, void *user_data, CONSOLE_CALLBACK cb, void *cbuser);
-	
-public:
-	class IGraphics *Graphics() const { return m_pGraphics; }
-	class CUI *UI() { return &m_UI; }
-	class CRenderTools *RenderTools() { return &m_RenderTools; }
-	
-	void SetEngine(class IEngine *pEngine);
-
-	bool suppress_events;
-	bool new_tick;
-	bool new_predicted_tick;
-
-	// TODO: move this
-	TUNING_PARAMS tuning;
-	
-	enum
-	{
-		SERVERMODE_PURE=0,
-		SERVERMODE_MOD,
-		SERVERMODE_PUREMOD,
-	};
-	int servermode;
-
-	vec2 local_character_pos;
-
-	// predicted players
-	CHARACTER_CORE predicted_prev_char;
-	CHARACTER_CORE predicted_char;
-
-	// snap pointers
-	struct SNAPSTATE
-	{
-		const NETOBJ_CHARACTER *local_character;
-		const NETOBJ_CHARACTER *local_prev_character;
-		const NETOBJ_PLAYER_INFO *local_info;
-		const NETOBJ_FLAG *flags[2];
-		const NETOBJ_GAME *gameobj;
-
-		const NETOBJ_PLAYER_INFO *player_infos[MAX_CLIENTS];
-		const NETOBJ_PLAYER_INFO *info_by_score[MAX_CLIENTS];
-		
-		int local_cid;
-		int num_players;
-		int team_size[2];
-		bool spectate;
-		
-		//
-		struct CHARACTERINFO
-		{
-			bool active;
-			
-			// snapshots
-			NETOBJ_CHARACTER prev;
-			NETOBJ_CHARACTER cur;
-			
-			// interpolated position
-			vec2 position;
-		};
-		
-		CHARACTERINFO characters[MAX_CLIENTS];
-	};
-
-	SNAPSTATE snap;
-	
-	// client data
-	struct CLIENT_DATA
-	{
-		int use_custom_color;
-		int color_body;
-		int color_feet;
-		
-		char name[64];
-		char skin_name[64];
-		int skin_id;
-		int skin_color;
-		int team;
-		int emoticon;
-		int emoticon_start;
-		CHARACTER_CORE predicted;
-		
-		TEE_RENDER_INFO skin_info; // this is what the server reports
-		TEE_RENDER_INFO render_info; // this is what we use
-		
-		float angle;
-		
-		void update_render_info();
-	};
-
-	CLIENT_DATA clients[MAX_CLIENTS];
-	
-	CRenderTools m_RenderTools;
-	
-	void on_reset();
-
-	// hooks
-	void on_connected();
-	void on_render();
-	void on_init();
-	void on_save();
-	void on_console_init();
-	void on_statechange(int new_state, int old_state);
-	void on_message(int msgtype);
-	void on_snapshot();
-	void on_predict();
-	int on_snapinput(int *data);
-
-	// actions
-	// TODO: move these
-	void send_switch_team(int team);
-	void send_info(bool start);
-	void send_kill(int client_id);
-	
-	// pointers to all systems
-	class CONSOLE *console;
-	class BINDS *binds;
-	class PARTICLES *particles;
-	class MENUS *menus;
-	class SKINS *skins;
-	class FLOW *flow;
-	class CHAT *chat;
-	class DAMAGEIND *damageind;
-	class CAMERA *camera;
-	class CONTROLS *controls;
-	class EFFECTS *effects;
-	class SOUNDS *sounds;
-	class MOTD *motd;
-	class MAPIMAGES *mapimages;
-	class VOTING *voting;
-};
-
-
-// TODO: Refactor: Remove this
-extern GAMECLIENT gameclient;
-
-extern const char *localize(const char *str);
-
-#endif
diff --git a/src/game/client/lineinput.cpp b/src/game/client/lineinput.cpp
index f8c9d7e7..f1159caf 100644
--- a/src/game/client/lineinput.cpp
+++ b/src/game/client/lineinput.cpp
@@ -1,85 +1,90 @@
-#include <engine/e_client_interface.h>
-#include <string.h> // strlen
-#include "lineinput.hpp"
+#include <engine/keys.h>
+#include "lineinput.h"
 
-LINEINPUT::LINEINPUT()
+CLineInput::CLineInput()
 {
-	clear();
+	Clear();
 }
 
-void LINEINPUT::clear()
+void CLineInput::Clear()
 {
-	mem_zero(str, sizeof(str));
-	len = 0;
-	cursor_pos = 0;
+	mem_zero(m_Str, sizeof(m_Str));
+	m_Len = 0;
+	m_CursorPos = 0;
 }
 
-void LINEINPUT::set(const char *string)
+void CLineInput::Set(const char *pString)
 {
-	str_copy(str, string, sizeof(str));
-	len = strlen(str);
-	cursor_pos = len;
+	str_copy(m_Str, pString, sizeof(m_Str));
+	m_Len = str_length(m_Str);
+	m_CursorPos = m_Len;
 }
 
-void LINEINPUT::manipulate(INPUT_EVENT e, char *str, int str_max_size, int *str_len_ptr, int *cursor_pos_ptr)
+bool CLineInput::Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int *pStrLenPtr, int *pCursorPosPtr)
 {
-	int cursor_pos = *cursor_pos_ptr;
-	int len = *str_len_ptr;
+	int CursorPos = *pCursorPosPtr;
+	int Len = *pStrLenPtr;
+	bool Changes = false;
 	
-	if(cursor_pos > len)
-		cursor_pos = len;
+	if(CursorPos > Len)
+		CursorPos = Len;
 	
-	int code = e.unicode;
-	int k = e.key;
+	int Code = e.m_Unicode;
+	int k = e.m_Key;
 	
 	// 127 is produced on Mac OS X and corresponds to the delete key
-	if (!(code >= 0 && code < 32) && code != 127)
+	if (!(Code >= 0 && Code < 32) && Code != 127)
 	{
-		char tmp[8];
-		int charsize = str_utf8_encode(tmp, code);
+		char Tmp[8];
+		int CharSize = str_utf8_encode(Tmp, Code);
 		
-		if (len < str_max_size - charsize && cursor_pos < str_max_size - charsize)
+		if (Len < StrMaxSize - CharSize && CursorPos < StrMaxSize - CharSize)
 		{
-			memmove(str + cursor_pos + charsize, str + cursor_pos, len - cursor_pos + charsize);
-			for(int i = 0; i < charsize; i++)
-				str[cursor_pos+i] = tmp[i];
-			cursor_pos += charsize;
-			len += charsize;
+			mem_move(pStr + CursorPos + CharSize, pStr + CursorPos, Len - CursorPos + CharSize);
+			for(int i = 0; i < CharSize; i++)
+				pStr[CursorPos+i] = Tmp[i];
+			CursorPos += CharSize;
+			Len += CharSize;
+			Changes = true;
 		}
 	}
 	
-	if(e.flags&INPFLAG_PRESS)
+	if(e.m_Flags&IInput::FLAG_PRESS)
 	{
-		if (k == KEY_BACKSPACE && cursor_pos > 0)
+		if (k == KEY_BACKSPACE && CursorPos > 0)
 		{
-			int new_cursor_pos = str_utf8_rewind(str, cursor_pos);
-			int charsize = cursor_pos-new_cursor_pos;
-			memmove(str+new_cursor_pos, str+cursor_pos, len - charsize + 1); // +1 == null term
-			cursor_pos = new_cursor_pos;
-			len -= charsize;
+			int NewCursorPos = str_utf8_rewind(pStr, CursorPos);
+			int CharSize = CursorPos-NewCursorPos;
+			mem_move(pStr+NewCursorPos, pStr+CursorPos, Len - NewCursorPos - CharSize + 1); // +1 == null term
+			CursorPos = NewCursorPos;
+			Len -= CharSize;
+			Changes = true;
 		}
-		else if (k == KEY_DELETE && cursor_pos < len)
+		else if (k == KEY_DELETE && CursorPos < Len)
 		{
-			int p = str_utf8_forward(str, cursor_pos);
-			int charsize = p-cursor_pos;
-			memmove(str + cursor_pos, str + cursor_pos + charsize, len - cursor_pos - charsize + 1); // +1 == null term
-			len -= charsize;
+			int p = str_utf8_forward(pStr, CursorPos);
+			int CharSize = p-CursorPos;
+			mem_move(pStr + CursorPos, pStr + CursorPos + CharSize, Len - CursorPos - CharSize + 1); // +1 == null term
+			Len -= CharSize;
+			Changes = true;
 		}
-		else if (k == KEY_LEFT && cursor_pos > 0)
-			cursor_pos = str_utf8_rewind(str, cursor_pos);
-		else if (k == KEY_RIGHT && cursor_pos < len)
-			cursor_pos = str_utf8_forward(str, cursor_pos);
+		else if (k == KEY_LEFT && CursorPos > 0)
+			CursorPos = str_utf8_rewind(pStr, CursorPos);
+		else if (k == KEY_RIGHT && CursorPos < Len)
+			CursorPos = str_utf8_forward(pStr, CursorPos);
 		else if (k == KEY_HOME)
-			cursor_pos = 0;
+			CursorPos = 0;
 		else if (k == KEY_END)
-			cursor_pos = len;
+			CursorPos = Len;
 	}
 	
-	*cursor_pos_ptr = cursor_pos;
-	*str_len_ptr = len;
+	*pCursorPosPtr = CursorPos;
+	*pStrLenPtr = Len;
+
+	return Changes;
 }
 
-void LINEINPUT::process_input(INPUT_EVENT e)
+void CLineInput::ProcessInput(IInput::CEvent e)
 {
-	manipulate(e, str, sizeof(str), &len, &cursor_pos);
+	Manipulate(e, m_Str, sizeof(m_Str), &m_Len, &m_CursorPos);
 }
diff --git a/src/game/client/lineinput.h b/src/game/client/lineinput.h
new file mode 100644
index 00000000..f5c65282
--- /dev/null
+++ b/src/game/client/lineinput.h
@@ -0,0 +1,31 @@
+#ifndef GAME_CLIENT_LINEINPUT_H
+#define GAME_CLIENT_LINEINPUT_H
+
+#include <engine/input.h>
+
+// line input helter
+class CLineInput
+{
+	char m_Str[256];
+	int m_Len;
+	int m_CursorPos;
+public:
+	static bool Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int *pStrLenPtr, int *pCursorPosPtr);
+
+	class CCallback
+	{
+	public:
+		virtual ~CCallback() {}
+		virtual bool Event(IInput::CEvent e) = 0;
+	};
+
+	CLineInput();
+	void Clear();
+	void ProcessInput(IInput::CEvent e);
+	void Set(const char *pString);
+	const char *GetString() const { return m_Str; }
+	int GetLength() const { return m_Len; }
+	unsigned GetCursorOffset() const { return m_CursorPos; }
+};
+
+#endif
diff --git a/src/game/client/lineinput.hpp b/src/game/client/lineinput.hpp
deleted file mode 100644
index 75b2bd1d..00000000
--- a/src/game/client/lineinput.hpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef GAME_CLIENT_LINEINPUT_H
-#define GAME_CLIENT_LINEINPUT_H
-
-// line input helter
-class LINEINPUT
-{
-	char str[256];
-	int len;
-	int cursor_pos;
-public:
-	static void manipulate(INPUT_EVENT e, char *str, int str_max_size, int *str_len, int *cursor_pos);
-
-	class CALLBACK
-	{
-	public:
-		virtual ~CALLBACK() {}
-		virtual bool event(INPUT_EVENT e) = 0;
-	};
-
-	LINEINPUT();
-	void clear();
-	void process_input(INPUT_EVENT e);
-	void set(const char *string);
-	const char *get_string() const { return str; }
-	int get_length() const { return len; }
-	unsigned cursor_offset() const { return cursor_pos; }
-};
-
-#endif
diff --git a/src/game/client/render.cpp b/src/game/client/render.cpp
index f271c7d2..ee4dc9d9 100644
--- a/src/game/client/render.cpp
+++ b/src/game/client/render.cpp
@@ -1,19 +1,19 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
 #include <math.h>
 
-#include <base/math.hpp>
+#include <base/math.h>
 
-#include <engine/e_client_interface.h>
-#include <engine/e_config.h>
-#include <engine/client/graphics.h>
-#include <game/generated/gc_data.hpp>
-#include <game/generated/g_protocol.hpp>
-#include <game/layers.hpp>
-#include "animstate.hpp"
-#include "render.hpp"
+#include <engine/shared/config.h>
+#include <engine/graphics.h>
+#include <engine/map.h>
+#include <game/generated/client_data.h>
+#include <game/generated/protocol.h>
+#include <game/layers.h>
+#include "animstate.h"
+#include "render.h"
 
-static float sprite_w_scale;
-static float sprite_h_scale;
+static float gs_SpriteWScale;
+static float gs_SpriteHScale;
 
 
 /*
@@ -36,133 +36,141 @@ static void layershot_end()
 	config.cl_layershot++;
 }*/
 
-void CRenderTools::select_sprite(SPRITE *spr, int flags, int sx, int sy)
+void CRenderTools::SelectSprite(SPRITE *pSpr, int Flags, int sx, int sy)
 {
-	int x = spr->x+sx;
-	int y = spr->y+sy;
-	int w = spr->w;
-	int h = spr->h;
-	int cx = spr->set->gridx;
-	int cy = spr->set->gridy;
+	int x = pSpr->m_X+sx;
+	int y = pSpr->m_Y+sy;
+	int w = pSpr->m_W;
+	int h = pSpr->m_H;
+	int cx = pSpr->m_pSet->m_Gridx;
+	int cy = pSpr->m_pSet->m_Gridy;
 
 	float f = sqrtf(h*h + w*w);
-	sprite_w_scale = w/f;
-	sprite_h_scale = h/f;
+	gs_SpriteWScale = w/f;
+	gs_SpriteHScale = h/f;
 	
 	float x1 = x/(float)cx;
 	float x2 = (x+w)/(float)cx;
 	float y1 = y/(float)cy;
 	float y2 = (y+h)/(float)cy;
-	float temp = 0;
+	float Temp = 0;
 
-	if(flags&SPRITE_FLAG_FLIP_Y)
+	if(Flags&SPRITE_FLAG_FLIP_Y)
 	{
-		temp = y1;
+		Temp = y1;
 		y1 = y2;
-		y2 = temp;
+		y2 = Temp;
 	}
 
-	if(flags&SPRITE_FLAG_FLIP_X)
+	if(Flags&SPRITE_FLAG_FLIP_X)
 	{
-		temp = x1;
+		Temp = x1;
 		x1 = x2;
-		x2 = temp;
+		x2 = Temp;
 	}
 	
 	Graphics()->QuadsSetSubset(x1, y1, x2, y2);
 }
 
-void CRenderTools::select_sprite(int id, int flags, int sx, int sy)
+void CRenderTools::SelectSprite(int Id, int Flags, int sx, int sy)
 {
-	if(id < 0 || id > data->num_sprites)
+	if(Id < 0 || Id > g_pData->m_NumSprites)
 		return;
-	select_sprite(&data->sprites[id], flags, sx, sy);
+	SelectSprite(&g_pData->m_aSprites[Id], Flags, sx, sy);
 }
 
-void CRenderTools::draw_sprite(float x, float y, float size)
+void CRenderTools::DrawSprite(float x, float y, float Size)
 {
-	Graphics()->QuadsDraw(x, y, size*sprite_w_scale, size*sprite_h_scale);
+	IGraphics::CQuadItem QuadItem(x, y, Size*gs_SpriteWScale, Size*gs_SpriteHScale);
+	Graphics()->QuadsDraw(&QuadItem, 1);
 }
 
-void CRenderTools::draw_round_rect_ext(float x, float y, float w, float h, float r, int corners)
+void CRenderTools::DrawRoundRectExt(float x, float y, float w, float h, float r, int Corners)
 {
-	int num = 8;
-	for(int i = 0; i < num; i+=2)
+	IGraphics::CFreeformItem ArrayF[32];
+	int NumItems = 0;
+	int Num = 8;
+	for(int i = 0; i < Num; i+=2)
 	{
-		float a1 = i/(float)num * pi/2;
-		float a2 = (i+1)/(float)num * pi/2;
-		float a3 = (i+2)/(float)num * pi/2;
-		float ca1 = cosf(a1);
-		float ca2 = cosf(a2);
-		float ca3 = cosf(a3);
-		float sa1 = sinf(a1);
-		float sa2 = sinf(a2);
-		float sa3 = sinf(a3);
-
-		if(corners&1) // TL
-		Graphics()->QuadsDrawFreeform(
+		float a1 = i/(float)Num * pi/2;
+		float a2 = (i+1)/(float)Num * pi/2;
+		float a3 = (i+2)/(float)Num * pi/2;
+		float Ca1 = cosf(a1);
+		float Ca2 = cosf(a2);
+		float Ca3 = cosf(a3);
+		float Sa1 = sinf(a1);
+		float Sa2 = sinf(a2);
+		float Sa3 = sinf(a3);
+
+		if(Corners&1) // TL
+		ArrayF[NumItems++] = IGraphics::CFreeformItem(
 			x+r, y+r,
-			x+(1-ca1)*r, y+(1-sa1)*r,
-			x+(1-ca3)*r, y+(1-sa3)*r,
-			x+(1-ca2)*r, y+(1-sa2)*r);
+			x+(1-Ca1)*r, y+(1-Sa1)*r,
+			x+(1-Ca3)*r, y+(1-Sa3)*r,
+			x+(1-Ca2)*r, y+(1-Sa2)*r);
 
-		if(corners&2) // TR
-		Graphics()->QuadsDrawFreeform(
+		if(Corners&2) // TR
+		ArrayF[NumItems++] = IGraphics::CFreeformItem(
 			x+w-r, y+r,
-			x+w-r+ca1*r, y+(1-sa1)*r,
-			x+w-r+ca3*r, y+(1-sa3)*r,
-			x+w-r+ca2*r, y+(1-sa2)*r);
+			x+w-r+Ca1*r, y+(1-Sa1)*r,
+			x+w-r+Ca3*r, y+(1-Sa3)*r,
+			x+w-r+Ca2*r, y+(1-Sa2)*r);
 
-		if(corners&4) // BL
-		Graphics()->QuadsDrawFreeform(
+		if(Corners&4) // BL
+		ArrayF[NumItems++] = IGraphics::CFreeformItem(
 			x+r, y+h-r,
-			x+(1-ca1)*r, y+h-r+sa1*r,
-			x+(1-ca3)*r, y+h-r+sa3*r,
-			x+(1-ca2)*r, y+h-r+sa2*r);
+			x+(1-Ca1)*r, y+h-r+Sa1*r,
+			x+(1-Ca3)*r, y+h-r+Sa3*r,
+			x+(1-Ca2)*r, y+h-r+Sa2*r);
 
-		if(corners&8) // BR
-		Graphics()->QuadsDrawFreeform(
+		if(Corners&8) // BR
+		ArrayF[NumItems++] = IGraphics::CFreeformItem(
 			x+w-r, y+h-r,
-			x+w-r+ca1*r, y+h-r+sa1*r,
-			x+w-r+ca3*r, y+h-r+sa3*r,
-			x+w-r+ca2*r, y+h-r+sa2*r);
+			x+w-r+Ca1*r, y+h-r+Sa1*r,
+			x+w-r+Ca3*r, y+h-r+Sa3*r,
+			x+w-r+Ca2*r, y+h-r+Sa2*r);
 	}
-
-	Graphics()->QuadsDrawTL(x+r, y+r, w-r*2, h-r*2); // center
-	Graphics()->QuadsDrawTL(x+r, y, w-r*2, r); // top
-	Graphics()->QuadsDrawTL(x+r, y+h-r, w-r*2, r); // bottom
-	Graphics()->QuadsDrawTL(x, y+r, r, h-r*2); // left
-	Graphics()->QuadsDrawTL(x+w-r, y+r, r, h-r*2); // right
+	Graphics()->QuadsDrawFreeform(ArrayF, NumItems);
+
+	IGraphics::CQuadItem ArrayQ[9];
+	NumItems = 0;
+	ArrayQ[NumItems++] = IGraphics::CQuadItem(x+r, y+r, w-r*2, h-r*2); // center
+	ArrayQ[NumItems++] = IGraphics::CQuadItem(x+r, y, w-r*2, r); // top
+	ArrayQ[NumItems++] = IGraphics::CQuadItem(x+r, y+h-r, w-r*2, r); // bottom
+	ArrayQ[NumItems++] = IGraphics::CQuadItem(x, y+r, r, h-r*2); // left
+	ArrayQ[NumItems++] = IGraphics::CQuadItem(x+w-r, y+r, r, h-r*2); // right
 	
-	if(!(corners&1)) Graphics()->QuadsDrawTL(x, y, r, r); // TL
-	if(!(corners&2)) Graphics()->QuadsDrawTL(x+w, y, -r, r); // TR
-	if(!(corners&4)) Graphics()->QuadsDrawTL(x, y+h, r, -r); // BL
-	if(!(corners&8)) Graphics()->QuadsDrawTL(x+w, y+h, -r, -r); // BR
+	if(!(Corners&1)) ArrayQ[NumItems++] = IGraphics::CQuadItem(x, y, r, r); // TL
+	if(!(Corners&2)) ArrayQ[NumItems++] = IGraphics::CQuadItem(x+w, y, -r, r); // TR
+	if(!(Corners&4)) ArrayQ[NumItems++] = IGraphics::CQuadItem(x, y+h, r, -r); // BL
+	if(!(Corners&8)) ArrayQ[NumItems++] = IGraphics::CQuadItem(x+w, y+h, -r, -r); // BR
+
+	Graphics()->QuadsDrawTL(ArrayQ, NumItems);
 }
 
-void CRenderTools::draw_round_rect(float x, float y, float w, float h, float r)
+void CRenderTools::DrawRoundRect(float x, float y, float w, float h, float r)
 {
-	draw_round_rect_ext(x,y,w,h,r,0xf);
+	DrawRoundRectExt(x,y,w,h,r,0xf);
 }
 
-void CRenderTools::DrawUIRect(const CUIRect *r, vec4 color, int corners, float rounding)
+void CRenderTools::DrawUIRect(const CUIRect *r, vec4 Color, int Corners, float Rounding)
 {
 	Graphics()->TextureSet(-1);
 	
 	// TODO: FIX US
 	Graphics()->QuadsBegin();
-	Graphics()->SetColor(color.r, color.g, color.b, color.a);
-	draw_round_rect_ext(r->x,r->y,r->w,r->h,rounding*UI()->Scale(), corners);
+	Graphics()->SetColor(Color.r, Color.g, Color.b, Color.a);
+	DrawRoundRectExt(r->x,r->y,r->w,r->h,Rounding*UI()->Scale(), Corners);
 	Graphics()->QuadsEnd();
 }
 
-void CRenderTools::RenderTee(ANIMSTATE *anim, TEE_RENDER_INFO *info, int emote, vec2 dir, vec2 pos)
+void CRenderTools::RenderTee(CAnimState *pAnim, CTeeRenderInfo *pInfo, int Emote, vec2 Dir, vec2 Pos)
 {
-	vec2 direction = dir;
-	vec2 position = pos;
+	vec2 Direction = Dir;
+	vec2 Position = Pos;
 
 	//Graphics()->TextureSet(data->images[IMAGE_CHAR_DEFAULT].id);
-	Graphics()->TextureSet(info->texture);
+	Graphics()->TextureSet(pInfo->m_Texture);
 	
 	// TODO: FIX ME
 	Graphics()->QuadsBegin();
@@ -172,75 +180,79 @@ void CRenderTools::RenderTee(ANIMSTATE *anim, TEE_RENDER_INFO *info, int emote,
 	// second pass we draw the filling
 	for(int p = 0; p < 2; p++)
 	{
-		int outline = p==0 ? 1 : 0;
+		int OutLine = p==0 ? 1 : 0;
 
 		for(int f = 0; f < 2; f++)
 		{
-			float animscale = info->size * 1.0f/64.0f;
-			float basesize = info->size;
+			float AnimScale = pInfo->m_Size * 1.0f/64.0f;
+			float BaseSize = pInfo->m_Size;
 			if(f == 1)
 			{
-				Graphics()->QuadsSetRotation(anim->body.angle*pi*2);
+				Graphics()->QuadsSetRotation(pAnim->GetBody()->m_Angle*pi*2);
 
 				// draw body
-				Graphics()->SetColor(info->color_body.r, info->color_body.g, info->color_body.b, 1.0f);
-				vec2 body_pos = position + vec2(anim->body.x, anim->body.y)*animscale;
-				select_sprite(outline?SPRITE_TEE_BODY_OUTLINE:SPRITE_TEE_BODY, 0, 0, 0);
-				Graphics()->QuadsDraw(body_pos.x, body_pos.y, basesize, basesize);
+				Graphics()->SetColor(pInfo->m_ColorBody.r, pInfo->m_ColorBody.g, pInfo->m_ColorBody.b, 1.0f);
+				vec2 BodyPos = Position + vec2(pAnim->GetBody()->m_X, pAnim->GetBody()->m_Y)*AnimScale;
+				SelectSprite(OutLine?SPRITE_TEE_BODY_OUTLINE:SPRITE_TEE_BODY, 0, 0, 0);
+				IGraphics::CQuadItem QuadItem(BodyPos.x, BodyPos.y, BaseSize, BaseSize);
+				Graphics()->QuadsDraw(&QuadItem, 1);
 
 				// draw eyes
 				if(p == 1)
 				{
-					switch (emote)
+					switch (Emote)
 					{
 						case EMOTE_PAIN:
-							select_sprite(SPRITE_TEE_EYE_PAIN, 0, 0, 0);
+							SelectSprite(SPRITE_TEE_EYE_PAIN, 0, 0, 0);
 							break;
 						case EMOTE_HAPPY:
-							select_sprite(SPRITE_TEE_EYE_HAPPY, 0, 0, 0);
+							SelectSprite(SPRITE_TEE_EYE_HAPPY, 0, 0, 0);
 							break;
 						case EMOTE_SURPRISE:
-							select_sprite(SPRITE_TEE_EYE_SURPRISE, 0, 0, 0);
+							SelectSprite(SPRITE_TEE_EYE_SURPRISE, 0, 0, 0);
 							break;
 						case EMOTE_ANGRY:
-							select_sprite(SPRITE_TEE_EYE_ANGRY, 0, 0, 0);
+							SelectSprite(SPRITE_TEE_EYE_ANGRY, 0, 0, 0);
 							break;
 						default:
-							select_sprite(SPRITE_TEE_EYE_NORMAL, 0, 0, 0);
+							SelectSprite(SPRITE_TEE_EYE_NORMAL, 0, 0, 0);
 							break;
 					}
 					
-					float eyescale = basesize*0.40f;
-					float h = emote == EMOTE_BLINK ? basesize*0.15f : eyescale;
-					float eyeseparation = (0.075f - 0.010f*fabs(direction.x))*basesize;
-					vec2 offset = vec2(direction.x*0.125f, -0.05f+direction.y*0.10f)*basesize;
-					Graphics()->QuadsDraw(body_pos.x-eyeseparation+offset.x, body_pos.y+offset.y, eyescale, h);
-					Graphics()->QuadsDraw(body_pos.x+eyeseparation+offset.x, body_pos.y+offset.y, -eyescale, h);
+					float EyeScale = BaseSize*0.40f;
+					float h = Emote == EMOTE_BLINK ? BaseSize*0.15f : EyeScale;
+					float EyeSeparation = (0.075f - 0.010f*absolute(Direction.x))*BaseSize;
+					vec2 Offset = vec2(Direction.x*0.125f, -0.05f+Direction.y*0.10f)*BaseSize;
+					IGraphics::CQuadItem Array[2] = {
+						IGraphics::CQuadItem(BodyPos.x-EyeSeparation+Offset.x, BodyPos.y+Offset.y, EyeScale, h),
+						IGraphics::CQuadItem(BodyPos.x+EyeSeparation+Offset.x, BodyPos.y+Offset.y, -EyeScale, h)};
+					Graphics()->QuadsDraw(Array, 2);
 				}
 			}
 
 			// draw feet
-			ANIM_KEYFRAME *foot = f ? &anim->front_foot : &anim->back_foot;
+			ANIM_KEYFRAME *pFoot = f ? pAnim->GetFrontFoot() : pAnim->GetBackFoot();
 
-			float w = basesize;
-			float h = basesize/2;
+			float w = BaseSize;
+			float h = BaseSize/2;
 
-			Graphics()->QuadsSetRotation(foot->angle*pi*2);
+			Graphics()->QuadsSetRotation(pFoot->m_Angle*pi*2);
 			
-			bool indicate = !info->got_airjump && config.cl_airjumpindicator;
+			bool Indicate = !pInfo->m_GotAirJump && g_Config.m_ClAirjumpindicator;
 			float cs = 1.0f; // color scale
 			
-			if(outline)
-				select_sprite(SPRITE_TEE_FOOT_OUTLINE, 0, 0, 0);
+			if(OutLine)
+				SelectSprite(SPRITE_TEE_FOOT_OUTLINE, 0, 0, 0);
 			else
 			{
-				select_sprite(SPRITE_TEE_FOOT, 0, 0, 0);
-				if(indicate)
+				SelectSprite(SPRITE_TEE_FOOT, 0, 0, 0);
+				if(Indicate)
 					cs = 0.5f;
 			}
 				
-			Graphics()->SetColor(info->color_feet.r*cs, info->color_feet.g*cs, info->color_feet.b*cs, 1.0f);
-			Graphics()->QuadsDraw(position.x+foot->x*animscale, position.y+foot->y*animscale, w, h);
+			Graphics()->SetColor(pInfo->m_ColorFeet.r*cs, pInfo->m_ColorFeet.g*cs, pInfo->m_ColorFeet.b*cs, 1.0f);
+			IGraphics::CQuadItem QuadItem(Position.x+pFoot->m_X*AnimScale, Position.y+pFoot->m_Y*AnimScale, w, h);
+			Graphics()->QuadsDraw(&QuadItem, 1);
 		}
 	}
 
@@ -249,67 +261,68 @@ void CRenderTools::RenderTee(ANIMSTATE *anim, TEE_RENDER_INFO *info, int emote,
 	
 }
 
-static void calc_screen_params(float amount, float wmax, float hmax, float aspect, float *w, float *h)
+static void CalcScreenParams(float Amount, float WMax, float HMax, float Aspect, float *w, float *h)
 {
-	float f = sqrt(amount) / sqrt(aspect);
-	*w = f*aspect;
+	float f = sqrtf(Amount) / sqrtf(Aspect);
+	*w = f*Aspect;
 	*h = f;
 	
 	// limit the view
-	if(*w > wmax)
+	if(*w > WMax)
 	{
-		*w = wmax;
-		*h = *w/aspect;
+		*w = WMax;
+		*h = *w/Aspect;
 	}
 	
-	if(*h > hmax)
+	if(*h > HMax)
 	{
-		*h = hmax;
-		*w = *h*aspect;
+		*h = HMax;
+		*w = *h*Aspect;
 	}
 }
 
-void CRenderTools::mapscreen_to_world(float center_x, float center_y, float parallax_x, float parallax_y,
-	float offset_x, float offset_y, float aspect, float zoom, float *points)
+void CRenderTools::MapscreenToWorld(float CenterX, float CenterY, float ParallaxX, float ParallaxY,
+	float OffsetX, float OffsetY, float Aspect, float Zoom, float *pPoints)
 {
-	float width, height;
-	calc_screen_params(1150*1000, 1500, 1050, aspect, &width, &height);
-	center_x *= parallax_x;
-	center_y *= parallax_y;
-	width *= zoom;
-	height *= zoom;
-	points[0] = offset_x+center_x-width/2;
-	points[1] = offset_y+center_y-height/2;
-	points[2] = offset_x+center_x+width/2;
-	points[3] = offset_y+center_y+height/2;
+	float Width, Height;
+	CalcScreenParams(1150*1000, 1500, 1050, Aspect, &Width, &Height);
+	CenterX *= ParallaxX;
+	CenterY *= ParallaxY;
+	Width *= Zoom;
+	Height *= Zoom;
+	pPoints[0] = OffsetX+CenterX-Width/2;
+	pPoints[1] = OffsetY+CenterY-Height/2;
+	pPoints[2] = OffsetX+CenterX+Width/2;
+	pPoints[3] = OffsetY+CenterY+Height/2;
 }
 
-void CRenderTools::render_tilemap_generate_skip()
+void CRenderTools::RenderTilemapGenerateSkip(class CLayers *pLayers)
 {
-	for(int g = 0; g < layers_num_groups(); g++)
+	
+	for(int g = 0; g < pLayers->NumGroups(); g++)
 	{
-		MAPITEM_GROUP *group = layers_get_group(g);
+		CMapItemGroup *pGroup = pLayers->GetGroup(g);
 		
-		for(int l = 0; l < group->num_layers; l++)
+		for(int l = 0; l < pGroup->m_NumLayers; l++)
 		{
-			MAPITEM_LAYER *layer = layers_get_layer(group->start_layer+l);
+			CMapItemLayer *pLayer = pLayers->GetLayer(pGroup->m_StartLayer+l);
 
-			if(layer->type == LAYERTYPE_TILES)
+			if(pLayer->m_Type == LAYERTYPE_TILES)
 			{
-				MAPITEM_LAYER_TILEMAP *tmap = (MAPITEM_LAYER_TILEMAP *)layer;
-				TILE *tiles = (TILE *)map_get_data(tmap->data);
-				for(int y = 0; y < tmap->height; y++)
+				CMapItemLayerTilemap *pTmap = (CMapItemLayerTilemap *)pLayer;
+				CTile *pTiles = (CTile *)pLayers->Map()->GetData(pTmap->m_Data);
+				for(int y = 0; y < pTmap->m_Height; y++)
 				{
-					for(int x = 1; x < tmap->width; x++)
+					for(int x = 1; x < pTmap->m_Width; x++)
 					{
 						int sx;
-						for(sx = 1; x+sx < tmap->width && sx < 255; sx++)
+						for(sx = 1; x+sx < pTmap->m_Width && sx < 255; sx++)
 						{
-							if(tiles[y*tmap->width+x+sx].index)
+							if(pTiles[y*pTmap->m_Width+x+sx].m_Index)
 								break;
 						}
 						
-						tiles[y*tmap->width+x].skip = sx-1;
+						pTiles[y*pTmap->m_Width+x].m_Skip = sx-1;
 					}
 				}
 			}
diff --git a/src/game/client/render.h b/src/game/client/render.h
new file mode 100644
index 00000000..a546b3eb
--- /dev/null
+++ b/src/game/client/render.h
@@ -0,0 +1,79 @@
+#ifndef GAME_CLIENT_RENDER_H
+#define GAME_CLIENT_RENDER_H
+
+#include <base/vmath.h>
+#include <game/mapitems.h>
+#include "ui.h"
+
+
+struct CTeeRenderInfo
+{
+	CTeeRenderInfo()
+	{
+		m_Texture = -1;
+		m_ColorBody = vec4(1,1,1,1);
+		m_ColorFeet = vec4(1,1,1,1);
+		m_Size = 1.0f;
+		m_GotAirJump = 1;
+	};
+	
+	int m_Texture;
+	vec4 m_ColorBody;
+	vec4 m_ColorFeet;
+	float m_Size;
+	int m_GotAirJump;
+};
+
+// sprite renderings
+enum
+{
+	SPRITE_FLAG_FLIP_Y=1,
+	SPRITE_FLAG_FLIP_X=2,
+	
+	LAYERRENDERFLAG_OPAQUE=1,
+	LAYERRENDERFLAG_TRANSPARENT=2,
+	
+	TILERENDERFLAG_EXTEND=4,
+};
+
+
+class CRenderTools
+{
+public:
+	class IGraphics *m_pGraphics;
+	class CUI *m_pUI;
+	
+	class IGraphics *Graphics() const { return m_pGraphics; }
+	class CUI *UI() const { return m_pUI; }
+
+	//typedef struct SPRITE;
+
+	void SelectSprite(struct SPRITE *pSprite, int Flags=0, int sx=0, int sy=0);
+	void SelectSprite(int id, int Flags=0, int sx=0, int sy=0);
+
+	void DrawSprite(float x, float y, float size);
+
+	// rects
+	void DrawRoundRect(float x, float y, float w, float h, float r);
+	void DrawRoundRectExt(float x, float y, float w, float h, float r, int Corners);
+	
+	void DrawUIRect(const CUIRect *pRect, vec4 Color, int Corners, float Rounding);
+
+	// larger rendering methods
+	void RenderTilemapGenerateSkip(class CLayers *pLayers);
+
+	// object render methods (gc_render_obj.cpp)
+	void RenderTee(class CAnimState *pAnim, CTeeRenderInfo *pInfo, int Emote, vec2 Dir, vec2 Pos);
+
+	// map render methods (gc_render_map.cpp)
+	static void RenderEvalEnvelope(CEnvPoint *pPoints, int NumPoints, int Channels, float Time, float *pResult);
+	void RenderQuads(CQuad *pQuads, int NumQuads, int Flags, void (*pfnEval)(float TimeOffset, int Env, float *pChannels, void *pUser), void *pUser);
+	void RenderTilemap(CTile *pTiles, int w, int h, float Scale, vec4 Color, int Flags);
+
+	// helpers
+	void MapscreenToWorld(float CenterX, float CenterY, float ParallaxX, float ParallaxY,
+		float OffsetX, float OffsetY, float Aspect, float Zoom, float *pPoints);	
+	
+};
+
+#endif
diff --git a/src/game/client/render.hpp b/src/game/client/render.hpp
deleted file mode 100644
index 8e99b432..00000000
--- a/src/game/client/render.hpp
+++ /dev/null
@@ -1,81 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef GAME_CLIENT_RENDER_H
-#define GAME_CLIENT_RENDER_H
-
-#include <base/vmath.hpp>
-
-#include "../mapitems.hpp"
-#include "ui.hpp"
-
-
-struct TEE_RENDER_INFO
-{
-	TEE_RENDER_INFO()
-	{
-		texture = -1;
-		color_body = vec4(1,1,1,1);
-		color_feet = vec4(1,1,1,1);
-		size = 1.0f;
-		got_airjump = 1;
-	};
-	
-	int texture;
-	vec4 color_body;
-	vec4 color_feet;
-	float size;
-	int got_airjump;
-};
-
-// sprite renderings
-enum
-{
-	SPRITE_FLAG_FLIP_Y=1,
-	SPRITE_FLAG_FLIP_X=2,
-	
-	LAYERRENDERFLAG_OPAQUE=1,
-	LAYERRENDERFLAG_TRANSPARENT=2,
-	
-	TILERENDERFLAG_EXTEND=4,
-};
-
-
-class CRenderTools
-{
-public:
-	class IGraphics *m_pGraphics;
-	class CUI *m_pUI;
-	
-	class IGraphics *Graphics() const { return m_pGraphics; }
-	class CUI *UI() const { return m_pUI; }
-
-	//typedef struct SPRITE;
-
-	void select_sprite(struct SPRITE *spr, int flags=0, int sx=0, int sy=0);
-	void select_sprite(int id, int flags=0, int sx=0, int sy=0);
-
-	void draw_sprite(float x, float y, float size);
-
-	// rects
-	void draw_round_rect(float x, float y, float w, float h, float r);
-	void draw_round_rect_ext(float x, float y, float w, float h, float r, int corners);
-	
-	void DrawUIRect(const CUIRect *r, vec4 color, int corners, float rounding);
-
-	// larger rendering methods
-	void render_tilemap_generate_skip();
-
-	// object render methods (gc_render_obj.cpp)
-	void RenderTee(class ANIMSTATE *anim, TEE_RENDER_INFO *info, int emote, vec2 dir, vec2 pos);
-
-	// map render methods (gc_render_map.cpp)
-	static void render_eval_envelope(ENVPOINT *points, int num_points, int channels, float time, float *result);
-	void render_quads(QUAD *quads, int num_quads, int flags, void (*eval)(float time_offset, int env, float *channels, void *user), void *user);
-	void render_tilemap(TILE *tiles, int w, int h, float scale, vec4 color, int flags);
-
-	// helpers
-	void mapscreen_to_world(float center_x, float center_y, float parallax_x, float parallax_y,
-		float offset_x, float offset_y, float aspect, float zoom, float *points);	
-	
-};
-
-#endif
diff --git a/src/game/client/render_map.cpp b/src/game/client/render_map.cpp
index ea3b8420..0354b9d5 100644
--- a/src/game/client/render_map.cpp
+++ b/src/game/client/render_map.cpp
@@ -1,198 +1,198 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
 #include <math.h>
-#include <base/math.hpp>
-#include <engine/e_client_interface.h>
-#include <engine/client/graphics.h>
+#include <base/math.h>
+#include <engine/graphics.h>
 
-#include "render.hpp"
+#include "render.h"
 
-void CRenderTools::render_eval_envelope(ENVPOINT *points, int num_points, int channels, float time, float *result)
+void CRenderTools::RenderEvalEnvelope(CEnvPoint *pPoints, int NumPoints, int Channels, float Time, float *pResult)
 {
-	if(num_points == 0)
+	if(NumPoints == 0)
 	{
-		result[0] = 0;
-		result[1] = 0;
-		result[2] = 0;
-		result[3] = 0;
+		pResult[0] = 0;
+		pResult[1] = 0;
+		pResult[2] = 0;
+		pResult[3] = 0;
 		return;
 	}
 	
-	if(num_points == 1)
+	if(NumPoints == 1)
 	{
-		result[0] = fx2f(points[0].values[0]);
-		result[1] = fx2f(points[0].values[1]);
-		result[2] = fx2f(points[0].values[2]);
-		result[3] = fx2f(points[0].values[3]);
+		pResult[0] = fx2f(pPoints[0].m_aValues[0]);
+		pResult[1] = fx2f(pPoints[0].m_aValues[1]);
+		pResult[2] = fx2f(pPoints[0].m_aValues[2]);
+		pResult[3] = fx2f(pPoints[0].m_aValues[3]);
 		return;
 	}
 	
-	time = fmod(time, points[num_points-1].time/1000.0f)*1000.0f;
-	for(int i = 0; i < num_points-1; i++)
+	Time = fmod(Time, pPoints[NumPoints-1].m_Time/1000.0f)*1000.0f;
+	for(int i = 0; i < NumPoints-1; i++)
 	{
-		if(time >= points[i].time && time <= points[i+1].time)
+		if(Time >= pPoints[i].m_Time && Time <= pPoints[i+1].m_Time)
 		{
-			float delta = points[i+1].time-points[i].time;
-			float a = (time-points[i].time)/delta;
+			float Delta = pPoints[i+1].m_Time-pPoints[i].m_Time;
+			float a = (Time-pPoints[i].m_Time)/Delta;
 
 
-			if(points[i].curvetype == CURVETYPE_SMOOTH)
+			if(pPoints[i].m_Curvetype == CURVETYPE_SMOOTH)
 				a = -2*a*a*a + 3*a*a; // second hermite basis
-			else if(points[i].curvetype == CURVETYPE_SLOW)
+			else if(pPoints[i].m_Curvetype == CURVETYPE_SLOW)
 				a = a*a*a;
-			else if(points[i].curvetype == CURVETYPE_FAST)
+			else if(pPoints[i].m_Curvetype == CURVETYPE_FAST)
 			{
 				a = 1-a;
 				a = 1-a*a*a;
 			}
-			else if (points[i].curvetype == CURVETYPE_STEP)
+			else if (pPoints[i].m_Curvetype == CURVETYPE_STEP)
 				a = 0;
 			else
 			{
 				// linear
 			}
 					
-			for(int c = 0; c < channels; c++)
+			for(int c = 0; c < Channels; c++)
 			{
-				float v0 = fx2f(points[i].values[c]);
-				float v1 = fx2f(points[i+1].values[c]);
-				result[c] = v0 + (v1-v0) * a;
+				float v0 = fx2f(pPoints[i].m_aValues[c]);
+				float v1 = fx2f(pPoints[i+1].m_aValues[c]);
+				pResult[c] = v0 + (v1-v0) * a;
 			}
 			
 			return;
 		}
 	}
 	
-	result[0] = fx2f(points[num_points-1].values[0]);
-	result[1] = fx2f(points[num_points-1].values[1]);
-	result[2] = fx2f(points[num_points-1].values[2]);
-	result[3] = fx2f(points[num_points-1].values[3]);
+	pResult[0] = fx2f(pPoints[NumPoints-1].m_aValues[0]);
+	pResult[1] = fx2f(pPoints[NumPoints-1].m_aValues[1]);
+	pResult[2] = fx2f(pPoints[NumPoints-1].m_aValues[2]);
+	pResult[3] = fx2f(pPoints[NumPoints-1].m_aValues[3]);
 	return;
 }
 
 
-static void rotate(POINT *center, POINT *point, float rotation)
+static void Rotate(CPoint *pCenter, CPoint *pPoint, float Rotation)
 {
-	int x = point->x - center->x;
-	int y = point->y - center->y;
-	point->x = (int)(x * cosf(rotation) - y * sinf(rotation) + center->x);
-	point->y = (int)(x * sinf(rotation) + y * cosf(rotation) + center->y);
+	int x = pPoint->x - pCenter->x;
+	int y = pPoint->y - pCenter->y;
+	pPoint->x = (int)(x * cosf(Rotation) - y * sinf(Rotation) + pCenter->x);
+	pPoint->y = (int)(x * sinf(Rotation) + y * cosf(Rotation) + pCenter->y);
 }
 
-void CRenderTools::render_quads(QUAD *quads, int num_quads, int renderflags, void (*eval)(float time_offset, int env, float *channels, void *user), void *user)
+void CRenderTools::RenderQuads(CQuad *pQuads, int NumQuads, int RenderFlags, void (*pfnEval)(float TimeOffset, int Env, float *pChannels, void *pUser), void *pUser)
 {
 	Graphics()->QuadsBegin();
-	float conv = 1/255.0f;
-	for(int i = 0; i < num_quads; i++)
+	float Conv = 1/255.0f;
+	for(int i = 0; i < NumQuads; i++)
 	{
-		QUAD *q = &quads[i];
+		CQuad *q = &pQuads[i];
 		
 		float r=1, g=1, b=1, a=1;
 
-		if(q->color_env >= 0)
+		if(q->m_ColorEnv >= 0)
 		{
-			float channels[4];
-			eval(q->color_env_offset/1000.0f, q->color_env, channels, user);
-			r = channels[0];
-			g = channels[1];
-			b = channels[2];
-			a = channels[3];
+			float aChannels[4];
+			pfnEval(q->m_ColorEnvOffset/1000.0f, q->m_ColorEnv, aChannels, pUser);
+			r = aChannels[0];
+			g = aChannels[1];
+			b = aChannels[2];
+			a = aChannels[3];
 		}		
 		
-		bool opaque = false;
-		if(a < 0.01f || (q->colors[0].a < 0.01f && q->colors[1].a < 0.01f && q->colors[2].a < 0.01f && q->colors[3].a < 0.01f))
-			opaque = true;
+		bool Opaque = false;
+		if(a < 0.01f || (q->m_aColors[0].a < 0.01f && q->m_aColors[1].a < 0.01f && q->m_aColors[2].a < 0.01f && q->m_aColors[3].a < 0.01f))
+			Opaque = true;
 			
-		if(opaque && !(renderflags&LAYERRENDERFLAG_OPAQUE))
+		if(Opaque && !(RenderFlags&LAYERRENDERFLAG_OPAQUE))
 			continue;
-		if(!opaque && !(renderflags&LAYERRENDERFLAG_TRANSPARENT))
+		if(!Opaque && !(RenderFlags&LAYERRENDERFLAG_TRANSPARENT))
 			continue;
 		
 		Graphics()->QuadsSetSubsetFree(
-			fx2f(q->texcoords[0].x), fx2f(q->texcoords[0].y),
-			fx2f(q->texcoords[1].x), fx2f(q->texcoords[1].y),
-			fx2f(q->texcoords[2].x), fx2f(q->texcoords[2].y),
-			fx2f(q->texcoords[3].x), fx2f(q->texcoords[3].y)
+			fx2f(q->m_aTexcoords[0].x), fx2f(q->m_aTexcoords[0].y),
+			fx2f(q->m_aTexcoords[1].x), fx2f(q->m_aTexcoords[1].y),
+			fx2f(q->m_aTexcoords[2].x), fx2f(q->m_aTexcoords[2].y),
+			fx2f(q->m_aTexcoords[3].x), fx2f(q->m_aTexcoords[3].y)
 		);
 
-		float offset_x = 0;
-		float offset_y = 0;
-		float rot = 0;
+		float OffsetX = 0;
+		float OffsetY = 0;
+		float Rot = 0;
 		
 		// TODO: fix this
-		if(q->pos_env >= 0)
+		if(q->m_PosEnv >= 0)
 		{
-			float channels[4];
-			eval(q->pos_env_offset/1000.0f, q->pos_env, channels, user);
-			offset_x = channels[0];
-			offset_y = channels[1];
-			rot = channels[2]/360.0f*pi*2;
+			float aChannels[4];
+			pfnEval(q->m_PosEnvOffset/1000.0f, q->m_PosEnv, aChannels, pUser);
+			OffsetX = aChannels[0];
+			OffsetY = aChannels[1];
+			Rot = aChannels[2]/360.0f*pi*2;
 		}
 		
-		
-		Graphics()->SetColorVertex(0, q->colors[0].r*conv*r, q->colors[0].g*conv*g, q->colors[0].b*conv*b, q->colors[0].a*conv*a);
-		Graphics()->SetColorVertex(1, q->colors[1].r*conv*r, q->colors[1].g*conv*g, q->colors[1].b*conv*b, q->colors[1].a*conv*a);
-		Graphics()->SetColorVertex(2, q->colors[2].r*conv*r, q->colors[2].g*conv*g, q->colors[2].b*conv*b, q->colors[2].a*conv*a);
-		Graphics()->SetColorVertex(3, q->colors[3].r*conv*r, q->colors[3].g*conv*g, q->colors[3].b*conv*b, q->colors[3].a*conv*a);
+		IGraphics::CColorVertex Array[4] = {
+			IGraphics::CColorVertex(0, q->m_aColors[0].r*Conv*r, q->m_aColors[0].g*Conv*g, q->m_aColors[0].b*Conv*b, q->m_aColors[0].a*Conv*a),
+			IGraphics::CColorVertex(1, q->m_aColors[1].r*Conv*r, q->m_aColors[1].g*Conv*g, q->m_aColors[1].b*Conv*b, q->m_aColors[1].a*Conv*a),
+			IGraphics::CColorVertex(2, q->m_aColors[2].r*Conv*r, q->m_aColors[2].g*Conv*g, q->m_aColors[2].b*Conv*b, q->m_aColors[2].a*Conv*a),
+			IGraphics::CColorVertex(3, q->m_aColors[3].r*Conv*r, q->m_aColors[3].g*Conv*g, q->m_aColors[3].b*Conv*b, q->m_aColors[3].a*Conv*a)};
+		Graphics()->SetColorVertex(Array, 4);
 
-		POINT *points = q->points;
+		CPoint *pPoints = q->m_aPoints;
 	
-		if(rot != 0)
+		if(Rot != 0)
 		{
-			static POINT rotated[4];
-			rotated[0] = q->points[0];
-			rotated[1] = q->points[1];
-			rotated[2] = q->points[2];
-			rotated[3] = q->points[3];
-			points = rotated;
+			static CPoint aRotated[4];
+			aRotated[0] = q->m_aPoints[0];
+			aRotated[1] = q->m_aPoints[1];
+			aRotated[2] = q->m_aPoints[2];
+			aRotated[3] = q->m_aPoints[3];
+			pPoints = aRotated;
 			
-			rotate(&q->points[4], &rotated[0], rot);
-			rotate(&q->points[4], &rotated[1], rot);
-			rotate(&q->points[4], &rotated[2], rot);
-			rotate(&q->points[4], &rotated[3], rot);
+			Rotate(&q->m_aPoints[4], &aRotated[0], Rot);
+			Rotate(&q->m_aPoints[4], &aRotated[1], Rot);
+			Rotate(&q->m_aPoints[4], &aRotated[2], Rot);
+			Rotate(&q->m_aPoints[4], &aRotated[3], Rot);
 		}
 		
-		Graphics()->QuadsDrawFreeform(
-			fx2f(points[0].x)+offset_x, fx2f(points[0].y)+offset_y,
-			fx2f(points[1].x)+offset_x, fx2f(points[1].y)+offset_y,
-			fx2f(points[2].x)+offset_x, fx2f(points[2].y)+offset_y,
-			fx2f(points[3].x)+offset_x, fx2f(points[3].y)+offset_y
-		);
+		IGraphics::CFreeformItem Freeform(
+			fx2f(pPoints[0].x)+OffsetX, fx2f(pPoints[0].y)+OffsetY,
+			fx2f(pPoints[1].x)+OffsetX, fx2f(pPoints[1].y)+OffsetY,
+			fx2f(pPoints[2].x)+OffsetX, fx2f(pPoints[2].y)+OffsetY,
+			fx2f(pPoints[3].x)+OffsetX, fx2f(pPoints[3].y)+OffsetY);
+		Graphics()->QuadsDrawFreeform(&Freeform, 1);
 	}
 	Graphics()->QuadsEnd();	
 }
 
-void CRenderTools::render_tilemap(TILE *tiles, int w, int h, float scale, vec4 color, int renderflags)
+void CRenderTools::RenderTilemap(CTile *pTiles, int w, int h, float Scale, vec4 Color, int RenderFlags)
 {
 	//Graphics()->TextureSet(img_get(tmap->image));
-	float screen_x0, screen_y0, screen_x1, screen_y1;
-	Graphics()->GetScreen(&screen_x0, &screen_y0, &screen_x1, &screen_y1);
+	float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
+	Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1);
 	//Graphics()->MapScreen(screen_x0-50, screen_y0-50, screen_x1+50, screen_y1+50);
 
 	// calculate the final pixelsize for the tiles	
-	float tile_pixelsize = 1024/32.0f;
-	float final_tilesize = scale/(screen_x1-screen_x0) * Graphics()->ScreenWidth();
-	float final_tilesize_scale = final_tilesize/tile_pixelsize;
+	float TilePixelSize = 1024/32.0f;
+	float FinalTileSize = Scale/(ScreenX1-ScreenX0) * Graphics()->ScreenWidth();
+	float FinalTilesetScale = FinalTileSize/TilePixelSize;
 	
 	Graphics()->QuadsBegin();
-	Graphics()->SetColor(color.r, color.g, color.b, color.a);
+	Graphics()->SetColor(Color.r, Color.g, Color.b, Color.a);
 	
-	int starty = (int)(screen_y0/scale)-1;
-	int startx = (int)(screen_x0/scale)-1;
-	int endy = (int)(screen_y1/scale)+1;
-	int endx = (int)(screen_x1/scale)+1;
+	int StartY = (int)(ScreenY0/Scale)-1;
+	int StartX = (int)(ScreenX0/Scale)-1;
+	int EndY = (int)(ScreenY1/Scale)+1;
+	int EndX = (int)(ScreenX1/Scale)+1;
 	
 	// adjust the texture shift according to mipmap level
-	float texsize = 1024.0f;
-	float frac = (1.25f/texsize) * (1/final_tilesize_scale);
-	float nudge = (0.5f/texsize) * (1/final_tilesize_scale);
+	float TexSize = 1024.0f;
+	float Frac = (1.25f/TexSize) * (1/FinalTilesetScale);
+	float Nudge = (0.5f/TexSize) * (1/FinalTilesetScale);
 
-	for(int y = starty; y < endy; y++)
-		for(int x = startx; x < endx; x++)
+	for(int y = StartY; y < EndY; y++)
+		for(int x = StartX; x < EndX; x++)
 		{
 			int mx = x;
 			int my = y;
 			
-			if(renderflags&TILERENDERFLAG_EXTEND)
+			if(RenderFlags&TILERENDERFLAG_EXTEND)
 			{
 				if(mx<0)
 					mx = 0;
@@ -217,59 +217,60 @@ void CRenderTools::render_tilemap(TILE *tiles, int w, int h, float scale, vec4 c
 			
 			int c = mx + my*w;
 				
-			unsigned char index = tiles[c].index;
-			if(index)
+			unsigned char Index = pTiles[c].m_Index;
+			if(Index)
 			{
-				unsigned char flags = tiles[c].flags;
+				unsigned char Flags = pTiles[c].m_Flags;
 				
-				bool render = false;
-				if(flags&TILEFLAG_OPAQUE)
+				bool Render = false;
+				if(Flags&TILEFLAG_OPAQUE)
 				{
-					if(renderflags&LAYERRENDERFLAG_OPAQUE)
-						render = true;
+					if(RenderFlags&LAYERRENDERFLAG_OPAQUE)
+						Render = true;
 				}
 				else
 				{
-					if(renderflags&LAYERRENDERFLAG_TRANSPARENT)
-						render = true;
+					if(RenderFlags&LAYERRENDERFLAG_TRANSPARENT)
+						Render = true;
 				}
 				
-				if(render)
+				if(Render)
 				{
 					
-					int tx = index%16;
-					int ty = index/16;
-					int px0 = tx*(1024/16);
-					int py0 = ty*(1024/16);
-					int px1 = (tx+1)*(1024/16)-1;
-					int py1 = (ty+1)*(1024/16)-1;
+					int tx = Index%16;
+					int ty = Index/16;
+					int Px0 = tx*(1024/16);
+					int Py0 = ty*(1024/16);
+					int Px1 = (tx+1)*(1024/16)-1;
+					int Py1 = (ty+1)*(1024/16)-1;
 					
-					float u0 = nudge + px0/texsize+frac;
-					float v0 = nudge + py0/texsize+frac;
-					float u1 = nudge + px1/texsize-frac;
-					float v1 = nudge + py1/texsize-frac;
+					float u0 = Nudge + Px0/TexSize+Frac;
+					float v0 = Nudge + Py0/TexSize+Frac;
+					float u1 = Nudge + Px1/TexSize-Frac;
+					float v1 = Nudge + Py1/TexSize-Frac;
 					
-					if(flags&TILEFLAG_VFLIP)
+					if(Flags&TILEFLAG_VFLIP)
 					{
-						float tmp = u0;
+						float Tmp = u0;
 						u0 = u1;
-						u1 = tmp;
+						u1 = Tmp;
 					}
 
-					if(flags&TILEFLAG_HFLIP)
+					if(Flags&TILEFLAG_HFLIP)
 					{
-						float tmp = v0;
+						float Tmp = v0;
 						v0 = v1;
-						v1 = tmp;
+						v1 = Tmp;
 					}
 					
 					Graphics()->QuadsSetSubset(u0,v0,u1,v1);
-					Graphics()->QuadsDrawTL(x*scale, y*scale, scale, scale);
+					IGraphics::CQuadItem QuadItem(x*Scale, y*Scale, Scale, Scale);
+					Graphics()->QuadsDrawTL(&QuadItem, 1);
 				}
 			}
-			x += tiles[c].skip;
+			x += pTiles[c].m_Skip;
 		}
 	
 	Graphics()->QuadsEnd();
-	Graphics()->MapScreen(screen_x0, screen_y0, screen_x1, screen_y1);
+	Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1);
 }
diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp
index 4aaaf32f..2895b717 100644
--- a/src/game/client/ui.cpp
+++ b/src/game/client/ui.cpp
@@ -1,10 +1,10 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
 #include <base/system.h>
 
-#include <engine/e_client_interface.h>
-#include <engine/e_config.h>
-#include <engine/client/graphics.h>
-#include "ui.hpp"
+#include <engine/shared/config.h>
+#include <engine/graphics.h>
+#include <engine/textrender.h>
+#include "ui.h"
 
 /********************************************************
  UI                                                      
@@ -30,12 +30,12 @@ CUI::CUI()
 	m_Screen.h = 480.0f;
 }
 
-int CUI::Update(float mx, float my, float mwx, float mwy, int Buttons)
+int CUI::Update(float Mx, float My, float Mwx, float Mwy, int Buttons)
 {
-    m_MouseX = mx;
-    m_MouseY = my;
-    m_MouseWorldX = mwx;
-    m_MouseWorldY = mwy;
+    m_MouseX = Mx;
+    m_MouseY = My;
+    m_MouseWorldX = Mwx;
+    m_MouseWorldY = Mwy;
     m_LastMouseButtons = m_MouseButtons;
     m_MouseButtons = Buttons;
     m_pHotItem = m_pBecommingHotItem;
@@ -54,11 +54,11 @@ int CUI::MouseInside(const CUIRect *r)
 
 CUIRect *CUI::Screen()
 {
-    float aspect = Graphics()->ScreenAspect();
+    float Aspect = Graphics()->ScreenAspect();
     float w, h;
 
     h = 600;
-    w = aspect*h;
+    w = Aspect*h;
 
     m_Screen.w = w;
     m_Screen.h = h;
@@ -78,9 +78,9 @@ void CUI::SetScale(float s)
 
 void CUI::ClipEnable(const CUIRect *r)
 {
-	float xscale = Graphics()->ScreenWidth()/Screen()->w;
-	float yscale = Graphics()->ScreenHeight()/Screen()->h;
-	Graphics()->ClipEnable((int)(r->x*xscale), (int)(r->y*yscale), (int)(r->w*xscale), (int)(r->h*yscale));
+	float XScale = Graphics()->ScreenWidth()/Screen()->w;
+	float YScale = Graphics()->ScreenHeight()/Screen()->h;
+	Graphics()->ClipEnable((int)(r->x*XScale), (int)(r->y*YScale), (int)(r->w*XScale), (int)(r->h*YScale));
 }
 
 void CUI::ClipDisable()
@@ -88,153 +88,153 @@ void CUI::ClipDisable()
 	Graphics()->ClipDisable();
 }
 
-void CUIRect::HSplitTop(float cut, CUIRect *top, CUIRect *bottom) const
+void CUIRect::HSplitTop(float Cut, CUIRect *pTop, CUIRect *pBottom) const
 {
     CUIRect r = *this;
-    cut *= Scale();
+    Cut *= Scale();
 
-    if (top)
+    if (pTop)
     {
-        top->x = r.x;
-        top->y = r.y;
-        top->w = r.w;
-        top->h = cut;
+        pTop->x = r.x;
+        pTop->y = r.y;
+        pTop->w = r.w;
+        pTop->h = Cut;
     }
 
-    if (bottom)
+    if (pBottom)
     {
-        bottom->x = r.x;
-        bottom->y = r.y + cut;
-        bottom->w = r.w;
-        bottom->h = r.h - cut;
+        pBottom->x = r.x;
+        pBottom->y = r.y + Cut;
+        pBottom->w = r.w;
+        pBottom->h = r.h - Cut;
     }
 }
 
-void CUIRect::HSplitBottom(float cut, CUIRect *top, CUIRect *bottom) const
+void CUIRect::HSplitBottom(float Cut, CUIRect *pTop, CUIRect *pBottom) const
 {
     CUIRect r = *this;
-    cut *= Scale();
+    Cut *= Scale();
 
-    if (top)
+    if (pTop)
     {
-        top->x = r.x;
-        top->y = r.y;
-        top->w = r.w;
-        top->h = r.h - cut;
+        pTop->x = r.x;
+        pTop->y = r.y;
+        pTop->w = r.w;
+        pTop->h = r.h - Cut;
     }
 
-    if (bottom)
+    if (pBottom)
     {
-        bottom->x = r.x;
-        bottom->y = r.y + r.h - cut;
-        bottom->w = r.w;
-        bottom->h = cut;
+        pBottom->x = r.x;
+        pBottom->y = r.y + r.h - Cut;
+        pBottom->w = r.w;
+        pBottom->h = Cut;
     }
 }
 
 
-void CUIRect::VSplitMid(CUIRect *left, CUIRect *right) const
+void CUIRect::VSplitMid(CUIRect *pLeft, CUIRect *pRight) const
 {
     CUIRect r = *this;
-    float cut = r.w/2;
+    float Cut = r.w/2;
 
-    if (left)
+    if (pLeft)
     {
-        left->x = r.x;
-        left->y = r.y;
-        left->w = cut;
-        left->h = r.h;
+        pLeft->x = r.x;
+        pLeft->y = r.y;
+        pLeft->w = Cut;
+        pLeft->h = r.h;
     }
 
-    if (right)
+    if (pRight)
     {
-        right->x = r.x + cut;
-        right->y = r.y;
-        right->w = r.w - cut;
-        right->h = r.h;
+        pRight->x = r.x + Cut;
+        pRight->y = r.y;
+        pRight->w = r.w - Cut;
+        pRight->h = r.h;
     }
 }
 
-void CUIRect::VSplitLeft(float cut, CUIRect *left, CUIRect *right) const
+void CUIRect::VSplitLeft(float Cut, CUIRect *pLeft, CUIRect *pRight) const
 {
     CUIRect r = *this;
-    cut *= Scale();
+    Cut *= Scale();
 
-    if (left)
+    if (pLeft)
     {
-        left->x = r.x;
-        left->y = r.y;
-        left->w = cut;
-        left->h = r.h;
+        pLeft->x = r.x;
+        pLeft->y = r.y;
+        pLeft->w = Cut;
+        pLeft->h = r.h;
     }
 
-    if (right)
+    if (pRight)
     {
-        right->x = r.x + cut;
-        right->y = r.y;
-        right->w = r.w - cut;
-        right->h = r.h;
+        pRight->x = r.x + Cut;
+        pRight->y = r.y;
+        pRight->w = r.w - Cut;
+        pRight->h = r.h;
     }
 }
 
-void CUIRect::VSplitRight(float cut, CUIRect *left, CUIRect *right) const
+void CUIRect::VSplitRight(float Cut, CUIRect *pLeft, CUIRect *pRight) const
 {
     CUIRect r = *this;
-    cut *= Scale();
+    Cut *= Scale();
 
-    if (left)
+    if (pLeft)
     {
-        left->x = r.x;
-        left->y = r.y;
-        left->w = r.w - cut;
-        left->h = r.h;
+        pLeft->x = r.x;
+        pLeft->y = r.y;
+        pLeft->w = r.w - Cut;
+        pLeft->h = r.h;
     }
 
-    if (right)
+    if (pRight)
     {
-        right->x = r.x + r.w - cut;
-        right->y = r.y;
-        right->w = cut;
-        right->h = r.h;
+        pRight->x = r.x + r.w - Cut;
+        pRight->y = r.y;
+        pRight->w = Cut;
+        pRight->h = r.h;
     }
 }
 
-void CUIRect::Margin(float cut, CUIRect *other_rect) const
+void CUIRect::Margin(float Cut, CUIRect *pOtherRect) const
 {
     CUIRect r = *this;
-	cut *= Scale();
+	Cut *= Scale();
 
-    other_rect->x = r.x + cut;
-    other_rect->y = r.y + cut;
-    other_rect->w = r.w - 2*cut;
-    other_rect->h = r.h - 2*cut;
+    pOtherRect->x = r.x + Cut;
+    pOtherRect->y = r.y + Cut;
+    pOtherRect->w = r.w - 2*Cut;
+    pOtherRect->h = r.h - 2*Cut;
 }
 
-void CUIRect::VMargin(float cut, CUIRect *other_rect) const
+void CUIRect::VMargin(float Cut, CUIRect *pOtherRect) const
 {
     CUIRect r = *this;
-	cut *= Scale();
+	Cut *= Scale();
 
-    other_rect->x = r.x + cut;
-    other_rect->y = r.y;
-    other_rect->w = r.w - 2*cut;
-    other_rect->h = r.h;
+    pOtherRect->x = r.x + Cut;
+    pOtherRect->y = r.y;
+    pOtherRect->w = r.w - 2*Cut;
+    pOtherRect->h = r.h;
 }
 
-void CUIRect::HMargin(float cut, CUIRect *other_rect) const
+void CUIRect::HMargin(float Cut, CUIRect *pOtherRect) const
 {
     CUIRect r = *this;
-	cut *= Scale();
+	Cut *= Scale();
 
-    other_rect->x = r.x;
-    other_rect->y = r.y + cut;
-    other_rect->w = r.w;
-    other_rect->h = r.h - 2*cut;
+    pOtherRect->x = r.x;
+    pOtherRect->y = r.y + Cut;
+    pOtherRect->w = r.w;
+    pOtherRect->h = r.h - 2*Cut;
 }
 
 int CUI::DoButtonLogic(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
 {
-    /* logic */
+    // logic
     int ReturnValue = 0;
     int Inside = MouseInside(pRect);
 	static int ButtonUsed = 0;
@@ -308,21 +308,21 @@ int CUI::DoButton(const void *id, const char *text, int checked, const CUIRect *
     return ret;
 }*/
 
-void CUI::DoLabel(const CUIRect *r, const char *text, float size, int align, int max_width)
+void CUI::DoLabel(const CUIRect *r, const char *pText, float size, int Align, int MaxWidth)
 {
 	// TODO: FIX ME!!!!
     //Graphics()->BlendNormal();
     size *= Scale();
-    if(align == 0)
+    if(Align == 0)
     {
-    	float tw = gfx_text_width(0, size, text, max_width);
-    	gfx_text(0, r->x + r->w/2-tw/2, r->y, size, text, max_width);
+    	float tw = TextRender()->TextWidth(0, size, pText, MaxWidth);
+    	TextRender()->Text(0, r->x + r->w/2-tw/2, r->y - size/10, size, pText, MaxWidth);
 	}
-	else if(align < 0)
-    	gfx_text(0, r->x, r->y, size, text, max_width);
-	else if(align > 0)
+	else if(Align < 0)
+    	TextRender()->Text(0, r->x, r->y - size/10, size, pText, MaxWidth);
+	else if(Align > 0)
 	{
-    	float tw = gfx_text_width(0, size, text, max_width);
-    	gfx_text(0, r->x + r->w-tw, r->y, size, text, max_width);
+    	float tw = TextRender()->TextWidth(0, size, pText, MaxWidth);
+    	TextRender()->Text(0, r->x + r->w-tw, r->y - size/10, size, pText, MaxWidth);
 	}
 }
diff --git a/src/game/client/ui.hpp b/src/game/client/ui.h
index 96f6c48b..e88b0e39 100644
--- a/src/game/client/ui.hpp
+++ b/src/game/client/ui.h
@@ -1,6 +1,5 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef FILE_GAME_CLIENT_UI_H
-#define FILE_GAME_CLIENT_UI_H
+#ifndef GAME_CLIENT_UI_H
+#define GAME_CLIENT_UI_H
 
 class CUIRect
 {
@@ -27,18 +26,20 @@ class CUI
 	const void *m_pActiveItem;
 	const void *m_pLastActiveItem;
 	const void *m_pBecommingHotItem;
-	float m_MouseX, m_MouseY; /* in gui space */
-	float m_MouseWorldX, m_MouseWorldY; /* in world space */
+	float m_MouseX, m_MouseY; // in gui space
+	float m_MouseWorldX, m_MouseWorldY; // in world space
 	unsigned m_MouseButtons;
 	unsigned m_LastMouseButtons;
 	
 	CUIRect m_Screen;
 	class IGraphics *m_pGraphics;
+	class ITextRender *m_pTextRender;
 	
 public:
 	// TODO: Refactor: Fill this in
-	void SetGraphics(class IGraphics *pGraphics) { m_pGraphics = pGraphics; }
+	void SetGraphics(class IGraphics *pGraphics, class ITextRender *pTextRender) { m_pGraphics = pGraphics; m_pTextRender = pTextRender;}
 	class IGraphics *Graphics() { return m_pGraphics; }
+	class ITextRender *TextRender() { return m_pTextRender; }
 
 	CUI();
 
@@ -57,7 +58,7 @@ public:
 		CORNER_ALL=CORNER_T|CORNER_B
 	};
 
-	int Update(float mx, float my, float mwx, float mwy, int buttons);
+	int Update(float mx, float my, float Mwx, float Mwy, int m_Buttons);
 
 	float MouseX() const { return m_MouseX; }
 	float MouseY() const { return m_MouseY; }
@@ -74,10 +75,10 @@ public:
 	const void *ActiveItem() const { return m_pActiveItem; }
 	const void *LastActiveItem() const { return m_pLastActiveItem; }
 
-	int MouseInside(const CUIRect *r);
+	int MouseInside(const CUIRect *pRect);
 
 	CUIRect *Screen();
-	void ClipEnable(const CUIRect *r);
+	void ClipEnable(const CUIRect *pRect);
 	void ClipDisable();
 	
 	// TODO: Refactor: Redo UI scaling
@@ -87,7 +88,7 @@ public:
 	int DoButtonLogic(const void *pID, const char *pText /* TODO: Refactor: Remove */, int Checked, const CUIRect *pRect);
 	
 	// TODO: Refactor: Remove this?
-	void DoLabel(const CUIRect *r, const char *text, float size, int align, int max_width = -1);
+	void DoLabel(const CUIRect *pRect, const char *pText, float Size, int Align, int MaxWidth = -1);
 };
 
 
diff --git a/src/game/collision.cpp b/src/game/collision.cpp
index 73f4a9c5..0dee57c8 100644
--- a/src/game/collision.cpp
+++ b/src/game/collision.cpp
@@ -1,87 +1,202 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
 #include <base/system.h>
-#include <base/math.hpp>
-#include <base/vmath.hpp>
+#include <base/math.h>
+#include <base/vmath.h>
 
 #include <math.h>
-#include <engine/e_common_interface.h>
-#include <game/mapitems.hpp>
-#include <game/layers.hpp>
-#include <game/collision.hpp>
+#include <engine/map.h>
+#include <engine/kernel.h>
 
-static TILE *tiles;
-static int width = 0;
-static int height = 0;
+#include <game/mapitems.h>
+#include <game/layers.h>
+#include <game/collision.h>
 
-int col_width() { return width; }
-int col_height() { return height; }
+CCollision::CCollision()
+{
+	m_pTiles = 0;
+	m_Width = 0;
+	m_Height = 0;
+	m_pLayers = 0;
+}
 
-int col_init()
+void CCollision::Init(class CLayers *pLayers)
 {
-	width = layers_game_layer()->width;
-	height = layers_game_layer()->height;
-	tiles = (TILE *)map_get_data(layers_game_layer()->data);
+	m_pLayers = pLayers;
+	m_Width = m_pLayers->GameLayer()->m_Width;
+	m_Height = m_pLayers->GameLayer()->m_Height;
+	m_pTiles = static_cast<CTile *>(m_pLayers->Map()->GetData(m_pLayers->GameLayer()->m_Data));
 	
-	for(int i = 0; i < width*height; i++)
+	for(int i = 0; i < m_Width*m_Height; i++)
 	{
-		int index = tiles[i].index;
+		int Index = m_pTiles[i].m_Index;
 		
-		if(index > 128)
+		if(Index > 128)
 			continue;
 		
-		if(index == TILE_DEATH)
-			tiles[i].index = COLFLAG_DEATH;
-		else if(index == TILE_SOLID)
-			tiles[i].index = COLFLAG_SOLID;
-		else if(index == TILE_NOHOOK)
-			tiles[i].index = COLFLAG_SOLID|COLFLAG_NOHOOK;
-		else
-			tiles[i].index = 0;
+		switch(Index)
+		{
+		case TILE_DEATH:
+			m_pTiles[i].m_Index = COLFLAG_DEATH;
+			break;
+		case TILE_SOLID:
+			m_pTiles[i].m_Index = COLFLAG_SOLID;
+			break;
+		case TILE_NOHOOK:
+			m_pTiles[i].m_Index = COLFLAG_SOLID|COLFLAG_NOHOOK;
+			break;
+		default:
+			m_pTiles[i].m_Index = 0;
+		}
 	}
-				
-	return 1;
 }
 
-
-int col_get(int x, int y)
+int CCollision::GetTile(int x, int y)
 {
-	int nx = clamp(x/32, 0, width-1);
-	int ny = clamp(y/32, 0, height-1);
+	int nx = clamp(x/32, 0, m_Width-1);
+	int ny = clamp(y/32, 0, m_Height-1);
 	
-	if(tiles[ny*width+nx].index > 128)
-		return 0;
-	return tiles[ny*width+nx].index;
+	return m_pTiles[ny*m_Width+nx].m_Index > 128 ? 0 : m_pTiles[ny*m_Width+nx].m_Index;
 }
 
-int col_is_solid(int x, int y)
+bool CCollision::IsTileSolid(int x, int y)
 {
-	return col_get(x,y)&COLFLAG_SOLID;
+	return GetTile(x,y)&COLFLAG_SOLID;
 }
 
-
 // TODO: rewrite this smarter!
-int col_intersect_line(vec2 pos0, vec2 pos1, vec2 *out_collision, vec2 *out_before_collision)
+int CCollision::IntersectLine(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision)
 {
-	float d = distance(pos0, pos1);
-	vec2 last = pos0;
+	float d = distance(Pos0, Pos1);
+	vec2 Last = Pos0;
 	
 	for(float f = 0; f < d; f++)
 	{
 		float a = f/d;
-		vec2 pos = mix(pos0, pos1, a);
-		if(col_is_solid(round(pos.x), round(pos.y)))
+		vec2 Pos = mix(Pos0, Pos1, a);
+		if(CheckPoint(Pos.x, Pos.y))
 		{
-			if(out_collision)
-				*out_collision = pos;
-			if(out_before_collision)
-				*out_before_collision = last;
-			return col_get(round(pos.x), round(pos.y));
+			if(pOutCollision)
+				*pOutCollision = Pos;
+			if(pOutBeforeCollision)
+				*pOutBeforeCollision = Last;
+			return GetCollisionAt(Pos.x, Pos.y);
 		}
-		last = pos;
+		Last = Pos;
 	}
-	if(out_collision)
-		*out_collision = pos1;
-	if(out_before_collision)
-		*out_before_collision = pos1;
+	if(pOutCollision)
+		*pOutCollision = Pos1;
+	if(pOutBeforeCollision)
+		*pOutBeforeCollision = Pos1;
 	return 0;
 }
+
+// TODO: OPT: rewrite this smarter!
+void CCollision::MovePoint(vec2 *pInoutPos, vec2 *pInoutVel, float Elasticity, int *pBounces)
+{
+	if(pBounces)
+		*pBounces = 0;
+	
+	vec2 Pos = *pInoutPos;
+	vec2 Vel = *pInoutVel;
+	if(CheckPoint(Pos + Vel))
+	{
+		int Affected = 0;
+		if(CheckPoint(Pos.x + Vel.x, Pos.y))
+		{
+			pInoutVel->x *= -Elasticity;
+			if(pBounces)
+				(*pBounces)++;			
+			Affected++;
+		}
+
+		if(CheckPoint(Pos.x, Pos.y + Vel.y))
+		{
+			pInoutVel->y *= -Elasticity;
+			if(pBounces)
+				(*pBounces)++;			
+			Affected++;
+		}
+		
+		if(Affected == 0)
+		{
+			pInoutVel->x *= -Elasticity;
+			pInoutVel->y *= -Elasticity;
+		}
+	}
+	else
+	{
+		*pInoutPos = Pos + Vel;
+	}
+}
+
+bool CCollision::TestBox(vec2 Pos, vec2 Size)
+{
+	Size *= 0.5f;
+	if(CheckPoint(Pos.x-Size.x, Pos.y-Size.y))
+		return true;
+	if(CheckPoint(Pos.x+Size.x, Pos.y-Size.y))
+		return true;
+	if(CheckPoint(Pos.x-Size.x, Pos.y+Size.y))
+		return true;
+	if(CheckPoint(Pos.x+Size.x, Pos.y+Size.y))
+		return true;
+	return false;
+}
+
+void CCollision::MoveBox(vec2 *pInoutPos, vec2 *pInoutVel, vec2 Size, float Elasticity)
+{
+	// do the move
+	vec2 Pos = *pInoutPos;
+	vec2 Vel = *pInoutVel;
+	
+	float Distance = length(Vel);
+	int Max = (int)Distance;
+	
+	if(Distance > 0.00001f)
+	{
+		//vec2 old_pos = pos;
+		float Fraction = 1.0f/(float)(Max+1);
+		for(int i = 0; i <= Max; i++)
+		{
+			//float amount = i/(float)max;
+			//if(max == 0)
+				//amount = 0;
+			
+			vec2 NewPos = Pos + Vel*Fraction; // TODO: this row is not nice
+			
+			if(TestBox(vec2(NewPos.x, NewPos.y), Size))
+			{
+				int Hits = 0;
+				
+				if(TestBox(vec2(Pos.x, NewPos.y), Size))
+				{
+					NewPos.y = Pos.y;
+					Vel.y *= -Elasticity;
+					Hits++;
+				}
+				
+				if(TestBox(vec2(NewPos.x, Pos.y), Size))
+				{
+					NewPos.x = Pos.x;
+					Vel.x *= -Elasticity;
+					Hits++;
+				}
+				
+				// neither of the tests got a collision.
+				// this is a real _corner case_!
+				if(Hits == 0)
+				{
+					NewPos.y = Pos.y;
+					Vel.y *= -Elasticity;
+					NewPos.x = Pos.x;
+					Vel.x *= -Elasticity;
+				}
+			}
+			
+			Pos = NewPos;
+		}
+	}
+	
+	*pInoutPos = Pos;
+	*pInoutVel = Vel;
+}
diff --git a/src/game/collision.h b/src/game/collision.h
new file mode 100644
index 00000000..66603890
--- /dev/null
+++ b/src/game/collision.h
@@ -0,0 +1,37 @@
+#ifndef GAME_COLLISION_H
+#define GAME_COLLISION_H
+
+#include <base/vmath.h>
+
+class CCollision
+{
+	class CTile *m_pTiles;
+	int m_Width;
+	int m_Height;
+	class CLayers *m_pLayers;
+
+	bool IsTileSolid(int x, int y);
+	int GetTile(int x, int y);
+
+public:
+	enum
+	{
+		COLFLAG_SOLID=1,
+		COLFLAG_DEATH=2,
+		COLFLAG_NOHOOK=4,
+	};
+
+	CCollision();
+	void Init(class CLayers *pLayers);
+	bool CheckPoint(float x, float y) { return IsTileSolid(round(x), round(y)); }
+	bool CheckPoint(vec2 p) { return CheckPoint(p.x, p.y); }
+	int GetCollisionAt(float x, float y) { return GetTile(round(x), round(y)); }
+	int GetWidth() { return m_Width; };
+	int GetHeight() { return m_Height; };
+	int IntersectLine(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision);
+	void MovePoint(vec2 *pInoutPos, vec2 *pInoutVel, float Elasticity, int *Bpounces);
+	void MoveBox(vec2 *pInoutPos, vec2 *pInoutVel, vec2 Size, float Elasticity);
+	bool TestBox(vec2 Pos, vec2 Size);
+};
+
+#endif
diff --git a/src/game/collision.hpp b/src/game/collision.hpp
deleted file mode 100644
index 0f072daa..00000000
--- a/src/game/collision.hpp
+++ /dev/null
@@ -1,21 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef GAME_MAPRES_COL_H
-#define GAME_MAPRES_COL_H
-
-#include <base/vmath.hpp>
-
-enum
-{
-	COLFLAG_SOLID=1,
-	COLFLAG_DEATH=2,
-	COLFLAG_NOHOOK=4,
-};
-
-int col_init();
-int col_is_solid(int x, int y);
-int col_get(int x, int y);
-int col_width();
-int col_height();
-int col_intersect_line(vec2 pos0, vec2 pos1, vec2 *out_collision, vec2 *out_before_collision);
-
-#endif
diff --git a/src/game/editor/array.hpp b/src/game/editor/array.hpp
deleted file mode 100755
index fe9f2739..00000000
--- a/src/game/editor/array.hpp
+++ /dev/null
@@ -1,238 +0,0 @@
-

-template <class T>

-class array

-{

-	// 

-	//

-	void init()

-	{

-		list = 0;

-		clear();

-	}

-

-public:

-	array()

-	{

-		init();

-	}

-	

-	//

-	array(const array &other)

-	{

-		init();

-		setsize(other.len());

-		for(int i = 0; i < len(); i++)

-			(*this)[i] = other[i];

-	}

-

-

-	// 

-	//

-	virtual ~array()

-	{

-		delete [] list;

-		list = 0;

-	}

-

-	//

-	//

-	void deleteall()

-	{

-		for(int i = 0; i < len(); i++)

-			delete list[i];

-

-		clear();

-	}

-

-

-	//

-	//

-	void clear()

-	{

-		delete [] list;

-		

-		list_size = 1;

-		list = new T[1];

-		num_elements = 0;

-	}

-

-	int find(T val)

-	{

-		for(int i = 0; i < len(); i++)

-			if((*this)[i] == val)

-				return i;

-		return -1;

-	}

-

-	bool exist(T val)

-	{

-		return find(val) != -1;

-	}

-

-	//

-	// returns the number of elements in the list

-	//

-	int len() const

-	{

-		return num_elements;

-	}

-

-	//

-	// This doesn't conserve the order in the list. Be careful

-	//

-	void removebyindexfast(int index)

-	{

-		//ASSUME(_Pos >= 0 && _Pos < num_elements);

-		list[index] = list[num_elements-1];

-		setsize(len()-1);

-	}

-

-	void removefast(const T& _Elem)

-	{

-		for(int i = 0; i < len(); i++)

-			if(list[i] == _Elem)

-			{

-				removebyindexfast(i);

-				return;

-			}

-	}

-

-	//

-	//

-	void removebyindex(int index)

-	{

-		//ASSUME(_Pos >= 0 && _Pos < num_elements);

-

-		for(int i = index+1; i < num_elements; i++)

-			list[i-1] = list[i];

-		

-		setsize(len()-1);

-	}

-

-	void insert(int index, const T& element)

-	{

-		int some_len = len();

-		if (index < some_len)

-			setsize(some_len+1);

-		else

-			setsize(index + 1);

-

-		for(int i = num_elements-2; i >= index; i--)

-			list[i+1] = list[i];

-

-		list[index] = element;

-	}

-

-	bool remove(const T& element)

-	{

-		for(int i = 0; i < len(); i++)

-			if(list[i] == element)

-			{

-				removebyindex(i);

-				return true;

-			}

-		return false;

-	}

-

-	// 

-	//

-	int add(const T& element)

-	{

-		//if(num_elements == list_size)

-		setsize(len()+1);

-		list[num_elements-1] = element;

-		return num_elements-1;

-	}

-

-	// 

-	//

-	int add(const T& elem, int index)

-	{

-		setsize(len()+1);

-		

-		for(int i = num_elements-1; i > index; i--)

-			list[i] = list[i-1];

-

-		list[index] = elem;

-		

-		//num_elements++;

-		return num_elements-1;

-	}

-

-	// 

-	//

-	T& operator[] (int index)

-	{

-		return list[index];

-	}

-

-	const T& operator[] (int index) const

-	{

-		return list[index];

-	}

-

-	//

-	//

-	T *getptr()

-	{

-		return list;

-	}

-

-	const T *getptr() const

-	{

-		return list;

-	}

-

-	//

-	//

-	//

-	void setsize(int new_len)

-	{

-		if (list_size < new_len)

-			allocsize(new_len);

-		num_elements = new_len;

-	}

-

-	// removes unnessasary data, returns how many bytes was earned

-	int optimize()

-	{

-		int Before = memoryusage();

-		setsize(num_elements);

-		return Before - memoryusage();

-	}

-

-	// returns how much memory this dynamic array is using

-	int memoryusage()

-	{

-		return sizeof(array) + sizeof(T)*list_size;

-	}

-

-	//

-	array &operator = (const array &other)

-	{

-		setsize(other.len());

-		for(int i = 0; i < len(); i++)

-			(*this)[i] = other[i];

-		return *this;

-	}		

-private:

-	void allocsize(int new_len)

-	{

-		list_size = new_len;

-		T *new_list = new T[list_size];

-		

-		long end = num_elements < list_size ? num_elements : list_size;

-		for(int i = 0; i < end; i++)

-			new_list[i] = list[i];

-		

-		delete [] list;

-		list = 0;

-		num_elements = num_elements < list_size ? num_elements : list_size;

-		list = new_list;

-	}

-

-	T *list;

-	long list_size;

-	long num_elements;

-};

-

diff --git a/src/game/editor/ed_editor.cpp b/src/game/editor/ed_editor.cpp
index 17b891fc..480a6827 100644
--- a/src/game/editor/ed_editor.cpp
+++ b/src/game/editor/ed_editor.cpp
@@ -1,185 +1,180 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
 
 #include <base/system.h>
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
 
-#include <engine/e_common_interface.h>
-#include <engine/e_datafile.h>
-#include <engine/e_config.h>
-#include <engine/e_engine.h>
-#include <engine/client/graphics.h>
+#include <engine/shared/datafile.h>
+#include <engine/shared/config.h>
+#include <engine/shared/engine.h>
+#include <engine/client.h>
+#include <engine/graphics.h>
+#include <engine/textrender.h>
+#include <engine/input.h>
+#include <engine/keys.h>
+#include <engine/storage.h>
 
-#include <game/client/ui.hpp>
-#include <game/gamecore.hpp>
-#include <game/client/render.hpp>
+#include <game/client/ui.h>
+#include <game/gamecore.h>
+#include <game/client/render.h>
 
-#include "ed_editor.hpp"
-#include <game/client/lineinput.hpp>
+#include "ed_editor.h"
+#include <game/client/lineinput.h>
 
-static int checker_texture = 0;
-static int background_texture = 0;
-static int cursor_texture = 0;
-static int entities_texture = 0;
+int CEditor::ms_CheckerTexture;
+int CEditor::ms_BackgroundTexture;
+int CEditor::ms_CursorTexture;
+int CEditor::ms_EntitiesTexture;
+const void* CEditor::ms_pUiGotContext;
 
 enum
 {
 	BUTTON_CONTEXT=1,
 };
 
-
-
-EDITOR_IMAGE::~EDITOR_IMAGE()
+CEditorImage::~CEditorImage()
 {
-	editor->Graphics()->UnloadTexture(tex_id);
+	m_pEditor->Graphics()->UnloadTexture(m_TexId);
 }
 
-static const void *ui_got_context = 0;
-
-LAYERGROUP::LAYERGROUP()
+CLayerGroup::CLayerGroup()
 {
-	name = "";
-	visible = true;
-	game_group = false;
-	offset_x = 0;
-	offset_y = 0;
-	parallax_x = 100;
-	parallax_y = 100;
-	
-	use_clipping = 0;
-	clip_x = 0;
-	clip_y = 0;
-	clip_w = 0;
-	clip_h = 0;
+	m_pName = "";
+	m_Visible = true;
+	m_GameGroup = false;
+	m_OffsetX = 0;
+	m_OffsetY = 0;
+	m_ParallaxX = 100;
+	m_ParallaxY = 100;
+
+	m_UseClipping = 0;
+	m_ClipX = 0;
+	m_ClipY = 0;
+	m_ClipW = 0;
+	m_ClipH = 0;
 }
 
-LAYERGROUP::~LAYERGROUP()
+CLayerGroup::~CLayerGroup()
 {
-	clear();
+	Clear();
 }
 
-void LAYERGROUP::convert(CUIRect *rect)
+void CLayerGroup::Convert(CUIRect *pRect)
 {
-	rect->x += offset_x;
-	rect->y += offset_y;
+	pRect->x += m_OffsetX;
+	pRect->y += m_OffsetY;
 }
 
-void LAYERGROUP::mapping(float *points)
+void CLayerGroup::Mapping(float *pPoints)
 {
-	m_pMap->editor->RenderTools()->mapscreen_to_world(
-		m_pMap->editor->world_offset_x, m_pMap->editor->world_offset_y,
-		parallax_x/100.0f, parallax_y/100.0f,
-		offset_x, offset_y,
-		m_pMap->editor->Graphics()->ScreenAspect(), m_pMap->editor->world_zoom, points);
-		
-	points[0] += m_pMap->editor->editor_offset_x;
-	points[1] += m_pMap->editor->editor_offset_y;
-	points[2] += m_pMap->editor->editor_offset_x;
-	points[3] += m_pMap->editor->editor_offset_y;
+	m_pMap->m_pEditor->RenderTools()->MapscreenToWorld(
+		m_pMap->m_pEditor->m_WorldOffsetX, m_pMap->m_pEditor->m_WorldOffsetY,
+		m_ParallaxX/100.0f, m_ParallaxY/100.0f,
+		m_OffsetX, m_OffsetY,
+		m_pMap->m_pEditor->Graphics()->ScreenAspect(), m_pMap->m_pEditor->m_WorldZoom, pPoints);
+
+	pPoints[0] += m_pMap->m_pEditor->m_EditorOffsetX;
+	pPoints[1] += m_pMap->m_pEditor->m_EditorOffsetY;
+	pPoints[2] += m_pMap->m_pEditor->m_EditorOffsetX;
+	pPoints[3] += m_pMap->m_pEditor->m_EditorOffsetY;
 }
 
-void LAYERGROUP::mapscreen()
+void CLayerGroup::MapScreen()
 {
-	float points[4];
-	mapping(points);
-	m_pMap->editor->Graphics()->MapScreen(points[0], points[1], points[2], points[3]);
+	float aPoints[4];
+	Mapping(aPoints);
+	m_pMap->m_pEditor->Graphics()->MapScreen(aPoints[0], aPoints[1], aPoints[2], aPoints[3]);
 }
 
-void LAYERGROUP::render()
+void CLayerGroup::Render()
 {
-	mapscreen();
-	IGraphics *pGraphics = m_pMap->editor->Graphics();
-	
-	if(use_clipping)
-	{
-		float points[4];
-		m_pMap->game_group->mapping(points);
-		float x0 = (clip_x - points[0]) / (points[2]-points[0]);
-		float y0 = (clip_y - points[1]) / (points[3]-points[1]);
-		float x1 = ((clip_x+clip_w) - points[0]) / (points[2]-points[0]);
-		float y1 = ((clip_y+clip_h) - points[1]) / (points[3]-points[1]);
-		
+	MapScreen();
+	IGraphics *pGraphics = m_pMap->m_pEditor->Graphics();
+
+	if(m_UseClipping)
+	{
+		float aPoints[4];
+		m_pMap->m_pGameGroup->Mapping(aPoints);
+		float x0 = (m_ClipX - aPoints[0]) / (aPoints[2]-aPoints[0]);
+		float y0 = (m_ClipY - aPoints[1]) / (aPoints[3]-aPoints[1]);
+		float x1 = ((m_ClipX+m_ClipW) - aPoints[0]) / (aPoints[2]-aPoints[0]);
+		float y1 = ((m_ClipY+m_ClipH) - aPoints[1]) / (aPoints[3]-aPoints[1]);
+
 		pGraphics->ClipEnable((int)(x0*pGraphics->ScreenWidth()), (int)(y0*pGraphics->ScreenHeight()),
 			(int)((x1-x0)*pGraphics->ScreenWidth()), (int)((y1-y0)*pGraphics->ScreenHeight()));
 	}
-	
-	for(int i = 0; i < layers.len(); i++)
+
+	for(int i = 0; i < m_lLayers.size(); i++)
 	{
-		if(layers[i]->visible && layers[i] != m_pMap->game_layer)
+		if(m_lLayers[i]->m_Visible && m_lLayers[i] != m_pMap->m_pGameLayer)
 		{
-			if(m_pMap->editor->show_detail || !(layers[i]->flags&LAYERFLAG_DETAIL))
-				layers[i]->render();
+			if(m_pMap->m_pEditor->m_ShowDetail || !(m_lLayers[i]->m_Flags&LAYERFLAG_DETAIL))
+				m_lLayers[i]->Render();
 		}
 	}
-	
+
 	pGraphics->ClipDisable();
 }
 
-bool LAYERGROUP::is_empty() const { return layers.len() == 0; }
-void LAYERGROUP::clear() { layers.deleteall(); }
-void LAYERGROUP::add_layer(LAYER *l) { layers.add(l); }
-
-void LAYERGROUP::delete_layer(int index)
+void CLayerGroup::DeleteLayer(int Index)
 {
-	if(index < 0 || index >= layers.len()) return;
-	delete layers[index];
-	layers.removebyindex(index);
-}	
+	if(Index < 0 || Index >= m_lLayers.size()) return;
+	delete m_lLayers[Index];
+	m_lLayers.remove_index(Index);
+}
 
-void LAYERGROUP::get_size(float *w, float *h)
+void CLayerGroup::GetSize(float *w, float *h)
 {
 	*w = 0; *h = 0;
-	for(int i = 0; i < layers.len(); i++)
+	for(int i = 0; i < m_lLayers.size(); i++)
 	{
 		float lw, lh;
-		layers[i]->get_size(&lw, &lh);
+		m_lLayers[i]->GetSize(&lw, &lh);
 		*w = max(*w, lw);
 		*h = max(*h, lh);
 	}
 }
 
 
-int LAYERGROUP::swap_layers(int index0, int index1)
+int CLayerGroup::SwapLayers(int Index0, int Index1)
 {
-	if(index0 < 0 || index0 >= layers.len()) return index0;
-	if(index1 < 0 || index1 >= layers.len()) return index0;
-	if(index0 == index1) return index0;
-	swap(layers[index0], layers[index1]);
-	return index1;
+	if(Index0 < 0 || Index0 >= m_lLayers.size()) return Index0;
+	if(Index1 < 0 || Index1 >= m_lLayers.size()) return Index0;
+	if(Index0 == Index1) return Index0;
+	swap(m_lLayers[Index0], m_lLayers[Index1]);
+	return Index1;
 }
 
-void EDITOR_IMAGE::analyse_tileflags()
+void CEditorImage::AnalyseTileFlags()
 {
-	mem_zero(tileflags, sizeof(tileflags));
-	
-	int tw = width/16; // tilesizes
-	int th = height/16;
-	if ( tw == th ) {
-		unsigned char *pixeldata = (unsigned char *)data;
-		
-		int tile_id = 0;
+	mem_zero(m_aTileFlags, sizeof(m_aTileFlags));
+
+	int tw = m_Width/16; // tilesizes
+	int th = m_Height/16;
+	if ( tw == th )
+    {
+		unsigned char *pPixelData = (unsigned char *)m_pData;
+
+		int TileId = 0;
 		for(int ty = 0; ty < 16; ty++)
-			for(int tx = 0; tx < 16; tx++, tile_id++)
+			for(int tx = 0; tx < 16; tx++, TileId++)
 			{
-				bool opaque = true;
+				bool Opaque = true;
 				for(int x = 0; x < tw; x++)
 					for(int y = 0; y < th; y++)
 					{
-						int p = (ty*tw+y)*width + tx*tw+x;
-						if(pixeldata[p*4+3] < 250)
+						int p = (ty*tw+y)*m_Width + tx*tw+x;
+						if(pPixelData[p*4+3] < 250)
 						{
-							opaque = false;
+							Opaque = false;
 							break;
 						}
 					}
-					
-				if(opaque)
-					tileflags[tile_id] |= TILEFLAG_OPAQUE;
+
+				if(Opaque)
+					m_aTileFlags[TileId] |= TILEFLAG_OPAQUE;
 			}
 	}
-	
+
 }
 
 /********************************************************
@@ -189,42 +184,42 @@ void EDITOR_IMAGE::analyse_tileflags()
 // copied from gc_menu.cpp, should be more generalized
 //extern int ui_do_edit_box(void *id, const CUIRect *rect, char *str, int str_size, float font_size, bool hidden=false);
 
-int EDITOR::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, bool Hidden)
+int CEditor::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, bool Hidden)
 {
     int Inside = UI()->MouseInside(pRect);
 	int ReturnValue = 0;
-	static int AtIndex = 0;
+	static int s_AtIndex = 0;
 
 	if(UI()->LastActiveItem() == pID)
 	{
-		int Len = strlen(pStr);
-			
+		int Len = str_length(pStr);
+
 		if(Inside && UI()->MouseButton(0))
 		{
-			int mx_rel = (int)(UI()->MouseX() - pRect->x);
+			int MxRel = (int)(UI()->MouseX() - pRect->x);
 
 			for (int i = 1; i <= Len; i++)
 			{
-				if (gfx_text_width(0, FontSize, pStr, i) + 10 > mx_rel)
+				if (TextRender()->TextWidth(0, FontSize, pStr, i) + 10 > MxRel)
 				{
-					AtIndex = i - 1;
+					s_AtIndex = i - 1;
 					break;
 				}
 
 				if (i == Len)
-					AtIndex = Len;
+					s_AtIndex = Len;
 			}
 		}
 
-		for(int i = 0; i < inp_num_events(); i++)
+		for(int i = 0; i < Input()->NumEvents(); i++)
 		{
-			Len = strlen(pStr);
-			LINEINPUT::manipulate(inp_get_event(i), pStr, StrSize, &Len, &AtIndex);
+			Len = str_length(pStr);
+			CLineInput::Manipulate(Input()->GetEvent(i), pStr, StrSize, &Len, &s_AtIndex);
 		}
 	}
 
 	bool JustGotActive = false;
-	
+
 	if(UI()->ActiveItem() == pID)
 	{
 		if(!UI()->MouseButton(0))
@@ -239,219 +234,138 @@ int EDITOR::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrS
 			UI()->SetActiveItem(pID);
 		}
 	}
-	
+
 	if(Inside)
 		UI()->SetHotItem(pID);
 
 	CUIRect Textbox = *pRect;
-	RenderTools()->DrawUIRect(&Textbox, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 5.0f);
-	Textbox.VMargin(5.0f, &Textbox);
-	
+	RenderTools()->DrawUIRect(&Textbox, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 3.0f);
+	Textbox.VMargin(3.0f, &Textbox);
+
 	const char *pDisplayStr = pStr;
 	char aStars[128];
-	
+
 	if(Hidden)
 	{
-		unsigned s = strlen(pStr);
+		unsigned s = str_length(pStr);
 		if(s >= sizeof(aStars))
 			s = sizeof(aStars)-1;
-		memset(aStars, '*', s);
+		for(unsigned int i = 0; i < s; ++i)
+			aStars[i] = '*';
 		aStars[s] = 0;
 		pDisplayStr = aStars;
 	}
 
 	UI()->DoLabel(&Textbox, pDisplayStr, FontSize, -1);
 	
-	if (UI()->LastActiveItem() == pID && !JustGotActive)
+	//TODO: make it blink
+	if(UI()->LastActiveItem() == pID && !JustGotActive)
 	{
-		float w = gfx_text_width(0, FontSize, pDisplayStr, AtIndex);
+		float w = TextRender()->TextWidth(0, FontSize, pDisplayStr, s_AtIndex);
+		Textbox = *pRect;
+		Textbox.VSplitLeft(2.0f, 0, &Textbox);
 		Textbox.x += w*UI()->Scale();
-		UI()->DoLabel(&Textbox, "_", FontSize, -1);
-	}
-
-	return ReturnValue;
-}
-
-/*
-int ui_do_edit_box(void *id, const CUIRect *rect, char *str, int str_size, float font_size, bool hidden=false)
-{
-    int inside = UI()->MouseInside(rect);
-	int r = 0;
-	static int at_index = 0;
-
-	if(UI()->LastActiveItem() == id)
-	{
-		int len = strlen(str);
-
-		if (inside && UI()->MouseButton(0))
-		{
-			int mx_rel = (int)(UI()->MouseX() - rect->x);
-
-			for (int i = 1; i <= len; i++)
-			{
-				if (gfx_text_width(0, font_size, str, i) + 10 > mx_rel)
-				{
-					at_index = i - 1;
-					break;
-				}
-
-				if (i == len)
-					at_index = len;
-			}
-		}
-
-		for(int i = 0; i < inp_num_events(); i++)
-		{
-			len = strlen(str);
-			LINEINPUT::manipulate(inp_get_event(i), str, str_size, &len, &at_index);
-		}
+		Textbox.y -= FontSize/10.f;
 		
-		r = 1;
-	}
-
-	bool just_got_active = false;
-	
-	if(UI()->ActiveItem() == id)
-	{
-		if(!UI()->MouseButton(0))
-			UI()->SetActiveItem(0);
-	}
-	else if(UI()->HotItem() == id)
-	{
-		if(UI()->MouseButton(0))
-		{
-			if (UI()->LastActiveItem() != id)
-				just_got_active = true;
-			UI()->SetActiveItem(id);
-		}
-	}
-	
-	if(inside)
-		UI()->SetHotItem(id);
-
-	CUIRect textbox = *rect;
-	RenderTools()->DrawUIRect(&textbox, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 5.0f);
-	textbox.VMargin(5.0f, &textbox);
-	
-	const char *display_str = str;
-	char stars[128];
-	
-	if(hidden)
-	{
-		unsigned s = strlen(str);
-		if(s >= sizeof(stars))
-			s = sizeof(stars)-1;
-		memset(stars, '*', s);
-		stars[s] = 0;
-		display_str = stars;
-	}
-
-	UI()->DoLabel(&textbox, display_str, font_size, -1);
-	
-	if (UI()->LastActiveItem() == id && !just_got_active)
-	{
-		float w = gfx_text_width(0, font_size, display_str, at_index);
-		textbox.x += w*UI()->Scale();
-		UI()->DoLabel(&textbox, "_", font_size, -1);
+		UI()->DoLabel(&Textbox, "|", FontSize*1.1f, -1);
 	}
 
-	return r;
+	return ReturnValue;
 }
-*/
 
-vec4 EDITOR::button_color_mul(const void *id)
+vec4 CEditor::ButtonColorMul(const void *pId)
 {
-	if(UI()->ActiveItem() == id)
+	if(UI()->ActiveItem() == pId)
 		return vec4(1,1,1,0.5f);
-	else if(UI()->HotItem() == id)
+	else if(UI()->HotItem() == pId)
 		return vec4(1,1,1,1.5f);
 	return vec4(1,1,1,1);
 }
 
-float EDITOR::ui_do_scrollbar_v(const void *id, const CUIRect *rect, float current)
+float CEditor::UiDoScrollbarV(const void *pId, const CUIRect *pRect, float Current)
 {
-	CUIRect handle;
-	static float offset_y;
-	rect->HSplitTop(33, &handle, 0);
+	CUIRect Handle;
+	static float s_OffsetY;
+	pRect->HSplitTop(33, &Handle, 0);
 
-	handle.y += (rect->h-handle.h)*current;
+	Handle.y += (pRect->h-Handle.h)*Current;
 
-	/* logic */
-    float ret = current;
-    int inside = UI()->MouseInside(&handle);
+	// logic
+    float Ret = Current;
+    int Inside = UI()->MouseInside(&Handle);
 
-	if(UI()->ActiveItem() == id)
+	if(UI()->ActiveItem() == pId)
 	{
 		if(!UI()->MouseButton(0))
 			UI()->SetActiveItem(0);
-		
-		float min = rect->y;
-		float max = rect->h-handle.h;
-		float cur = UI()->MouseY()-offset_y;
-		ret = (cur-min)/max;
-		if(ret < 0.0f) ret = 0.0f;
-		if(ret > 1.0f) ret = 1.0f;
+
+		float Min = pRect->y;
+		float Max = pRect->h-Handle.h;
+		float Cur = UI()->MouseY()-s_OffsetY;
+		Ret = (Cur-Min)/Max;
+		if(Ret < 0.0f) Ret = 0.0f;
+		if(Ret > 1.0f) Ret = 1.0f;
 	}
-	else if(UI()->HotItem() == id)
+	else if(UI()->HotItem() == pId)
 	{
 		if(UI()->MouseButton(0))
 		{
-			UI()->SetActiveItem(id);
-			offset_y = UI()->MouseY()-handle.y;
+			UI()->SetActiveItem(pId);
+			s_OffsetY = UI()->MouseY()-Handle.y;
 		}
 	}
-	
-	if(inside)
-		UI()->SetHotItem(id);
+
+	if(Inside)
+		UI()->SetHotItem(pId);
 
 	// render
-	CUIRect rail;
-	rect->VMargin(5.0f, &rail);
-	RenderTools()->DrawUIRect(&rail, vec4(1,1,1,0.25f), 0, 0.0f);
-
-	CUIRect slider = handle;
-	slider.w = rail.x-slider.x;
-	RenderTools()->DrawUIRect(&slider, vec4(1,1,1,0.25f), CUI::CORNER_L, 2.5f);
-	slider.x = rail.x+rail.w;
-	RenderTools()->DrawUIRect(&slider, vec4(1,1,1,0.25f), CUI::CORNER_R, 2.5f);
-
-	slider = handle;
-	slider.Margin(5.0f, &slider);
-	RenderTools()->DrawUIRect(&slider, vec4(1,1,1,0.25f)*button_color_mul(id), CUI::CORNER_ALL, 2.5f);
-	
-    return ret;
+	CUIRect Rail;
+	pRect->VMargin(5.0f, &Rail);
+	RenderTools()->DrawUIRect(&Rail, vec4(1,1,1,0.25f), 0, 0.0f);
+
+	CUIRect Slider = Handle;
+	Slider.w = Rail.x-Slider.x;
+	RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f), CUI::CORNER_L, 2.5f);
+	Slider.x = Rail.x+Rail.w;
+	RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f), CUI::CORNER_R, 2.5f);
+
+	Slider = Handle;
+	Slider.Margin(5.0f, &Slider);
+	RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f)*ButtonColorMul(pId), CUI::CORNER_ALL, 2.5f);
+
+    return Ret;
 }
 
-vec4 EDITOR::get_button_color(const void *id, int checked)
+vec4 CEditor::GetButtonColor(const void *pId, int Checked)
 {
-	if(checked < 0)
+	if(Checked < 0)
 		return vec4(0,0,0,0.5f);
-		
-	if(checked > 0)
+
+	if(Checked > 0)
 	{
-		if(UI()->HotItem() == id)
+		if(UI()->HotItem() == pId)
 			return vec4(1,0,0,0.75f);
 		return vec4(1,0,0,0.5f);
 	}
-	
-	if(UI()->HotItem() == id)
+
+	if(UI()->HotItem() == pId)
 		return vec4(1,1,1,0.75f);
 	return vec4(1,1,1,0.5f);
 }
 
-int EDITOR::DoButton_Editor_Common(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip)
+int CEditor::DoButton_Editor_Common(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip)
 {
 	if(UI()->MouseInside(pRect))
 	{
 		if(Flags&BUTTON_CONTEXT)
-			ui_got_context = pID;
-		if(tooltip)
-			tooltip = pToolTip;
+			ms_pUiGotContext = pID;
+		if(m_pTooltip)
+			m_pTooltip = pToolTip;
 	}
-	
+
 	if(UI()->HotItem() == pID && pToolTip)
-		tooltip = (const char *)pToolTip;
-	
+		m_pTooltip = (const char *)pToolTip;
+
 	return UI()->DoButtonLogic(pID, pText, Checked, pRect);
 
 	// Draw here
@@ -459,444 +373,399 @@ int EDITOR::DoButton_Editor_Common(const void *pID, const char *pText, int Check
 }
 
 
-int EDITOR::DoButton_Editor(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip)
+int CEditor::DoButton_Editor(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip)
 {
-	RenderTools()->DrawUIRect(pRect, get_button_color(pID, Checked), CUI::CORNER_ALL, 3.0f);
-	UI()->DoLabel(pRect, pText, 10, 0, -1);
+	RenderTools()->DrawUIRect(pRect, GetButtonColor(pID, Checked), CUI::CORNER_ALL, 3.0f);
+    CUIRect NewRect = *pRect;
+    NewRect.y += NewRect.h/2.0f-7.0f;
+    UI()->DoLabel(&NewRect, pText, 10, 0, -1);
 	return DoButton_Editor_Common(pID, pText, Checked, pRect, Flags, pToolTip);
 }
 
-int EDITOR::DoButton_File(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip)
+int CEditor::DoButton_File(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip)
 {
 	if(UI()->HotItem() == pID)
-		RenderTools()->DrawUIRect(pRect, get_button_color(pID, Checked), CUI::CORNER_ALL, 3.0f);
-	
+		RenderTools()->DrawUIRect(pRect, GetButtonColor(pID, Checked), CUI::CORNER_ALL, 3.0f);
+
 	CUIRect t = *pRect;
 	t.VMargin(5.0f, &t);
 	UI()->DoLabel(&t, pText, 10, -1, -1);
 	return DoButton_Editor_Common(pID, pText, Checked, pRect, Flags, pToolTip);
 }
 
-//static void draw_editor_button_menu(const void *id, const char *text, int checked, const CUIRect *rect, const void *extra)
-int EDITOR::DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip)
+int CEditor::DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip)
 {
-	/*
-	if(UI()->HotItem() == id) if(extra) editor.tooltip = (const char *)extra;
-	if(UI()->HotItem() == id)
-		RenderTools()->DrawUIRect(r, get_button_color(id, checked), CUI::CORNER_ALL, 3.0f);
-	*/
-
 	CUIRect r = *pRect;
-	/*
-	if(ui_popups[id == id)
-	{
-		RenderTools()->DrawUIRect(&r, vec4(0.5f,0.5f,0.5f,0.75f), CUI::CORNER_T, 3.0f);
-		r.Margin(1.0f, &r);
-		RenderTools()->DrawUIRect(&r, vec4(0,0,0,0.75f), CUI::CORNER_T, 3.0f);
-	}
-	else*/
-		RenderTools()->DrawUIRect(&r, vec4(0.5f,0.5f,0.5f, 1.0f), CUI::CORNER_T, 3.0f);
-	
+    RenderTools()->DrawUIRect(&r, vec4(0.5f, 0.5f, 0.5f, 1.0f), CUI::CORNER_T, 3.0f);
 
 	r = *pRect;
 	r.VMargin(5.0f, &r);
 	UI()->DoLabel(&r, pText, 10, -1, -1);
-	
 	return DoButton_Editor_Common(pID, pText, Checked, pRect, Flags, pToolTip);
-	
-	//CUIRect t = *r;
 }
 
-int EDITOR::DoButton_MenuItem(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip)
+int CEditor::DoButton_MenuItem(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip)
 {
 	if(UI()->HotItem() == pID || Checked)
-		RenderTools()->DrawUIRect(pRect, get_button_color(pID, Checked), CUI::CORNER_ALL, 3.0f);
-	
+		RenderTools()->DrawUIRect(pRect, GetButtonColor(pID, Checked), CUI::CORNER_ALL, 3.0f);
+
 	CUIRect t = *pRect;
 	t.VMargin(5.0f, &t);
 	UI()->DoLabel(&t, pText, 10, -1, -1);
 	return DoButton_Editor_Common(pID, pText, Checked, pRect, 0, 0);
 }
 
-int EDITOR::DoButton_ButtonL(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip)
-{
-	RenderTools()->DrawUIRect(pRect, get_button_color(pID, Checked), CUI::CORNER_L, 3.0f);
-	UI()->DoLabel(pRect, pText, 10, 0, -1);
-	return DoButton_Editor_Common(pID, pText, Checked, pRect, Flags, pToolTip);
-}
-
-int EDITOR::DoButton_ButtonM(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip)
+int CEditor::DoButton_Tab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip)
 {
-	RenderTools()->DrawUIRect(pRect, get_button_color(pID, Checked), 0, 3.0f);
-	UI()->DoLabel(pRect, pText, 10, 0, -1);
+	RenderTools()->DrawUIRect(pRect, GetButtonColor(pID, Checked), CUI::CORNER_T, 5.0f);
+    CUIRect NewRect = *pRect;
+    NewRect.y += NewRect.h/2.0f-7.0f;
+    UI()->DoLabel(&NewRect, pText, 10, 0, -1);
 	return DoButton_Editor_Common(pID, pText, Checked, pRect, Flags, pToolTip);
 }
 
-int EDITOR::DoButton_ButtonR(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip)
+int CEditor::DoButton_Ex(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip, int Corners)
 {
-	RenderTools()->DrawUIRect(pRect, get_button_color(pID, Checked), CUI::CORNER_R, 3.0f);
-	UI()->DoLabel(pRect, pText, 10, 0, -1);
+	RenderTools()->DrawUIRect(pRect, GetButtonColor(pID, Checked), Corners, 3.0f);
+    CUIRect NewRect = *pRect;
+    NewRect.y += NewRect.h/2.0f-7.0f;
+    UI()->DoLabel(&NewRect, pText, 10, 0, -1);
 	return DoButton_Editor_Common(pID, pText, Checked, pRect, Flags, pToolTip);
 }
 
-int EDITOR::DoButton_ButtonInc(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip)
+int CEditor::DoButton_ButtonInc(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip)
 {
-	RenderTools()->DrawUIRect(pRect, get_button_color(pID, Checked), CUI::CORNER_R, 3.0f);
-	UI()->DoLabel(pRect, pText?pText:">", 10, 0, -1);
+	RenderTools()->DrawUIRect(pRect, GetButtonColor(pID, Checked), CUI::CORNER_R, 3.0f);
+	UI()->DoLabel(pRect, pText?pText:"+", 10, 0, -1);
 	return DoButton_Editor_Common(pID, pText, Checked, pRect, Flags, pToolTip);
 }
 
-int EDITOR::DoButton_ButtonDec(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip)
+int CEditor::DoButton_ButtonDec(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip)
 {
-	RenderTools()->DrawUIRect(pRect, get_button_color(pID, Checked), CUI::CORNER_L, 3.0f);
-	UI()->DoLabel(pRect, pText?pText:"<", 10, 0, -1);
+	RenderTools()->DrawUIRect(pRect, GetButtonColor(pID, Checked), CUI::CORNER_L, 3.0f);
+	UI()->DoLabel(pRect, pText?pText:"-", 10, 0, -1);
 	return DoButton_Editor_Common(pID, pText, Checked, pRect, Flags, pToolTip);
 }
 
-/*
-static void draw_editor_button_l(const void *id, const char *text, int checked, const CUIRect *r, const void *extra)
-{
-	RenderTools()->DrawUIRect(r, get_button_color(id, checked), CUI::CORNER_L, 3.0f);
-	UI()->DoLabel(r, text, 10, 0, -1);
-}
-
-static void draw_editor_button_m(const void *id, const char *text, int checked, const CUIRect *r, const void *extra)
-{
-	if(UI()->HotItem() == id) if(extra) editor.tooltip = (const char *)extra;
-	RenderTools()->DrawUIRect(r, get_button_color(id, checked), 0, 3.0f);
-	UI()->DoLabel(r, text, 10, 0, -1);
-}
-
-static void draw_editor_button_r(const void *id, const char *text, int checked, const CUIRect *r, const void *extra)
-{
-	if(UI()->HotItem() == id) if(extra) editor.tooltip = (const char *)extra;
-	RenderTools()->DrawUIRect(r, get_button_color(id, checked), CUI::CORNER_R, 3.0f);
-	UI()->DoLabel(r, text, 10, 0, -1);
-}
-
-static void draw_inc_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra)
+void CEditor::RenderBackground(CUIRect View, int Texture, float Size, float Brightness)
 {
-	if(UI()->HotItem == id) if(extra) editor.tooltip = (const char *)extra;
-	RenderTools()->DrawUIRect(r, get_button_color(id, checked), CUI::CORNER_R, 3.0f);
-	UI()->DoLabel(r, text?text:">", 10, 0, -1);
-}
-
-static void draw_dec_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra)
-{
-	if(UI()->HotItem == id) if(extra) editor.tooltip = (const char *)extra;
-	RenderTools()->DrawUIRect(r, get_button_color(id, checked), CUI::CORNER_L, 3.0f);
-	UI()->DoLabel(r, text?text:"<", 10, 0, -1);
-}
-
-int do_editor_button(const void *id, const char *text, int checked, const CUIRect *r, ui_draw_button_func draw_func, int flags, const char *tooltip)
-{
-	if(UI()->MouseInside(r))
-	{
-		if(flags&BUTTON_CONTEXT)
-			ui_got_context = id;
-		if(tooltip)
-			editor.tooltip = tooltip;
-	}
-	
-	return UI()->DoButton(id, text, checked, r, draw_func, 0);
-}*/
-
-
-void EDITOR::render_background(CUIRect view, int texture, float size, float brightness)
-{
-	Graphics()->TextureSet(texture);
+	Graphics()->TextureSet(Texture);
 	Graphics()->BlendNormal();
 	Graphics()->QuadsBegin();
-	Graphics()->SetColor(brightness,brightness,brightness,1.0f);
-	Graphics()->QuadsSetSubset(0,0, view.w/size, view.h/size);
-	Graphics()->QuadsDrawTL(view.x, view.y, view.w, view.h);
+	Graphics()->SetColor(Brightness, Brightness, Brightness, 1.0f);
+	Graphics()->QuadsSetSubset(0,0, View.w/Size, View.h/Size);
+	IGraphics::CQuadItem QuadItem(View.x, View.y, View.w, View.h);
+	Graphics()->QuadsDrawTL(&QuadItem, 1);
 	Graphics()->QuadsEnd();
 }
 
-static LAYERGROUP brush;
-static LAYER_TILES tileset_picker(16, 16);
-
-int EDITOR::ui_do_value_selector(void *id, CUIRect *r, const char *label, int current, int min, int max, float scale)
+int CEditor::UiDoValueSelector(void *pId, CUIRect *r, const char *pLabel, int Current, int Min, int Max, float Scale)
 {
-    /* logic */
-    static float value;
-    int ret = 0;
-    int inside = UI()->MouseInside(r);
+    // logic
+    static float s_Value;
+    int Ret = 0;
+    int Inside = UI()->MouseInside(r);
 
-	if(UI()->ActiveItem() == id)
+	if(UI()->ActiveItem() == pId)
 	{
 		if(!UI()->MouseButton(0))
 		{
-			if(inside)
-				ret = 1;
-			lock_mouse = false;
+			if(Inside)
+				Ret = 1;
+			m_LockMouse = false;
 			UI()->SetActiveItem(0);
 		}
 		else
 		{
-			if(inp_key_pressed(KEY_LSHIFT) || inp_key_pressed(KEY_RSHIFT))
-				value += mouse_delta_x*0.05f;
+			if(Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT))
+				s_Value += m_MouseDeltaX*0.05f;
 			else
-				value += mouse_delta_x;
-			
-			if(fabs(value) > scale)
+				s_Value += m_MouseDeltaX;
+
+			if(absolute(s_Value) > Scale)
 			{
-				int count = (int)(value/scale);
-				value = fmod(value, scale);
-				current += count;
-				if(current < min)
-					current = min;
-				if(current > max)
-					current = max;
+				int Count = (int)(s_Value/Scale);
+				s_Value = fmod(s_Value, Scale);
+				Current += Count;
+				if(Current < Min)
+					Current = Min;
+				if(Current > Max)
+					Current = Max;
 			}
 		}
 	}
-	else if(UI()->HotItem() == id)
+	else if(UI()->HotItem() == pId)
 	{
 		if(UI()->MouseButton(0))
 		{
-			lock_mouse = true;
-			value = 0;
-			UI()->SetActiveItem(id);
+			m_LockMouse = true;
+			s_Value = 0;
+			UI()->SetActiveItem(pId);
 		}
 	}
-	
-	if(inside)
-		UI()->SetHotItem(id);
+
+	if(Inside)
+		UI()->SetHotItem(pId);
 
 	// render
-	char buf[128];
-	sprintf(buf, "%s %d", label, current);
-	RenderTools()->DrawUIRect(r, get_button_color(id, 0), CUI::CORNER_ALL, 5.0f);
-	UI()->DoLabel(r, buf, 10, 0, -1);
-	return current;
+	char aBuf[128];
+	str_format(aBuf, sizeof(aBuf),"%s %d", pLabel, Current);
+	RenderTools()->DrawUIRect(r, GetButtonColor(pId, 0), CUI::CORNER_ALL, 5.0f);
+    r->y += r->h/2.0f-7.0f;
+    UI()->DoLabel(r, aBuf, 10, 0, -1);
+    
+	return Current;
 }
 
-LAYERGROUP *EDITOR::get_selected_group()
+CLayerGroup *CEditor::GetSelectedGroup()
 {
-	if(selected_group >= 0 && selected_group < map.groups.len())
-		return map.groups[selected_group];
+	if(m_SelectedGroup >= 0 && m_SelectedGroup < m_Map.m_lGroups.size())
+		return m_Map.m_lGroups[m_SelectedGroup];
 	return 0x0;
 }
 
-LAYER *EDITOR::get_selected_layer(int index)
+CLayer *CEditor::GetSelectedLayer(int Index)
 {
-	LAYERGROUP *group = get_selected_group();
-	if(!group)
+	CLayerGroup *pGroup = GetSelectedGroup();
+	if(!pGroup)
 		return 0x0;
 
-	if(selected_layer >= 0 && selected_layer < map.groups[selected_group]->layers.len())
-		return group->layers[selected_layer];
+	if(m_SelectedLayer >= 0 && m_SelectedLayer < m_Map.m_lGroups[m_SelectedGroup]->m_lLayers.size())
+		return pGroup->m_lLayers[m_SelectedLayer];
 	return 0x0;
 }
 
-LAYER *EDITOR::get_selected_layer_type(int index, int type)
+CLayer *CEditor::GetSelectedLayerType(int Index, int Type)
 {
-	LAYER *p = get_selected_layer(index);
-	if(p && p->type == type)
+	CLayer *p = GetSelectedLayer(Index);
+	if(p && p->m_Type == Type)
 		return p;
 	return 0x0;
 }
 
-QUAD *EDITOR::get_selected_quad()
+CQuad *CEditor::GetSelectedQuad()
 {
-	LAYER_QUADS *ql = (LAYER_QUADS *)get_selected_layer_type(0, LAYERTYPE_QUADS);
+	CLayerQuads *ql = (CLayerQuads *)GetSelectedLayerType(0, LAYERTYPE_QUADS);
 	if(!ql)
 		return 0;
-	if(selected_quad >= 0 && selected_quad < ql->quads.len())
-		return &ql->quads[selected_quad];
+	if(m_SelectedQuad >= 0 && m_SelectedQuad < ql->m_lQuads.size())
+		return &ql->m_lQuads[m_SelectedQuad];
 	return 0;
 }
 
-static void callback_open_map(const char *filename, void *user) { ((EDITOR*)user)->load(filename); }
-static void callback_append_map(const char *filename, void *user) { ((EDITOR*)user)->append(filename); }
-static void callback_save_map(const char *filename, void *user) { ((EDITOR*)user)->save(filename); }
+static void CallbackOpenMap(const char *pFileName, void *pUser) { if(((CEditor*)pUser)->Load(pFileName)) str_copy(((CEditor*)pUser)->m_aFileName, pFileName, 512); }
+static void CallbackAppendMap(const char *pFileName, void *pUser) { if(((CEditor*)pUser)->Append(pFileName)) ((CEditor*)pUser)->m_aFileName[0] = 0; }
+static void CallbackSaveMap(const char *pFileName, void *pUser){ if(((CEditor*)pUser)->Save(pFileName)) str_copy(((CEditor*)pUser)->m_aFileName, pFileName, 512); }
 
-void EDITOR::do_toolbar(CUIRect toolbar)
+void CEditor::DoToolbar(CUIRect ToolBar)
 {
-	CUIRect button;
+	CUIRect TB_Top, TB_Bottom;
+	CUIRect Button;
 	
-	// ctrl+o to open
-	if(inp_key_down('o') && (inp_key_pressed(KEY_LCTRL) || inp_key_pressed(KEY_RCTRL)))
-		invoke_file_dialog(LISTDIRTYPE_ALL, "Open Map", "Open", "maps/", "", callback_open_map, this);
+	ToolBar.HSplitTop(ToolBar.h/2.0f, &TB_Top, &TB_Bottom);
 	
+    TB_Top.HSplitBottom(2.5f, &TB_Top, 0);
+    TB_Bottom.HSplitTop(2.5f, 0, &TB_Bottom);
+
+	// ctrl+o to open
+	if(Input()->KeyDown('o') && (Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL)))
+		InvokeFileDialog(IStorage::TYPE_ALL, "Open Map", "Open", "maps/", "", CallbackOpenMap, this);
+
 	// ctrl+s to save
-	if(inp_key_down('s') && (inp_key_pressed(KEY_LCTRL) || inp_key_pressed(KEY_RCTRL)))
-		invoke_file_dialog(LISTDIRTYPE_SAVE, "Save Map", "Save", "maps/", "", callback_save_map, this);
+	if(Input()->KeyDown('s') && (Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL)))
+	{
+		if(m_aFileName[0])	
+			Save(m_aFileName);
+		else
+			InvokeFileDialog(IStorage::TYPE_SAVE, "Save Map", "Save", "maps/", "", CallbackSaveMap, this);
+	}
 
 	// detail button
-	toolbar.VSplitLeft(30.0f, &button, &toolbar);
-	static int hq_button = 0;
-	if(DoButton_Editor(&hq_button, "Detail", show_detail, &button, 0, "[ctrl+h] Toggle High Detail") ||
-		(inp_key_down('h') && (inp_key_pressed(KEY_LCTRL) || inp_key_pressed(KEY_RCTRL))))
+	TB_Top.VSplitLeft(30.0f, &Button, &TB_Top);
+	static int s_HqButton = 0;
+	if(DoButton_Editor(&s_HqButton, "HD", m_ShowDetail, &Button, 0, "[ctrl+h] Toggle High Detail") ||
+		(Input()->KeyDown('h') && (Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL))))
 	{
-		show_detail = !show_detail;
+		m_ShowDetail = !m_ShowDetail;
 	}
 
-	toolbar.VSplitLeft(5.0f, 0, &toolbar);
-	
+	TB_Top.VSplitLeft(5.0f, 0, &TB_Top);
+
 	// animation button
-	toolbar.VSplitLeft(30.0f, &button, &toolbar);
-	static int animate_button = 0;
-	if(DoButton_Editor(&animate_button, "Anim", animate, &button, 0, "[ctrl+m] Toggle animation") ||
-		(inp_key_down('m') && (inp_key_pressed(KEY_LCTRL) || inp_key_pressed(KEY_RCTRL))))
+	TB_Top.VSplitLeft(40.0f, &Button, &TB_Top);
+	static int s_AnimateButton = 0;
+	if(DoButton_Editor(&s_AnimateButton, "Anim", m_Animate, &Button, 0, "[ctrl+m] Toggle animation") ||
+		(Input()->KeyDown('m') && (Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL))))
 	{
-		animate_start = time_get();
-		animate = !animate;
+		m_AnimateStart = time_get();
+		m_Animate = !m_Animate;
 	}
 
-	toolbar.VSplitLeft(5.0f, 0, &toolbar);
+	TB_Top.VSplitLeft(5.0f, 0, &TB_Top);
 
 	// proof button
-	toolbar.VSplitLeft(30.0f, &button, &toolbar);
-	static int proof_button = 0;
-	if(DoButton_Editor(&proof_button, "Proof", proof_borders, &button, 0, "[ctrl-p] Toggles proof borders. These borders represent what a player maximum can see.") ||
-		(inp_key_down('p') && (inp_key_pressed(KEY_LCTRL) || inp_key_pressed(KEY_RCTRL))))
+	TB_Top.VSplitLeft(40.0f, &Button, &TB_Top);
+	static int s_ProofButton = 0;
+	if(DoButton_Editor(&s_ProofButton, "Proof", m_ProofBorders, &Button, 0, "[ctrl-p] Toggles proof borders. These borders represent what a player maximum can see.") ||
+		(Input()->KeyDown('p') && (Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL))))
 	{
-		proof_borders = !proof_borders;
+		m_ProofBorders = !m_ProofBorders;
 	}
 
-	toolbar.VSplitLeft(15.0f, 0, &toolbar);
-	
+	TB_Top.VSplitLeft(15.0f, 0, &TB_Top);
+
 	// zoom group
-	toolbar.VSplitLeft(16.0f, &button, &toolbar);
-	static int zoom_out_button = 0;
-	if(DoButton_ButtonL(&zoom_out_button, "ZO", 0, &button, 0, "[NumPad-] Zoom out") || inp_key_down(KEY_KP_MINUS))
-		zoom_level += 50;
-		
-	toolbar.VSplitLeft(16.0f, &button, &toolbar);
-	static int zoom_normal_button = 0;
-	if(DoButton_ButtonM(&zoom_normal_button, "1:1", 0, &button, 0, "[NumPad*] Zoom to normal and remove editor offset") || inp_key_down(KEY_KP_MULTIPLY))
+	TB_Top.VSplitLeft(30.0f, &Button, &TB_Top);
+	static int s_ZoomOutButton = 0;
+	if(DoButton_Ex(&s_ZoomOutButton, "ZO", 0, &Button, 0, "[NumPad-] Zoom out", CUI::CORNER_L) || Input()->KeyDown(KEY_KP_MINUS))
+		m_ZoomLevel += 50;
+
+	TB_Top.VSplitLeft(30.0f, &Button, &TB_Top);
+	static int s_ZoomNormalButton = 0;
+	if(DoButton_Ex(&s_ZoomNormalButton, "1:1", 0, &Button, 0, "[NumPad*] Zoom to normal and remove editor offset", 0) || Input()->KeyDown(KEY_KP_MULTIPLY))
 	{
-		editor_offset_x = 0;
-		editor_offset_y = 0;
-		zoom_level = 100;
+		m_EditorOffsetX = 0;
+		m_EditorOffsetY = 0;
+		m_ZoomLevel = 100;
 	}
-		
-	toolbar.VSplitLeft(16.0f, &button, &toolbar);
-	static int zoom_in_button = 0;
-	if(DoButton_ButtonR(&zoom_in_button, "ZI", 0, &button, 0, "[NumPad+] Zoom in") || inp_key_down(KEY_KP_PLUS))
-		zoom_level -= 50;
-	
-	toolbar.VSplitLeft(15.0f, 0, &toolbar);
-	
+
+	TB_Top.VSplitLeft(30.0f, &Button, &TB_Top);
+	static int s_ZoomInButton = 0;
+	if(DoButton_Ex(&s_ZoomInButton, "ZI", 0, &Button, 0, "[NumPad+] Zoom in", CUI::CORNER_R) || Input()->KeyDown(KEY_KP_PLUS))
+		m_ZoomLevel -= 50;
+
+	TB_Top.VSplitLeft(10.0f, 0, &TB_Top);
+
 	// animation speed
-	toolbar.VSplitLeft(16.0f, &button, &toolbar);
-	static int anim_faster_button = 0;
-	if(DoButton_ButtonL(&anim_faster_button, "A+", 0, &button, 0, "Increase animation speed"))
-		animate_speed += 0.5f;
-	
-	toolbar.VSplitLeft(16.0f, &button, &toolbar);
-	static int anim_normal_button = 0;
-	if(DoButton_ButtonM(&anim_normal_button, "1", 0, &button, 0, "Normal animation speed"))
-		animate_speed = 1.0f;
-	
-	toolbar.VSplitLeft(16.0f, &button, &toolbar);
-	static int anim_slower_button = 0;
-	if(DoButton_ButtonR(&anim_slower_button, "A-", 0, &button, 0, "Decrease animation speed"))
+	TB_Top.VSplitLeft(30.0f, &Button, &TB_Top);
+	static int s_AnimFasterButton = 0;
+	if(DoButton_Ex(&s_AnimFasterButton, "A+", 0, &Button, 0, "Increase animation speed", CUI::CORNER_L))
+		m_AnimateSpeed += 0.5f;
+
+	TB_Top.VSplitLeft(30.0f, &Button, &TB_Top);
+	static int s_AnimNormalButton = 0;
+	if(DoButton_Ex(&s_AnimNormalButton, "1", 0, &Button, 0, "Normal animation speed", 0))
+		m_AnimateSpeed = 1.0f;
+
+	TB_Top.VSplitLeft(30.0f, &Button, &TB_Top);
+	static int s_AnimSlowerButton = 0;
+	if(DoButton_Ex(&s_AnimSlowerButton, "A-", 0, &Button, 0, "Decrease animation speed", CUI::CORNER_R))
 	{
-		if(animate_speed > 0.5f)
-			animate_speed -= 0.5f;
+		if(m_AnimateSpeed > 0.5f)
+			m_AnimateSpeed -= 0.5f;
 	}
-	
-	if(inp_key_presses(KEY_MOUSE_WHEEL_UP) && dialog == DIALOG_NONE)
-		zoom_level -= 20;
-		
-	if(inp_key_presses(KEY_MOUSE_WHEEL_DOWN) && dialog == DIALOG_NONE)
-		zoom_level += 20;
-	
-	if(zoom_level < 50)
-		zoom_level = 50;
-	world_zoom = zoom_level/100.0f;
 
-	toolbar.VSplitLeft(10.0f, &button, &toolbar);
+	if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP) && m_Dialog == DIALOG_NONE)
+		m_ZoomLevel -= 20;
+
+	if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN) && m_Dialog == DIALOG_NONE)
+		m_ZoomLevel += 20;
+
+	if(m_ZoomLevel < 50)
+		m_ZoomLevel = 50;
+	m_WorldZoom = m_ZoomLevel/100.0f;
+
+	TB_Top.VSplitLeft(10.0f, &Button, &TB_Top);
 
 
 	// brush manipulation
-	{	
-		int enabled = brush.is_empty()?-1:0;
-		
+	{
+		int Enabled = m_Brush.IsEmpty()?-1:0;
+
 		// flip buttons
-		toolbar.VSplitLeft(20.0f, &button, &toolbar);
-		static int flipx_button = 0;
-		if(DoButton_ButtonL(&flipx_button, "^X", enabled, &button, 0, "[N] Flip brush horizontal") || inp_key_down('n'))
+		TB_Top.VSplitLeft(30.0f, &Button, &TB_Top);
+		static int s_FlipXButton = 0;
+		if(DoButton_Ex(&s_FlipXButton, "X/X", Enabled, &Button, 0, "[N] Flip brush horizontal", CUI::CORNER_L) || Input()->KeyDown('n'))
 		{
-			for(int i = 0; i < brush.layers.len(); i++)
-				brush.layers[i]->brush_flip_x();
+			for(int i = 0; i < m_Brush.m_lLayers.size(); i++)
+				m_Brush.m_lLayers[i]->BrushFlipX();
 		}
-			
-		toolbar.VSplitLeft(20.0f, &button, &toolbar);
-		static int flipy_button = 0;
-		if(DoButton_ButtonR(&flipy_button, "^Y", enabled, &button, 0, "[M] Flip brush vertical") || inp_key_down('m'))
+
+		TB_Top.VSplitLeft(30.0f, &Button, &TB_Top);
+		static int s_FlipyButton = 0;
+		if(DoButton_Ex(&s_FlipyButton, "Y/Y", Enabled, &Button, 0, "[M] Flip brush vertical", CUI::CORNER_R) || Input()->KeyDown('m'))
 		{
-			for(int i = 0; i < brush.layers.len(); i++)
-				brush.layers[i]->brush_flip_y();
+			for(int i = 0; i < m_Brush.m_lLayers.size(); i++)
+				m_Brush.m_lLayers[i]->BrushFlipY();
 		}
 
 		// rotate buttons
-		toolbar.VSplitLeft(20.0f, &button, &toolbar);
-		
-		toolbar.VSplitLeft(30.0f, &button, &toolbar);
-		static int rotation_amount = 90;
-		rotation_amount = ui_do_value_selector(&rotation_amount, &button, "", rotation_amount, 1, 360, 2.0f);
-		
-		toolbar.VSplitLeft(5.0f, &button, &toolbar);
-		toolbar.VSplitLeft(30.0f, &button, &toolbar);
-		static int ccw_button = 0;
-		if(DoButton_ButtonL(&ccw_button, "CCW", enabled, &button, 0, "[R] Rotates the brush counter clockwise") || inp_key_down('r'))
+		TB_Top.VSplitLeft(15.0f, &Button, &TB_Top);
+
+		TB_Top.VSplitLeft(30.0f, &Button, &TB_Top);
+		static int s_RotationAmount = 90;
+		s_RotationAmount = UiDoValueSelector(&s_RotationAmount, &Button, "", s_RotationAmount, 1, 360, 2.0f);
+
+		TB_Top.VSplitLeft(5.0f, &Button, &TB_Top);
+		TB_Top.VSplitLeft(30.0f, &Button, &TB_Top);
+		static int s_CcwButton = 0;
+		if(DoButton_Ex(&s_CcwButton, "CCW", Enabled, &Button, 0, "[R] Rotates the brush counter clockwise", CUI::CORNER_L) || Input()->KeyDown('r'))
 		{
-			for(int i = 0; i < brush.layers.len(); i++)
-				brush.layers[i]->brush_rotate(-rotation_amount/360.0f*pi*2);
+			for(int i = 0; i < m_Brush.m_lLayers.size(); i++)
+				m_Brush.m_lLayers[i]->BrushRotate(-s_RotationAmount/360.0f*pi*2);
 		}
-			
-		toolbar.VSplitLeft(30.0f, &button, &toolbar);
-		static int cw_button = 0;
-		if(DoButton_ButtonR(&cw_button, "CW", enabled, &button, 0, "[T] Rotates the brush clockwise") || inp_key_down('t'))
+
+		TB_Top.VSplitLeft(30.0f, &Button, &TB_Top);
+		static int s_CwButton = 0;
+		if(DoButton_Ex(&s_CwButton, "CW", Enabled, &Button, 0, "[T] Rotates the brush clockwise", CUI::CORNER_R) || Input()->KeyDown('t'))
 		{
-			for(int i = 0; i < brush.layers.len(); i++)
-				brush.layers[i]->brush_rotate(rotation_amount/360.0f*pi*2);
+			for(int i = 0; i < m_Brush.m_lLayers.size(); i++)
+				m_Brush.m_lLayers[i]->BrushRotate(s_RotationAmount/360.0f*pi*2);
 		}
 	}
 
 	// quad manipulation
 	{
 		// do add button
-		toolbar.VSplitLeft(10.0f, &button, &toolbar);
-		toolbar.VSplitLeft(60.0f, &button, &toolbar);
-		static int new_button = 0;
-		
-		LAYER_QUADS *qlayer = (LAYER_QUADS *)get_selected_layer_type(0, LAYERTYPE_QUADS);
-		//LAYER_TILES *tlayer = (LAYER_TILES *)get_selected_layer_type(0, LAYERTYPE_TILES);
-		if(DoButton_Editor(&new_button, "Add Quad", qlayer?0:-1, &button, 0, "Adds a new quad"))
+		TB_Top.VSplitLeft(10.0f, &Button, &TB_Top);
+		TB_Top.VSplitLeft(60.0f, &Button, &TB_Top);
+		static int s_NewButton = 0;
+
+		CLayerQuads *pQLayer = (CLayerQuads *)GetSelectedLayerType(0, LAYERTYPE_QUADS);
+		//CLayerTiles *tlayer = (CLayerTiles *)get_selected_layer_type(0, LAYERTYPE_TILES);
+		if(DoButton_Editor(&s_NewButton, "Add Quad", pQLayer?0:-1, &Button, 0, "Adds a new quad"))
 		{
-			if(qlayer)
+			if(pQLayer)
 			{
-				float mapping[4];
-				LAYERGROUP *g = get_selected_group();
-				g->mapping(mapping);
-				int add_x = f2fx(mapping[0] + (mapping[2]-mapping[0])/2);
-				int add_y = f2fx(mapping[1] + (mapping[3]-mapping[1])/2);
-				
-				QUAD *q = qlayer->new_quad();
+				float Mapping[4];
+				CLayerGroup *g = GetSelectedGroup();
+				g->Mapping(Mapping);
+				int AddX = f2fx(Mapping[0] + (Mapping[2]-Mapping[0])/2);
+				int AddY = f2fx(Mapping[1] + (Mapping[3]-Mapping[1])/2);
+
+				CQuad *q = pQLayer->NewQuad();
 				for(int i = 0; i < 5; i++)
 				{
-					q->points[i].x += add_x;
-					q->points[i].y += add_y;
+					q->m_aPoints[i].x += AddX;
+					q->m_aPoints[i].y += AddY;
 				}
 			}
 		}
 	}
+    
+	// tile manipulation
+	{
+		TB_Bottom.VSplitLeft(40.0f, &Button, &TB_Bottom);
+		static int s_BorderBut = 0;
+		CLayerTiles *pT = (CLayerTiles *)GetSelectedLayerType(0, LAYERTYPE_TILES);
+		
+		if(DoButton_Editor(&s_BorderBut, "Border", pT?0:-1, &Button, 0, "Border"))
+		{
+			if(pT)
+                DoMapBorder();
+		}
+	}
 }
 
-static void rotate(POINT *center, POINT *point, float rotation)
+static void Rotate(CPoint *pCenter, CPoint *pPoint, float Rotation)
 {
-	int x = point->x - center->x;
-	int y = point->y - center->y;
-	point->x = (int)(x * cosf(rotation) - y * sinf(rotation) + center->x);
-	point->y = (int)(x * sinf(rotation) + y * cosf(rotation) + center->y);
+	int x = pPoint->x - pCenter->x;
+	int y = pPoint->y - pCenter->y;
+	pPoint->x = (int)(x * cosf(Rotation) - y * sinf(Rotation) + pCenter->x);
+	pPoint->y = (int)(x * sinf(Rotation) + y * cosf(Rotation) + pCenter->y);
 }
 
-void EDITOR::do_quad(QUAD *q, int index)
+void CEditor::DoQuad(CQuad *q, int Index)
 {
 	enum
 	{
@@ -906,71 +775,72 @@ void EDITOR::do_quad(QUAD *q, int index)
 		OP_ROTATE,
 		OP_CONTEXT_MENU,
 	};
-	
+
 	// some basic values
-	void *id = &q->points[4]; // use pivot addr as id
-	static POINT rotate_points[4];
-	static float last_wx;
-	static float last_wy;
-	static int operation = OP_NONE;
-	static float rotate_angle = 0;
+	void *pId = &q->m_aPoints[4]; // use pivot addr as id
+	static CPoint s_RotatePoints[4];
+	static float s_LastWx;
+	static float s_LastWy;
+	static int s_Operation = OP_NONE;
+	static float s_RotateAngle = 0;
 	float wx = UI()->MouseWorldX();
 	float wy = UI()->MouseWorldY();
-	
+
 	// get pivot
-	float center_x = fx2f(q->points[4].x);
-	float center_y = fx2f(q->points[4].y);
+	float CenterX = fx2f(q->m_aPoints[4].x);
+	float CenterY = fx2f(q->m_aPoints[4].y);
 
-	float dx = (center_x - wx);
-	float dy = (center_y - wy);
+	float dx = (CenterX - wx);
+	float dy = (CenterY - wy);
 	if(dx*dx+dy*dy < 10*10)
-		UI()->SetHotItem(id);
+		UI()->SetHotItem(pId);
 
-	// draw selection background	
-	if(selected_quad == index)
+	// draw selection background
+	if(m_SelectedQuad == Index)
 	{
 		Graphics()->SetColor(0,0,0,1);
-		Graphics()->QuadsDraw(center_x, center_y, 7.0f, 7.0f);
+		IGraphics::CQuadItem QuadItem(CenterX, CenterY, 7.0f, 7.0f);
+		Graphics()->QuadsDraw(&QuadItem, 1);
 	}
-	
-	if(UI()->ActiveItem() == id)
+
+	if(UI()->ActiveItem() == pId)
 	{
 		// check if we only should move pivot
-		if(operation == OP_MOVE_PIVOT)
+		if(s_Operation == OP_MOVE_PIVOT)
 		{
-			q->points[4].x += f2fx(wx-last_wx);
-			q->points[4].y += f2fx(wy-last_wy);
+			q->m_aPoints[4].x += f2fx(wx-s_LastWx);
+			q->m_aPoints[4].y += f2fx(wy-s_LastWy);
 		}
-		else if(operation == OP_MOVE_ALL)
+		else if(s_Operation == OP_MOVE_ALL)
 		{
 			// move all points including pivot
 			for(int v = 0; v < 5; v++)
 			{
-				q->points[v].x += f2fx(wx-last_wx);
-				q->points[v].y += f2fx(wy-last_wy);
+				q->m_aPoints[v].x += f2fx(wx-s_LastWx);
+				q->m_aPoints[v].y += f2fx(wy-s_LastWy);
 			}
 		}
-		else if(operation == OP_ROTATE)
+		else if(s_Operation == OP_ROTATE)
 		{
 			for(int v = 0; v < 4; v++)
 			{
-				q->points[v] = rotate_points[v];
-				rotate(&q->points[4], &q->points[v], rotate_angle);
+				q->m_aPoints[v] = s_RotatePoints[v];
+				Rotate(&q->m_aPoints[4], &q->m_aPoints[v], s_RotateAngle);
 			}
 		}
-		
-		rotate_angle += (mouse_delta_x) * 0.002f;
-		last_wx = wx;
-		last_wy = wy;
-		
-		if(operation == OP_CONTEXT_MENU)
+
+		s_RotateAngle += (m_MouseDeltaX) * 0.002f;
+		s_LastWx = wx;
+		s_LastWy = wy;
+
+		if(s_Operation == OP_CONTEXT_MENU)
 		{
 			if(!UI()->MouseButton(1))
 			{
-				static int quad_popup_id = 0;
-				ui_invoke_popup_menu(&quad_popup_id, 0, UI()->MouseX(), UI()->MouseY(), 120, 150, popup_quad);
-				lock_mouse = false;
-				operation = OP_NONE;
+				static int s_QuadPopupId = 0;
+				UiInvokePopupMenu(&s_QuadPopupId, 0, UI()->MouseX(), UI()->MouseY(), 120, 150, PopupQuad);
+				m_LockMouse = false;
+				s_Operation = OP_NONE;
 				UI()->SetActiveItem(0);
 			}
 		}
@@ -978,79 +848,81 @@ void EDITOR::do_quad(QUAD *q, int index)
 		{
 			if(!UI()->MouseButton(0))
 			{
-				lock_mouse = false;
-				operation = OP_NONE;
+				m_LockMouse = false;
+				s_Operation = OP_NONE;
 				UI()->SetActiveItem(0);
 			}
-		}			
+		}
 
 		Graphics()->SetColor(1,1,1,1);
 	}
-	else if(UI()->HotItem() == id)
+	else if(UI()->HotItem() == pId)
 	{
-		ui_got_context = id;
-		
+		ms_pUiGotContext = pId;
+
 		Graphics()->SetColor(1,1,1,1);
-		tooltip = "Left mouse button to move. Hold shift to move pivot. Hold ctrl to rotate";
-		
+		m_pTooltip = "Left mouse button to move. Hold shift to move pivot. Hold ctrl to rotate";
+
 		if(UI()->MouseButton(0))
 		{
-			if(inp_key_pressed(KEY_LSHIFT) || inp_key_pressed(KEY_RSHIFT))
-				operation = OP_MOVE_PIVOT;
-			else if(inp_key_pressed(KEY_LCTRL) || inp_key_pressed(KEY_RCTRL))
+			if(Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT))
+				s_Operation = OP_MOVE_PIVOT;
+			else if(Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL))
 			{
-				lock_mouse = true;
-				operation = OP_ROTATE;
-				rotate_angle = 0;
-				rotate_points[0] = q->points[0];
-				rotate_points[1] = q->points[1];
-				rotate_points[2] = q->points[2];
-				rotate_points[3] = q->points[3];
+				m_LockMouse = true;
+				s_Operation = OP_ROTATE;
+				s_RotateAngle = 0;
+				s_RotatePoints[0] = q->m_aPoints[0];
+				s_RotatePoints[1] = q->m_aPoints[1];
+				s_RotatePoints[2] = q->m_aPoints[2];
+				s_RotatePoints[3] = q->m_aPoints[3];
 			}
 			else
-				operation = OP_MOVE_ALL;
-				
-			UI()->SetActiveItem(id);
-			selected_quad = index;
-			last_wx = wx;
-			last_wy = wy;
+				s_Operation = OP_MOVE_ALL;
+
+			UI()->SetActiveItem(pId);
+			m_SelectedQuad = Index;
+			s_LastWx = wx;
+			s_LastWy = wy;
 		}
-		
+
 		if(UI()->MouseButton(1))
 		{
-			selected_quad = index;
-			operation = OP_CONTEXT_MENU;
-			UI()->SetActiveItem(id);
+			m_SelectedQuad = Index;
+			s_Operation = OP_CONTEXT_MENU;
+			UI()->SetActiveItem(pId);
 		}
 	}
 	else
 		Graphics()->SetColor(0,1,0,1);
 
-	Graphics()->QuadsDraw(center_x, center_y, 5.0f, 5.0f);
+	IGraphics::CQuadItem QuadItem(CenterX, CenterY, 5.0f, 5.0f);
+	Graphics()->QuadsDraw(&QuadItem, 1);
 }
 
-void EDITOR::do_quad_point(QUAD *q, int quad_index, int v)
+void CEditor::DoQuadPoint(CQuad *q, int QuadIndex, int v)
 {
-	void *id = &q->points[v];
+	void *pId = &q->m_aPoints[v];
 
 	float wx = UI()->MouseWorldX();
 	float wy = UI()->MouseWorldY();
-	
-	float px = fx2f(q->points[v].x);
-	float py = fx2f(q->points[v].y);
-	
+
+	float px = fx2f(q->m_aPoints[v].x);
+	float py = fx2f(q->m_aPoints[v].y);
+
 	float dx = (px - wx);
 	float dy = (py - wy);
 	if(dx*dx+dy*dy < 10*10)
-		UI()->SetHotItem(id);
+		UI()->SetHotItem(pId);
 
-	// draw selection background	
-	if(selected_quad == quad_index && selected_points&(1<<v))
+	// draw selection background
+	if(m_SelectedQuad == QuadIndex && m_SelectedPoints&(1<<v))
 	{
 		Graphics()->SetColor(0,0,0,1);
-		Graphics()->QuadsDraw(px, py, 7.0f, 7.0f);
+		IGraphics::CQuadItem QuadItem(px, py, 7.0f, 7.0f);
+		Graphics()->QuadsDraw(&QuadItem, 1);
 	}
-	
+
 	enum
 	{
 		OP_NONE=0,
@@ -1058,48 +930,48 @@ void EDITOR::do_quad_point(QUAD *q, int quad_index, int v)
 		OP_MOVEUV,
 		OP_CONTEXT_MENU
 	};
-	
-	static bool moved;
-	static int operation = OP_NONE;
 
-	if(UI()->ActiveItem() == id)
+	static bool s_Moved;
+	static int s_Operation = OP_NONE;
+
+	if(UI()->ActiveItem() == pId)
 	{
-		float dx = mouse_delta_wx;
-		float dy = mouse_delta_wy;
-		if(!moved)
+		float dx = m_MouseDeltaWx;
+		float dy = m_MouseDeltaWy;
+		if(!s_Moved)
 		{
 			if(dx*dx+dy*dy > 0.5f)
-				moved = true;
+				s_Moved = true;
 		}
-		
-		if(moved)
+
+		if(s_Moved)
 		{
-			if(operation == OP_MOVEPOINT)
+			if(s_Operation == OP_MOVEPOINT)
 			{
 				for(int m = 0; m < 4; m++)
-					if(selected_points&(1<<m))
+					if(m_SelectedPoints&(1<<m))
 					{
-						q->points[m].x += f2fx(dx);
-						q->points[m].y += f2fx(dy);
+						q->m_aPoints[m].x += f2fx(dx);
+						q->m_aPoints[m].y += f2fx(dy);
 					}
 			}
-			else if(operation == OP_MOVEUV)
+			else if(s_Operation == OP_MOVEUV)
 			{
 				for(int m = 0; m < 4; m++)
-					if(selected_points&(1<<m))
+					if(m_SelectedPoints&(1<<m))
 					{
-						q->texcoords[m].x += f2fx(dx*0.001f);
-						q->texcoords[m].y += f2fx(dy*0.001f);
+						q->m_aTexcoords[m].x += f2fx(dx*0.001f);
+						q->m_aTexcoords[m].y += f2fx(dy*0.001f);
 					}
 			}
 		}
-		
-		if(operation == OP_CONTEXT_MENU)
+
+		if(s_Operation == OP_CONTEXT_MENU)
 		{
 			if(!UI()->MouseButton(1))
 			{
-				static int point_popup_id = 0;
-				ui_invoke_popup_menu(&point_popup_id, 0, UI()->MouseX(), UI()->MouseY(), 120, 150, popup_point);
+				static int s_PointPopupId = 0;
+				UiInvokePopupMenu(&s_PointPopupId, 0, UI()->MouseX(), UI()->MouseY(), 120, 150, PopupPoint);
 				UI()->SetActiveItem(0);
 			}
 		}
@@ -1107,210 +979,214 @@ void EDITOR::do_quad_point(QUAD *q, int quad_index, int v)
 		{
 			if(!UI()->MouseButton(0))
 			{
-				if(!moved)
+				if(!s_Moved)
 				{
-					if(inp_key_pressed(KEY_LSHIFT) || inp_key_pressed(KEY_RSHIFT))
-						selected_points ^= 1<<v;
+					if(Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT))
+						m_SelectedPoints ^= 1<<v;
 					else
-						selected_points = 1<<v;
+						m_SelectedPoints = 1<<v;
 				}
-				lock_mouse = false;
+				m_LockMouse = false;
 				UI()->SetActiveItem(0);
 			}
 		}
 
 		Graphics()->SetColor(1,1,1,1);
 	}
-	else if(UI()->HotItem() == id)
+	else if(UI()->HotItem() == pId)
 	{
-		ui_got_context = id;
-		
+		ms_pUiGotContext = pId;
+
 		Graphics()->SetColor(1,1,1,1);
-		tooltip = "Left mouse button to move. Hold shift to move the texture.";
-		
+		m_pTooltip = "Left mouse button to move. Hold shift to move the texture.";
+
 		if(UI()->MouseButton(0))
 		{
-			UI()->SetActiveItem(id);
-			moved = false;
-			if(inp_key_pressed(KEY_LSHIFT) || inp_key_pressed(KEY_RSHIFT))
+			UI()->SetActiveItem(pId);
+			s_Moved = false;
+			if(Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT))
 			{
-				operation = OP_MOVEUV;
-				lock_mouse = true;
+				s_Operation = OP_MOVEUV;
+				m_LockMouse = true;
 			}
 			else
-				operation = OP_MOVEPOINT;
-				
-			if(!(selected_points&(1<<v)))
+				s_Operation = OP_MOVEPOINT;
+
+			if(!(m_SelectedPoints&(1<<v)))
 			{
-				if(inp_key_pressed(KEY_LSHIFT) || inp_key_pressed(KEY_RSHIFT))
-					selected_points |= 1<<v;
+				if(Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT))
+					m_SelectedPoints |= 1<<v;
 				else
-					selected_points = 1<<v;
-				moved = true;
+					m_SelectedPoints = 1<<v;
+				s_Moved = true;
 			}
-															
-			selected_quad = quad_index;
+
+			m_SelectedQuad = QuadIndex;
 		}
 		else if(UI()->MouseButton(1))
 		{
-			operation = OP_CONTEXT_MENU;
-			selected_quad = quad_index;
-			UI()->SetActiveItem(id);
+			s_Operation = OP_CONTEXT_MENU;
+			m_SelectedQuad = QuadIndex;
+			UI()->SetActiveItem(pId);
 		}
 	}
 	else
 		Graphics()->SetColor(1,0,0,1);
-	
-	Graphics()->QuadsDraw(px, py, 5.0f, 5.0f);	
+
+	IGraphics::CQuadItem QuadItem(px, py, 5.0f, 5.0f);
+	Graphics()->QuadsDraw(&QuadItem, 1);
 }
 
-void EDITOR::do_map_editor(CUIRect view, CUIRect toolbar)
+void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar)
 {
 	//UI()->ClipEnable(&view);
-	
-	bool show_picker = inp_key_pressed(KEY_SPACE) != 0 && dialog == DIALOG_NONE;
+
+	bool ShowPicker = Input()->KeyPressed(KEY_SPACE) != 0 && m_Dialog == DIALOG_NONE;
 
 	// render all good stuff
-	if(!show_picker)
+	if(!ShowPicker)
 	{
-		for(int g = 0; g < map.groups.len(); g++)
+		for(int g = 0; g < m_Map.m_lGroups.size(); g++)
 		{
-			if(map.groups[g]->visible)
-				map.groups[g]->render();
+			if(m_Map.m_lGroups[g]->m_Visible)
+				m_Map.m_lGroups[g]->Render();
 			//UI()->ClipEnable(&view);
 		}
-		
+
 		// render the game above everything else
-		if(map.game_group->visible && map.game_layer->visible)
+		if(m_Map.m_pGameGroup->m_Visible && m_Map.m_pGameLayer->m_Visible)
 		{
-			map.game_group->mapscreen();
-			map.game_layer->render();
+			m_Map.m_pGameGroup->MapScreen();
+			m_Map.m_pGameLayer->Render();
 		}
 	}
 
-	static void *editor_id = (void *)&editor_id;
-	int inside = UI()->MouseInside(&view);
+	static void *s_pEditorId = (void *)&s_pEditorId;
+	int Inside = UI()->MouseInside(&View);
 
 	// fetch mouse position
 	float wx = UI()->MouseWorldX();
 	float wy = UI()->MouseWorldY();
 	float mx = UI()->MouseX();
 	float my = UI()->MouseY();
-	
-	static float start_wx = 0;
-	static float start_wy = 0;
-	static float start_mx = 0;
-	static float start_my = 0;
-	
+
+	static float s_StartWx = 0;
+	static float s_StartWy = 0;
+	static float s_StartMx = 0;
+	static float s_StartMy = 0;
+
 	enum
 	{
 		OP_NONE=0,
 		OP_BRUSH_GRAB,
 		OP_BRUSH_DRAW,
+		OP_BRUSH_PAINT,
 		OP_PAN_WORLD,
 		OP_PAN_EDITOR,
 	};
 
 	// remap the screen so it can display the whole tileset
-	if(show_picker)
-	{
-		CUIRect screen = *UI()->Screen();
-		float size = 32.0*16.0f;
-		float w = size*(screen.w/view.w);
-		float h = size*(screen.h/view.h);
-		float x = -(view.x/screen.w)*w;
-		float y = -(view.y/screen.h)*h;
-		wx = x+w*mx/screen.w;
-		wy = y+h*my/screen.h;
+	if(ShowPicker)
+	{
+		CUIRect Screen = *UI()->Screen();
+		float Size = 32.0*16.0f;
+		float w = Size*(Screen.w/View.w);
+		float h = Size*(Screen.h/View.h);
+		float x = -(View.x/Screen.w)*w;
+		float y = -(View.y/Screen.h)*h;
+		wx = x+w*mx/Screen.w;
+		wy = y+h*my/Screen.h;
 		Graphics()->MapScreen(x, y, x+w, y+h);
-		LAYER_TILES *t = (LAYER_TILES *)get_selected_layer_type(0, LAYERTYPE_TILES);
+		CLayerTiles *t = (CLayerTiles *)GetSelectedLayerType(0, LAYERTYPE_TILES);
 		if(t)
 		{
-			tileset_picker.image = t->image;
-			tileset_picker.tex_id = t->tex_id;
-			tileset_picker.render();
+			m_TilesetPicker.m_Image = t->m_Image;
+			m_TilesetPicker.m_TexId = t->m_TexId;
+			m_TilesetPicker.Render();
 		}
 	}
-	
-	static int operation = OP_NONE;
-	
+
+	static int s_Operation = OP_NONE;
+
 	// draw layer borders
-	LAYER *edit_layers[16];
-	int num_edit_layers = 0;
-	num_edit_layers = 0;
-	
-	if(show_picker)
+	CLayer *pEditLayers[16];
+	int NumEditLayers = 0;
+	NumEditLayers = 0;
+
+	if(ShowPicker)
 	{
-		edit_layers[0] = &tileset_picker;
-		num_edit_layers++;
+		pEditLayers[0] = &m_TilesetPicker;
+		NumEditLayers++;
 	}
 	else
 	{
-		edit_layers[0] = get_selected_layer(0);
-		if(edit_layers[0])
-			num_edit_layers++;
+		pEditLayers[0] = GetSelectedLayer(0);
+		if(pEditLayers[0])
+			NumEditLayers++;
 
-		LAYERGROUP *g = get_selected_group();
+		CLayerGroup *g = GetSelectedGroup();
 		if(g)
 		{
-			g->mapscreen();
-			
-			for(int i = 0; i < num_edit_layers; i++)
+			g->MapScreen();
+
+			for(int i = 0; i < NumEditLayers; i++)
 			{
-				if(edit_layers[i]->type != LAYERTYPE_TILES)
+				if(pEditLayers[i]->m_Type != LAYERTYPE_TILES)
 					continue;
-					
+
 				float w, h;
-				edit_layers[i]->get_size(&w, &h);
+				pEditLayers[i]->GetSize(&w, &h);
 
+				IGraphics::CLineItem Array[4] = {
+					IGraphics::CLineItem(0, 0, w, 0),
+					IGraphics::CLineItem(w, 0, w, h),
+					IGraphics::CLineItem(w, h, 0, h),
+					IGraphics::CLineItem(0, h, 0, 0)};
 				Graphics()->TextureSet(-1);
 				Graphics()->LinesBegin();
-				Graphics()->LinesDraw(0,0, w,0);
-				Graphics()->LinesDraw(w,0, w,h);
-				Graphics()->LinesDraw(w,h, 0,h);
-				Graphics()->LinesDraw(0,h, 0,0);
+				Graphics()->LinesDraw(Array, 4);
 				Graphics()->LinesEnd();
 			}
 		}
 	}
-		
-	if(inside)
+
+	if(Inside)
 	{
-		UI()->SetHotItem(editor_id);
-				
+		UI()->SetHotItem(s_pEditorId);
+
 		// do global operations like pan and zoom
 		if(UI()->ActiveItem() == 0 && (UI()->MouseButton(0) || UI()->MouseButton(2)))
 		{
-			start_wx = wx;
-			start_wy = wy;
-			start_mx = mx;
-			start_my = my;
-					
-			if(inp_key_pressed(KEY_LCTRL) || inp_key_pressed(KEY_RCTRL) || UI()->MouseButton(2))
+			s_StartWx = wx;
+			s_StartWy = wy;
+			s_StartMx = mx;
+			s_StartMy = my;
+
+			if(Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL) || UI()->MouseButton(2))
 			{
-				if(inp_key_pressed(KEY_LSHIFT))
-					operation = OP_PAN_EDITOR;
+				if(Input()->KeyPressed(KEY_LSHIFT))
+					s_Operation = OP_PAN_EDITOR;
 				else
-					operation = OP_PAN_WORLD;
-				UI()->SetActiveItem(editor_id);
+					s_Operation = OP_PAN_WORLD;
+				UI()->SetActiveItem(s_pEditorId);
 			}
 		}
 
 		// brush editing
-		if(UI()->HotItem() == editor_id)
+		if(UI()->HotItem() == s_pEditorId)
 		{
-			if(brush.is_empty())
-				tooltip = "Use left mouse button to drag and create a brush.";
+			if(m_Brush.IsEmpty())
+				m_pTooltip = "Use left mouse button to drag and create a brush.";
 			else
-				tooltip = "Use left mouse button to paint with the brush. Right button clears the brush.";
+				m_pTooltip = "Use left mouse button to paint with the brush. Right button clears the brush.";
 
-			if(UI()->ActiveItem() == editor_id)
+			if(UI()->ActiveItem() == s_pEditorId)
 			{
 				CUIRect r;
-				r.x = start_wx;
-				r.y = start_wy;
-				r.w = wx-start_wx;
-				r.h = wy-start_wy;
+				r.x = s_StartWx;
+				r.y = s_StartWy;
+				r.w = wx-s_StartWx;
+				r.h = wy-s_StartWy;
 				if(r.w < 0)
 				{
 					r.x += r.w;
@@ -1322,38 +1198,53 @@ void EDITOR::do_map_editor(CUIRect view, CUIRect toolbar)
 					r.y += r.h;
 					r.h = -r.h;
 				}
-				
-				if(operation == OP_BRUSH_DRAW)
-				{						
-					if(!brush.is_empty())
+
+				if(s_Operation == OP_BRUSH_DRAW)
+				{
+					if(!m_Brush.IsEmpty())
 					{
 						// draw with brush
-						for(int k = 0; k < num_edit_layers; k++)
+						for(int k = 0; k < NumEditLayers; k++)
 						{
-							if(edit_layers[k]->type == brush.layers[0]->type)
-								edit_layers[k]->brush_draw(brush.layers[0], wx, wy);
+							if(pEditLayers[k]->m_Type == m_Brush.m_lLayers[0]->m_Type)
+								pEditLayers[k]->BrushDraw(m_Brush.m_lLayers[0], wx, wy);
 						}
 					}
 				}
-				else if(operation == OP_BRUSH_GRAB)
+				else if(s_Operation == OP_BRUSH_GRAB)
 				{
 					if(!UI()->MouseButton(0))
 					{
 						// grab brush
 						dbg_msg("editor", "grabbing %f %f %f %f", r.x, r.y, r.w, r.h);
-						
+
 						// TODO: do all layers
-						int grabs = 0;
-						for(int k = 0; k < num_edit_layers; k++)
-							grabs += edit_layers[k]->brush_grab(&brush, r);
-						if(grabs == 0)
-							brush.clear();
+						int Grabs = 0;
+						for(int k = 0; k < NumEditLayers; k++)
+							Grabs += pEditLayers[k]->BrushGrab(&m_Brush, r);
+						if(Grabs == 0)
+							m_Brush.Clear();
 					}
 					else
 					{
 						//editor.map.groups[selected_group]->mapscreen();
-						for(int k = 0; k < num_edit_layers; k++)
-							edit_layers[k]->brush_selecting(r);
+						for(int k = 0; k < NumEditLayers; k++)
+							pEditLayers[k]->BrushSelecting(r);
+						Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h);
+					}
+				}
+				else if(s_Operation == OP_BRUSH_PAINT)
+				{
+					if(!UI()->MouseButton(0))
+					{
+                        for(int k = 0; k < NumEditLayers; k++)
+                            pEditLayers[k]->FillSelection(m_Brush.IsEmpty(), m_Brush.m_lLayers[0], r);
+					}
+					else
+					{
+						//editor.map.groups[selected_group]->mapscreen();
+						for(int k = 0; k < NumEditLayers; k++)
+							pEditLayers[k]->BrushSelecting(r);
 						Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h);
 					}
 				}
@@ -1361,182 +1252,196 @@ void EDITOR::do_map_editor(CUIRect view, CUIRect toolbar)
 			else
 			{
 				if(UI()->MouseButton(1))
-					brush.clear();
-					
-				if(UI()->MouseButton(0) && operation == OP_NONE)
+					m_Brush.Clear();
+
+				if(UI()->MouseButton(0) && s_Operation == OP_NONE)
 				{
-					UI()->SetActiveItem(editor_id);
-					
-					if(brush.is_empty())
-						operation = OP_BRUSH_GRAB;
+					UI()->SetActiveItem(s_pEditorId);
+
+					if(m_Brush.IsEmpty())
+						s_Operation = OP_BRUSH_GRAB;
 					else
 					{
-						operation = OP_BRUSH_DRAW;
-						for(int k = 0; k < num_edit_layers; k++)
+						s_Operation = OP_BRUSH_DRAW;
+						for(int k = 0; k < NumEditLayers; k++)
 						{
-							if(edit_layers[k]->type == brush.layers[0]->type)
-								edit_layers[k]->brush_place(brush.layers[0], wx, wy);
+							if(pEditLayers[k]->m_Type == m_Brush.m_lLayers[0]->m_Type)
+								pEditLayers[k]->BrushPlace(m_Brush.m_lLayers[0], wx, wy);
 						}
-						
+
 					}
+					
+					CLayerTiles *pLayer = (CLayerTiles*)GetSelectedLayerType(0, LAYERTYPE_TILES);
+					if((Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT)) && pLayer)
+                        s_Operation = OP_BRUSH_PAINT;
 				}
-				
-				if(!brush.is_empty())
+
+				if(!m_Brush.IsEmpty())
 				{
-					brush.offset_x = -(int)wx;
-					brush.offset_y = -(int)wy;
-					for(int i = 0; i < brush.layers.len(); i++)
+					m_Brush.m_OffsetX = -(int)wx;
+					m_Brush.m_OffsetY = -(int)wy;
+					for(int i = 0; i < m_Brush.m_lLayers.size(); i++)
 					{
-						if(brush.layers[i]->type == LAYERTYPE_TILES)
+						if(m_Brush.m_lLayers[i]->m_Type == LAYERTYPE_TILES)
 						{
-							brush.offset_x = -(int)(wx/32.0f)*32;
-							brush.offset_y = -(int)(wy/32.0f)*32;
+							m_Brush.m_OffsetX = -(int)(wx/32.0f)*32;
+							m_Brush.m_OffsetY = -(int)(wy/32.0f)*32;
 							break;
 						}
 					}
-				
-					LAYERGROUP *g = get_selected_group();
-					brush.offset_x += g->offset_x;
-					brush.offset_y += g->offset_y;
-					brush.parallax_x = g->parallax_x;
-					brush.parallax_y = g->parallax_y;
-					brush.render();
+
+					CLayerGroup *g = GetSelectedGroup();
+					m_Brush.m_OffsetX += g->m_OffsetX;
+					m_Brush.m_OffsetY += g->m_OffsetY;
+					m_Brush.m_ParallaxX = g->m_ParallaxX;
+					m_Brush.m_ParallaxY = g->m_ParallaxY;
+					m_Brush.Render();
 					float w, h;
-					brush.get_size(&w, &h);
-					
+					m_Brush.GetSize(&w, &h);
+
+					IGraphics::CLineItem Array[4] = {
+						IGraphics::CLineItem(0, 0, w, 0),
+						IGraphics::CLineItem(w, 0, w, h),
+						IGraphics::CLineItem(w, h, 0, h),
+						IGraphics::CLineItem(0, h, 0, 0)};
 					Graphics()->TextureSet(-1);
 					Graphics()->LinesBegin();
-					Graphics()->LinesDraw(0,0, w,0);
-					Graphics()->LinesDraw(w,0, w,h);
-					Graphics()->LinesDraw(w,h, 0,h);
-					Graphics()->LinesDraw(0,h, 0,0);
+					Graphics()->LinesDraw(Array, 4);
 					Graphics()->LinesEnd();
-					
+
 				}
 			}
 		}
-		
+
 		// quad editing
 		{
-			if(!show_picker && brush.is_empty())
+			if(!ShowPicker && m_Brush.IsEmpty())
 			{
 				// fetch layers
-				LAYERGROUP *g = get_selected_group();
+				CLayerGroup *g = GetSelectedGroup();
 				if(g)
-					g->mapscreen();
-					
-				for(int k = 0; k < num_edit_layers; k++)
+					g->MapScreen();
+
+				for(int k = 0; k < NumEditLayers; k++)
 				{
-					if(edit_layers[k]->type == LAYERTYPE_QUADS)
+					if(pEditLayers[k]->m_Type == LAYERTYPE_QUADS)
 					{
-						LAYER_QUADS *layer = (LAYER_QUADS *)edit_layers[k];
-		
+						CLayerQuads *pLayer = (CLayerQuads *)pEditLayers[k];
+
 						Graphics()->TextureSet(-1);
-						Graphics()->QuadsBegin();				
-						for(int i = 0; i < layer->quads.len(); i++)
+						Graphics()->QuadsBegin();
+						for(int i = 0; i < pLayer->m_lQuads.size(); i++)
 						{
 							for(int v = 0; v < 4; v++)
-								do_quad_point(&layer->quads[i], i, v);
-								
-							do_quad(&layer->quads[i], i);
+								DoQuadPoint(&pLayer->m_lQuads[i], i, v);
+
+							DoQuad(&pLayer->m_lQuads[i], i);
 						}
 						Graphics()->QuadsEnd();
 					}
 				}
-				
+
 				Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h);
-			}		
-			
+			}
+
 			// do panning
-			if(UI()->ActiveItem() == editor_id)
+			if(UI()->ActiveItem() == s_pEditorId)
 			{
-				if(operation == OP_PAN_WORLD)
+				if(s_Operation == OP_PAN_WORLD)
 				{
-					world_offset_x -= mouse_delta_x*world_zoom;
-					world_offset_y -= mouse_delta_y*world_zoom;
+					m_WorldOffsetX -= m_MouseDeltaX*m_WorldZoom;
+					m_WorldOffsetY -= m_MouseDeltaY*m_WorldZoom;
 				}
-				else if(operation == OP_PAN_EDITOR)
+				else if(s_Operation == OP_PAN_EDITOR)
 				{
-					editor_offset_x -= mouse_delta_x*world_zoom;
-					editor_offset_y -= mouse_delta_y*world_zoom;
+					m_EditorOffsetX -= m_MouseDeltaX*m_WorldZoom;
+					m_EditorOffsetY -= m_MouseDeltaY*m_WorldZoom;
 				}
 
 				// release mouse
 				if(!UI()->MouseButton(0))
 				{
-					operation = OP_NONE;
+					s_Operation = OP_NONE;
 					UI()->SetActiveItem(0);
 				}
 			}
 		}
 	}
-	
-	if(get_selected_group() && get_selected_group()->use_clipping)
+
+	if(GetSelectedGroup() && GetSelectedGroup()->m_UseClipping)
 	{
-		LAYERGROUP *g = map.game_group;
-		g->mapscreen();
-		
+		CLayerGroup *g = m_Map.m_pGameGroup;
+		g->MapScreen();
+	
 		Graphics()->TextureSet(-1);
 		Graphics()->LinesBegin();
 
 			CUIRect r;
-			r.x = get_selected_group()->clip_x;
-			r.y = get_selected_group()->clip_y;
-			r.w = get_selected_group()->clip_w;
-			r.h = get_selected_group()->clip_h;
-			
+			r.x = GetSelectedGroup()->m_ClipX;
+			r.y = GetSelectedGroup()->m_ClipY;
+			r.w = GetSelectedGroup()->m_ClipW;
+			r.h = GetSelectedGroup()->m_ClipH;
+
+			IGraphics::CLineItem Array[4] = {
+				IGraphics::CLineItem(r.x, r.y, r.x+r.w, r.y),
+				IGraphics::CLineItem(r.x+r.w, r.y, r.x+r.w, r.y+r.h),
+				IGraphics::CLineItem(r.x+r.w, r.y+r.h, r.x, r.y+r.h),
+				IGraphics::CLineItem(r.x, r.y+r.h, r.x, r.y)};
 			Graphics()->SetColor(1,0,0,1);
-			Graphics()->LinesDraw(r.x, r.y, r.x+r.w, r.y);
-			Graphics()->LinesDraw(r.x+r.w, r.y, r.x+r.w, r.y+r.h);
-			Graphics()->LinesDraw(r.x+r.w, r.y+r.h, r.x, r.y+r.h);
-			Graphics()->LinesDraw(r.x, r.y+r.h, r.x, r.y);
-			
+			Graphics()->LinesDraw(Array, 4);
+
 		Graphics()->LinesEnd();
 	}
 
-	// render screen sizes	
-	if(proof_borders)
+	// render screen sizes
+	if(m_ProofBorders)
 	{
-		LAYERGROUP *g = map.game_group;
-		g->mapscreen();
-		
+		CLayerGroup *g = m_Map.m_pGameGroup;
+		g->MapScreen();
+
 		Graphics()->TextureSet(-1);
 		Graphics()->LinesBegin();
-		
-		float last_points[4];
-		float start = 1.0f; //9.0f/16.0f;
-		float end = 16.0f/9.0f;
-		const int num_steps = 20;
-		for(int i = 0; i <= num_steps; i++)
+
+		float aLastPoints[4];
+		float Start = 1.0f; //9.0f/16.0f;
+		float End = 16.0f/9.0f;
+		const int NumSteps = 20;
+		for(int i = 0; i <= NumSteps; i++)
 		{
-			float points[4];
-			float aspect = start + (end-start)*(i/(float)num_steps);
-			
-			RenderTools()->mapscreen_to_world(
-				world_offset_x, world_offset_y,
-				1.0f, 1.0f, 0.0f, 0.0f, aspect, 1.0f, points);
-			
+			float aPoints[4];
+			float Aspect = Start + (End-Start)*(i/(float)NumSteps);
+
+			RenderTools()->MapscreenToWorld(
+				m_WorldOffsetX, m_WorldOffsetY,
+				1.0f, 1.0f, 0.0f, 0.0f, Aspect, 1.0f, aPoints);
+
 			if(i == 0)
 			{
-				Graphics()->LinesDraw(points[0], points[1], points[2], points[1]);
-				Graphics()->LinesDraw(points[0], points[3], points[2], points[3]);
+				IGraphics::CLineItem Array[2] = {
+					IGraphics::CLineItem(aPoints[0], aPoints[1], aPoints[2], aPoints[1]),
+					IGraphics::CLineItem(aPoints[0], aPoints[3], aPoints[2], aPoints[3])};
+				Graphics()->LinesDraw(Array, 2);
 			}
 
 			if(i != 0)
 			{
-				Graphics()->LinesDraw(points[0], points[1], last_points[0], last_points[1]);
-				Graphics()->LinesDraw(points[2], points[1], last_points[2], last_points[1]);
-				Graphics()->LinesDraw(points[0], points[3], last_points[0], last_points[3]);
-				Graphics()->LinesDraw(points[2], points[3], last_points[2], last_points[3]);
+				IGraphics::CLineItem Array[4] = {
+					IGraphics::CLineItem(aPoints[0], aPoints[1], aLastPoints[0], aLastPoints[1]),
+					IGraphics::CLineItem(aPoints[2], aPoints[1], aLastPoints[2], aLastPoints[1]),
+					IGraphics::CLineItem(aPoints[0], aPoints[3], aLastPoints[0], aLastPoints[3]),
+					IGraphics::CLineItem(aPoints[2], aPoints[3], aLastPoints[2], aLastPoints[3])};
+				Graphics()->LinesDraw(Array, 4);
 			}
 
-			if(i == num_steps)
+			if(i == NumSteps)
 			{
-				Graphics()->LinesDraw(points[0], points[1], points[0], points[3]);
-				Graphics()->LinesDraw(points[2], points[1], points[2], points[3]);
+				IGraphics::CLineItem Array[2] = {
+					IGraphics::CLineItem(aPoints[0], aPoints[1], aPoints[0], aPoints[3]),
+					IGraphics::CLineItem(aPoints[2], aPoints[1], aPoints[2], aPoints[3])};
+				Graphics()->LinesDraw(Array, 2);
 			}
-			
-			mem_copy(last_points, points, sizeof(points));
+
+			mem_copy(aLastPoints, aPoints, sizeof(aPoints));
 		}
 
 		if(1)
@@ -1544,351 +1449,359 @@ void EDITOR::do_map_editor(CUIRect view, CUIRect toolbar)
 			Graphics()->SetColor(1,0,0,1);
 			for(int i = 0; i < 2; i++)
 			{
-				float points[4];
-				float aspects[] = {4.0f/3.0f, 16.0f/10.0f, 5.0f/4.0f, 16.0f/9.0f};
-				float aspect = aspects[i];
-				
-				RenderTools()->mapscreen_to_world(
-					world_offset_x, world_offset_y,
-					1.0f, 1.0f, 0.0f, 0.0f, aspect, 1.0f, points);
-				
+				float aPoints[4];
+				float aAspects[] = {4.0f/3.0f, 16.0f/10.0f, 5.0f/4.0f, 16.0f/9.0f};
+				float Aspect = aAspects[i];
+
+				RenderTools()->MapscreenToWorld(
+					m_WorldOffsetX, m_WorldOffsetY,
+					1.0f, 1.0f, 0.0f, 0.0f, Aspect, 1.0f, aPoints);
+
 				CUIRect r;
-				r.x = points[0];
-				r.y = points[1];
-				r.w = points[2]-points[0];
-				r.h = points[3]-points[1];
-				
-				Graphics()->LinesDraw(r.x, r.y, r.x+r.w, r.y);
-				Graphics()->LinesDraw(r.x+r.w, r.y, r.x+r.w, r.y+r.h);
-				Graphics()->LinesDraw(r.x+r.w, r.y+r.h, r.x, r.y+r.h);
-				Graphics()->LinesDraw(r.x, r.y+r.h, r.x, r.y);
+				r.x = aPoints[0];
+				r.y = aPoints[1];
+				r.w = aPoints[2]-aPoints[0];
+				r.h = aPoints[3]-aPoints[1];
+
+				IGraphics::CLineItem Array[4] = {
+					IGraphics::CLineItem(r.x, r.y, r.x+r.w, r.y),
+					IGraphics::CLineItem(r.x+r.w, r.y, r.x+r.w, r.y+r.h),
+					IGraphics::CLineItem(r.x+r.w, r.y+r.h, r.x, r.y+r.h),
+					IGraphics::CLineItem(r.x, r.y+r.h, r.x, r.y)};
+				Graphics()->LinesDraw(Array, 4);
 				Graphics()->SetColor(0,1,0,1);
 			}
 		}
-			
+
 		Graphics()->LinesEnd();
 	}
-	
+
 	Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h);
 	//UI()->ClipDisable();
 }
 
 
-int EDITOR::do_properties(CUIRect *toolbox, PROPERTY *props, int *ids, int *new_val)
+int CEditor::DoProperties(CUIRect *pToolBox, CProperty *pProps, int *pIds, int *pNewVal)
 {
-	int change = -1;
+	int Change = -1;
 
-	for(int i = 0; props[i].name; i++)
+	for(int i = 0; pProps[i].m_pName; i++)
 	{
-		CUIRect slot;
-		toolbox->HSplitTop(13.0f, &slot, toolbox);
-		CUIRect label, shifter;
-		slot.VSplitMid(&label, &shifter);
-		shifter.HMargin(1.0f, &shifter);
-		UI()->DoLabel(&label, props[i].name, 10.0f, -1, -1);
-		
-		if(props[i].type == PROPTYPE_INT_STEP)
+		CUIRect Slot;
+		pToolBox->HSplitTop(13.0f, &Slot, pToolBox);
+		CUIRect Label, Shifter;
+		Slot.VSplitMid(&Label, &Shifter);
+		Shifter.HMargin(1.0f, &Shifter);
+		UI()->DoLabel(&Label, pProps[i].m_pName, 10.0f, -1, -1);
+
+		if(pProps[i].m_Type == PROPTYPE_INT_STEP)
 		{
-			CUIRect inc, dec;
-			char buf[64];
-			
-			shifter.VSplitRight(10.0f, &shifter, &inc);
-			shifter.VSplitLeft(10.0f, &dec, &shifter);
-			sprintf(buf, "%d", props[i].value);
-			RenderTools()->DrawUIRect(&shifter, vec4(1,1,1,0.5f), 0, 0.0f);
-			UI()->DoLabel(&shifter, buf, 10.0f, 0, -1);
-			
-			if(DoButton_ButtonDec(&ids[i], 0, 0, &dec, 0, "Decrease"))
+			CUIRect Inc, Dec;
+			char aBuf[64];
+
+			Shifter.VSplitRight(10.0f, &Shifter, &Inc);
+			Shifter.VSplitLeft(10.0f, &Dec, &Shifter);
+			str_format(aBuf, sizeof(aBuf),"%d", pProps[i].m_Value);
+			RenderTools()->DrawUIRect(&Shifter, vec4(1,1,1,0.5f), 0, 0.0f);
+			UI()->DoLabel(&Shifter, aBuf, 10.0f, 0, -1);
+
+			if(DoButton_ButtonDec(&pIds[i], 0, 0, &Dec, 0, "Decrease"))
 			{
-				if(inp_key_pressed(KEY_LSHIFT) || inp_key_pressed(KEY_RSHIFT))
-					*new_val = props[i].value-5;
+				if(Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT))
+					*pNewVal = pProps[i].m_Value-5;
 				else
-					*new_val = props[i].value-1;
-				change = i;
+					*pNewVal = pProps[i].m_Value-1;
+				Change = i;
 			}
-			if(DoButton_ButtonInc(((char *)&ids[i])+1, 0, 0, &inc, 0, "Increase"))
+			if(DoButton_ButtonInc(((char *)&pIds[i])+1, 0, 0, &Inc, 0, "Increase"))
 			{
-				if(inp_key_pressed(KEY_LSHIFT) || inp_key_pressed(KEY_RSHIFT))
-					*new_val = props[i].value+5;
+				if(Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT))
+					*pNewVal = pProps[i].m_Value+5;
 				else
-					*new_val = props[i].value+1;
-				change = i;
+					*pNewVal = pProps[i].m_Value+1;
+				Change = i;
 			}
 		}
-		else if(props[i].type == PROPTYPE_BOOL)
+		else if(pProps[i].m_Type == PROPTYPE_BOOL)
 		{
-			CUIRect no, yes;
-			shifter.VSplitMid(&no, &yes);
-			if(DoButton_ButtonDec(&ids[i], "No", !props[i].value, &no, 0, ""))
+			CUIRect No, Yes;
+			Shifter.VSplitMid(&No, &Yes);
+			if(DoButton_ButtonDec(&pIds[i], "No", !pProps[i].m_Value, &No, 0, ""))
 			{
-				*new_val = 0;
-				change = i;
+				*pNewVal = 0;
+				Change = i;
 			}
-			if(DoButton_ButtonInc(((char *)&ids[i])+1, "Yes", props[i].value, &yes, 0, ""))
+			if(DoButton_ButtonInc(((char *)&pIds[i])+1, "Yes", pProps[i].m_Value, &Yes, 0, ""))
 			{
-				*new_val = 1;
-				change = i;
+				*pNewVal = 1;
+				Change = i;
 			}
-		}		
-		else if(props[i].type == PROPTYPE_INT_SCROLL)
+		}
+		else if(pProps[i].m_Type == PROPTYPE_INT_SCROLL)
 		{
-			int new_value = ui_do_value_selector(&ids[i], &shifter, "", props[i].value, props[i].min, props[i].max, 1.0f);
-			if(new_value != props[i].value)
+			int NewValue = UiDoValueSelector(&pIds[i], &Shifter, "", pProps[i].m_Value, pProps[i].m_Min, pProps[i].m_Max, 1.0f);
+			if(NewValue != pProps[i].m_Value)
 			{
-				*new_val = new_value;
-				change = i;
+				*pNewVal = NewValue;
+				Change = i;
 			}
 		}
-		else if(props[i].type == PROPTYPE_COLOR)
+		else if(pProps[i].m_Type == PROPTYPE_COLOR)
 		{
-			static const char *texts[4] = {"R", "G", "B", "A"};
-			static int shift[] = {24, 16, 8, 0};
-			int new_color = 0;
-			
+			static const char *s_paTexts[4] = {"R", "G", "B", "A"};
+			static int s_aShift[] = {24, 16, 8, 0};
+			int NewColor = 0;
+
 			for(int c = 0; c < 4; c++)
 			{
-				int v = (props[i].value >> shift[c])&0xff;
-				new_color |= ui_do_value_selector(((char *)&ids[i])+c, &shifter, texts[c], v, 0, 255, 1.0f)<<shift[c];
+				int v = (pProps[i].m_Value >> s_aShift[c])&0xff;
+				NewColor |= UiDoValueSelector(((char *)&pIds[i])+c, &Shifter, s_paTexts[c], v, 0, 255, 1.0f)<<s_aShift[c];
 
 				if(c != 3)
 				{
-					toolbox->HSplitTop(13.0f, &slot, toolbox);
-					slot.VSplitMid(0, &shifter);
-					shifter.HMargin(1.0f, &shifter);
+					pToolBox->HSplitTop(13.0f, &Slot, pToolBox);
+					Slot.VSplitMid(0, &Shifter);
+					Shifter.HMargin(1.0f, &Shifter);
 				}
 			}
-			
-			if(new_color != props[i].value)
+
+			if(NewColor != pProps[i].m_Value)
 			{
-				*new_val = new_color;
-				change = i;
+				*pNewVal = NewColor;
+				Change = i;
 			}
 		}
-		else if(props[i].type == PROPTYPE_IMAGE)
+		else if(pProps[i].m_Type == PROPTYPE_IMAGE)
 		{
-			char buf[64];
-			if(props[i].value < 0)
-				strcpy(buf, "None");
+			char aBuf[64];
+			if(pProps[i].m_Value < 0)
+				str_copy(aBuf, "None", sizeof(aBuf));
 			else
-				sprintf(buf, "%s",  map.images[props[i].value]->name);
-			
-			if(DoButton_Editor(&ids[i], buf, 0, &shifter, 0, 0))
-				popup_select_image_invoke(props[i].value, UI()->MouseX(), UI()->MouseY());
-			
-			int r = popup_select_image_result();
+				str_format(aBuf, sizeof(aBuf),"%s",  m_Map.m_lImages[pProps[i].m_Value]->m_aName);
+
+			if(DoButton_Editor(&pIds[i], aBuf, 0, &Shifter, 0, 0))
+				PopupSelectImageInvoke(pProps[i].m_Value, UI()->MouseX(), UI()->MouseY());
+
+			int r = PopupSelectImageResult();
 			if(r >= -1)
 			{
-				*new_val = r;
-				change = i;
+				*pNewVal = r;
+				Change = i;
 			}
 		}
 	}
 
-	return change;
+	return Change;
 }
 
-void EDITOR::render_layers(CUIRect toolbox, CUIRect toolbar, CUIRect view)
+void CEditor::RenderLayers(CUIRect ToolBox, CUIRect ToolBar, CUIRect View)
 {
-	CUIRect layersbox = toolbox;
+	CUIRect LayersBox = ToolBox;
 
-	if(!gui_active)
+	if(!m_GuiActive)
 		return;
-			
-	CUIRect slot, button;
-	char buf[64];
 
-	int valid_group = 0;
-	int valid_layer = 0;
-	if(selected_group >= 0 && selected_group < map.groups.len())
-		valid_group = 1;
+	CUIRect Slot, Button;
+	char aBuf[64];
 
-	if(valid_group && selected_layer >= 0 && selected_layer < map.groups[selected_group]->layers.len())
-		valid_layer = 1;
-		
-	// render layers	
+	int ValidGroup = 0;
+	int ValidLayer = 0;
+	if(m_SelectedGroup >= 0 && m_SelectedGroup < m_Map.m_lGroups.size())
+		ValidGroup = 1;
+
+	if(ValidGroup && m_SelectedLayer >= 0 && m_SelectedLayer < m_Map.m_lGroups[m_SelectedGroup]->m_lLayers.size())
+		ValidLayer = 1;
+
+	// render layers
 	{
-		for(int g = 0; g < map.groups.len(); g++)
+		for(int g = 0; g < m_Map.m_lGroups.size(); g++)
 		{
-			CUIRect visible_toggle;
-			layersbox.HSplitTop(12.0f, &slot, &layersbox);
-			slot.VSplitLeft(12, &visible_toggle, &slot);
-			if(DoButton_ButtonL(&map.groups[g]->visible, map.groups[g]->visible?"V":"H", 0, &visible_toggle, 0, "Toggle group visibility"))
-				map.groups[g]->visible = !map.groups[g]->visible;
-
-			sprintf(buf, "#%d %s", g, map.groups[g]->name);
-			if(int result = DoButton_ButtonR(&map.groups[g], buf, g==selected_group, &slot,
-				BUTTON_CONTEXT, "Select group. Right click for properties."))
+			CUIRect VisibleToggle;
+			LayersBox.HSplitTop(12.0f, &Slot, &LayersBox);
+			Slot.VSplitLeft(12, &VisibleToggle, &Slot);
+			if(DoButton_Ex(&m_Map.m_lGroups[g]->m_Visible, m_Map.m_lGroups[g]->m_Visible?"V":"H", 0, &VisibleToggle, 0, "Toggle group visibility", CUI::CORNER_L))
+				m_Map.m_lGroups[g]->m_Visible = !m_Map.m_lGroups[g]->m_Visible;
+
+			str_format(aBuf, sizeof(aBuf),"#%d %s", g, m_Map.m_lGroups[g]->m_pName);
+			if(int Result = DoButton_Ex(&m_Map.m_lGroups[g], aBuf, g==m_SelectedGroup, &Slot,
+				BUTTON_CONTEXT, "Select group. Right click for properties.", CUI::CORNER_R))
 			{
-				selected_group = g;
-				selected_layer = 0;
-				
-				static int group_popup_id = 0;
-				if(result == 2)
-					ui_invoke_popup_menu(&group_popup_id, 0, UI()->MouseX(), UI()->MouseY(), 120, 200, popup_group);
+				m_SelectedGroup = g;
+				m_SelectedLayer = 0;
+
+				static int s_GroupPopupId = 0;
+				if(Result == 2)
+					UiInvokePopupMenu(&s_GroupPopupId, 0, UI()->MouseX(), UI()->MouseY(), 120, 200, PopupGroup);
 			}
-			
-			
-			layersbox.HSplitTop(2.0f, &slot, &layersbox);
-			
-			for(int i = 0; i < map.groups[g]->layers.len(); i++)
+
+			LayersBox.HSplitTop(2.0f, &Slot, &LayersBox);
+
+			for(int i = 0; i < m_Map.m_lGroups[g]->m_lLayers.size(); i++)
 			{
 				//visible
-				layersbox.HSplitTop(12.0f, &slot, &layersbox);
-				slot.VSplitLeft(12.0f, 0, &button);
-				button.VSplitLeft(15, &visible_toggle, &button);
+				LayersBox.HSplitTop(12.0f, &Slot, &LayersBox);
+				Slot.VSplitLeft(12.0f, 0, &Button);
+				Button.VSplitLeft(15, &VisibleToggle, &Button);
 
-				if(DoButton_ButtonL(&map.groups[g]->layers[i]->visible, map.groups[g]->layers[i]->visible?"V":"H", 0, &visible_toggle, 0, "Toggle layer visibility"))
-					map.groups[g]->layers[i]->visible = !map.groups[g]->layers[i]->visible;
+				if(DoButton_Ex(&m_Map.m_lGroups[g]->m_lLayers[i]->m_Visible, m_Map.m_lGroups[g]->m_lLayers[i]->m_Visible?"V":"H", 0, &VisibleToggle, 0, "Toggle layer visibility", CUI::CORNER_L))
+					m_Map.m_lGroups[g]->m_lLayers[i]->m_Visible = !m_Map.m_lGroups[g]->m_lLayers[i]->m_Visible;
 
-				sprintf(buf, "#%d %s ", i, map.groups[g]->layers[i]->type_name);
-				if(int result = DoButton_ButtonR(map.groups[g]->layers[i], buf, g==selected_group&&i==selected_layer, &button,
-					BUTTON_CONTEXT, "Select layer. Right click for properties."))
+				str_format(aBuf, sizeof(aBuf),"#%d %s ", i, m_Map.m_lGroups[g]->m_lLayers[i]->m_pTypeName);
+				if(int Result = DoButton_Ex(m_Map.m_lGroups[g]->m_lLayers[i], aBuf, g==m_SelectedGroup&&i==m_SelectedLayer, &Button,
+					BUTTON_CONTEXT, "Select layer. Right click for properties.", CUI::CORNER_R))
 				{
-					selected_layer = i;
-					selected_group = g;
-					static int layer_popup_id = 0;
-					if(result == 2)
-						ui_invoke_popup_menu(&layer_popup_id, 0, UI()->MouseX(), UI()->MouseY(), 120, 150, popup_layer);
+					m_SelectedLayer = i;
+					m_SelectedGroup = g;
+					static int s_LayerPopupId = 0;
+					if(Result == 2)
+						UiInvokePopupMenu(&s_LayerPopupId, 0, UI()->MouseX(), UI()->MouseY(), 120, 150, PopupLayer);
 				}
-				
-				
-				layersbox.HSplitTop(2.0f, &slot, &layersbox);
+
+
+				LayersBox.HSplitTop(2.0f, &Slot, &LayersBox);
 			}
-			layersbox.HSplitTop(5.0f, &slot, &layersbox);
+			LayersBox.HSplitTop(5.0f, &Slot, &LayersBox);
 		}
 	}
-	
+
 
 	{
-		layersbox.HSplitTop(12.0f, &slot, &layersbox);
+		LayersBox.HSplitTop(12.0f, &Slot, &LayersBox);
 
-		static int new_group_button = 0;
-		if(DoButton_Editor(&new_group_button, "Add Group", 0, &slot, 0, "Adds a new group"))
+		static int s_NewGroupButton = 0;
+		if(DoButton_Editor(&s_NewGroupButton, "Add Group", 0, &Slot, 0, "Adds a new group"))
 		{
-			map.new_group();
-			selected_group = map.groups.len()-1;
+			m_Map.NewGroup();
+			m_SelectedGroup = m_Map.m_lGroups.size()-1;
 		}
 	}
 
-	layersbox.HSplitTop(5.0f, &slot, &layersbox);
-	
+	LayersBox.HSplitTop(5.0f, &Slot, &LayersBox);
+
 }
 
-static void extract_name(const char *filename, char *name)
+static void ExtractName(const char *pFileName, char *pName)
 {
-	int len = strlen(filename);
-	int start = len;
-	int end = len;
-	
-	while(start > 0)
+	int Len = str_length(pFileName);
+	int Start = Len;
+	int End = Len;
+
+	while(Start > 0)
 	{
-		start--;
-		if(filename[start] == '/' || filename[start] == '\\')
+		Start--;
+		if(pFileName[Start] == '/' || pFileName[Start] == '\\')
 		{
-			start++;
+			Start++;
 			break;
 		}
 	}
-	
-	end = start;
-	for(int i = start; i < len; i++)
+
+	End = Start;
+	for(int i = Start; i < Len; i++)
 	{
-		if(filename[i] == '.')
-			end = i;
+		if(pFileName[i] == '.')
+			End = i;
 	}
-	
-	if(end == start)
-		end = len;
-	
-	int final_len = end-start;
-	mem_copy(name, &filename[start], final_len);
-	name[final_len] = 0;
-	dbg_msg("", "%s %s %d %d", filename, name, start, end);
+
+	if(End == Start)
+		End = Len;
+
+	int FinalLen = End-Start;
+	mem_copy(pName, &pFileName[Start], FinalLen);
+	pName[FinalLen] = 0;
+	dbg_msg("", "%s %s %d %d", pFileName, pName, Start, End);
 }
 
-void EDITOR::replace_image(const char *filename, void *user)
+void CEditor::ReplaceImage(const char *pFileName, void *pUser)
 {
-	EDITOR *editor = (EDITOR *)user;
-	EDITOR_IMAGE imginfo(editor);
-	if(!editor->Graphics()->LoadPNG(&imginfo, filename))
+	CEditor *pEditor = (CEditor *)pUser;
+	CEditorImage ImgInfo(pEditor);
+	if(!pEditor->Graphics()->LoadPNG(&ImgInfo, pFileName))
 		return;
-	
-	EDITOR_IMAGE *img = editor->map.images[editor->selected_image];
-	editor->Graphics()->UnloadTexture(img->tex_id);
-	*img = imginfo;
-	extract_name(filename, img->name);
-	img->tex_id = editor->Graphics()->LoadTextureRaw(imginfo.width, imginfo.height, imginfo.format, imginfo.data, IMG_AUTO, 0);
+
+	CEditorImage *pImg = pEditor->m_Map.m_lImages[pEditor->m_SelectedImage];
+	pEditor->Graphics()->UnloadTexture(pImg->m_TexId);
+	*pImg = ImgInfo;
+	ExtractName(pFileName, pImg->m_aName);
+	pImg->m_TexId = pEditor->Graphics()->LoadTextureRaw(ImgInfo.m_Width, ImgInfo.m_Height, ImgInfo.m_Format, ImgInfo.m_pData, CImageInfo::FORMAT_AUTO, 0);
 }
 
-void EDITOR::add_image(const char *filename, void *user)
+void CEditor::AddImage(const char *pFileName, void *pUser)
 {
-	EDITOR *editor = (EDITOR *)user;
-	EDITOR_IMAGE imginfo(editor);
-	if(!editor->Graphics()->LoadPNG(&imginfo, filename))
+	CEditor *pEditor = (CEditor *)pUser;
+	CEditorImage ImgInfo(pEditor);
+	if(!pEditor->Graphics()->LoadPNG(&ImgInfo, pFileName))
 		return;
 
-	EDITOR_IMAGE *img = new EDITOR_IMAGE(editor);
-	*img = imginfo;
-	img->tex_id = editor->Graphics()->LoadTextureRaw(imginfo.width, imginfo.height, imginfo.format, imginfo.data, IMG_AUTO, 0);
-	img->external = 1; // external by default
-	extract_name(filename, img->name);
-	editor->map.images.add(img);
+	CEditorImage *pImg = new CEditorImage(pEditor);
+	*pImg = ImgInfo;
+	pImg->m_TexId = pEditor->Graphics()->LoadTextureRaw(ImgInfo.m_Width, ImgInfo.m_Height, ImgInfo.m_Format, ImgInfo.m_pData, CImageInfo::FORMAT_AUTO, 0);
+	pImg->m_External = 1; // external by default
+	ExtractName(pFileName, pImg->m_aName);
+
+	for(int i = 0; i < pEditor->m_Map.m_lImages.size(); ++i)
+	{
+	    if(!str_comp(pEditor->m_Map.m_lImages[i]->m_aName, pImg->m_aName))
+            return;
+	}
+
+	pEditor->m_Map.m_lImages.add(pImg);
 }
 
 
-static int modify_index_deleted_index;
-static void modify_index_deleted(int *index)
+static int gs_ModifyIndexDeletedIndex;
+static void ModifyIndexDeleted(int *pIndex)
 {
-	if(*index == modify_index_deleted_index)
-		*index = -1;
-	else if(*index > modify_index_deleted_index)
-		*index = *index - 1;
+	if(*pIndex == gs_ModifyIndexDeletedIndex)
+		*pIndex = -1;
+	else if(*pIndex > gs_ModifyIndexDeletedIndex)
+		*pIndex = *pIndex - 1;
 }
 
-int EDITOR::popup_image(EDITOR *pEditor, CUIRect view)
+int CEditor::PopupImage(CEditor *pEditor, CUIRect View)
 {
-	static int replace_button = 0;	
-	static int remove_button = 0;	
+	static int s_ReplaceButton = 0;
+	static int s_RemoveButton = 0;
 
-	CUIRect slot;
-	view.HSplitTop(2.0f, &slot, &view);
-	view.HSplitTop(12.0f, &slot, &view);
-	EDITOR_IMAGE *img = pEditor->map.images[pEditor->selected_image];
-	
-	static int external_button = 0;
-	if(img->external)
+	CUIRect Slot;
+	View.HSplitTop(2.0f, &Slot, &View);
+	View.HSplitTop(12.0f, &Slot, &View);
+	CEditorImage *pImg = pEditor->m_Map.m_lImages[pEditor->m_SelectedImage];
+
+	static int s_ExternalButton = 0;
+	if(pImg->m_External)
 	{
-		if(pEditor->DoButton_MenuItem(&external_button, "Embedd", 0, &slot, 0, "Embedds the image into the map file."))
+		if(pEditor->DoButton_MenuItem(&s_ExternalButton, "Embedd", 0, &Slot, 0, "Embedds the image into the map file."))
 		{
-			img->external = 0;
+			pImg->m_External = 0;
 			return 1;
 		}
 	}
 	else
-	{		
-		if(pEditor->DoButton_MenuItem(&external_button, "Make external", 0, &slot, 0, "Removes the image from the map file."))
+	{
+		if(pEditor->DoButton_MenuItem(&s_ExternalButton, "Make external", 0, &Slot, 0, "Removes the image from the map file."))
 		{
-			img->external = 1;
+			pImg->m_External = 1;
 			return 1;
 		}
 	}
 
-	view.HSplitTop(10.0f, &slot, &view);
-	view.HSplitTop(12.0f, &slot, &view);
-	if(pEditor->DoButton_MenuItem(&replace_button, "Replace", 0, &slot, 0, "Replaces the image with a new one"))
+	View.HSplitTop(10.0f, &Slot, &View);
+	View.HSplitTop(12.0f, &Slot, &View);
+	if(pEditor->DoButton_MenuItem(&s_ReplaceButton, "Replace", 0, &Slot, 0, "Replaces the image with a new one"))
 	{
-		pEditor->invoke_file_dialog(LISTDIRTYPE_ALL, "Replace Image", "Replace", "mapres/", "", replace_image, pEditor);
+		pEditor->InvokeFileDialog(IStorage::TYPE_ALL, "Replace Image", "Replace", "mapres/", "", ReplaceImage, pEditor);
 		return 1;
 	}
 
-	view.HSplitTop(10.0f, &slot, &view);
-	view.HSplitTop(12.0f, &slot, &view);
-	if(pEditor->DoButton_MenuItem(&remove_button, "Remove", 0, &slot, 0, "Removes the image from the map"))
+	View.HSplitTop(10.0f, &Slot, &View);
+	View.HSplitTop(12.0f, &Slot, &View);
+	if(pEditor->DoButton_MenuItem(&s_RemoveButton, "Remove", 0, &Slot, 0, "Removes the image from the map"))
 	{
-		delete img;
-		pEditor->map.images.removebyindex(pEditor->selected_image);
-		modify_index_deleted_index = pEditor->selected_image;
-		pEditor->map.modify_image_index(modify_index_deleted);
+		delete pImg;
+		pEditor->m_Map.m_lImages.remove_index(pEditor->m_SelectedImage);
+		gs_ModifyIndexDeletedIndex = pEditor->m_SelectedImage;
+		pEditor->m_Map.ModifyImageIndex(ModifyIndexDeleted);
 		return 1;
 	}
 
@@ -1896,712 +1809,722 @@ int EDITOR::popup_image(EDITOR *pEditor, CUIRect view)
 }
 
 
-void EDITOR::render_images(CUIRect toolbox, CUIRect toolbar, CUIRect view)
+void CEditor::RenderImages(CUIRect ToolBox, CUIRect ToolBar, CUIRect View)
 {
 	for(int e = 0; e < 2; e++) // two passes, first embedded, then external
 	{
-		CUIRect slot;
-		toolbox.HSplitTop(15.0f, &slot, &toolbox);
+		CUIRect Slot;
+		ToolBox.HSplitTop(15.0f, &Slot, &ToolBox);
 		if(e == 0)
-			UI()->DoLabel(&slot, "Embedded", 12.0f, 0);
+			UI()->DoLabel(&Slot, "Embedded", 12.0f, 0);
 		else
-			UI()->DoLabel(&slot, "External", 12.0f, 0);
-		
-		for(int i = 0; i < map.images.len(); i++)
+			UI()->DoLabel(&Slot, "External", 12.0f, 0);
+
+		for(int i = 0; i < m_Map.m_lImages.size(); i++)
 		{
-			if((e && !map.images[i]->external) ||
-				(!e && map.images[i]->external))
+			if((e && !m_Map.m_lImages[i]->m_External) ||
+				(!e && m_Map.m_lImages[i]->m_External))
 			{
 				continue;
 			}
-			
-			char buf[128];
-			sprintf(buf, "%s", map.images[i]->name);
-			toolbox.HSplitTop(12.0f, &slot, &toolbox);
-			
-			if(int result = DoButton_Editor(&map.images[i], buf, selected_image == i, &slot,
+
+			char aBuf[128];
+			str_copy(aBuf, m_Map.m_lImages[i]->m_aName, sizeof(aBuf));
+			ToolBox.HSplitTop(12.0f, &Slot, &ToolBox);
+
+			if(int Result = DoButton_Editor(&m_Map.m_lImages[i], aBuf, m_SelectedImage == i, &Slot,
 				BUTTON_CONTEXT, "Select image"))
 			{
-				selected_image = i;
-				
-				static int popup_image_id = 0;
-				if(result == 2)
-					ui_invoke_popup_menu(&popup_image_id, 0, UI()->MouseX(), UI()->MouseY(), 120, 80, popup_image);
+				m_SelectedImage = i;
+
+				static int s_PopupImageId = 0;
+				if(Result == 2)
+					UiInvokePopupMenu(&s_PopupImageId, 0, UI()->MouseX(), UI()->MouseY(), 120, 80, PopupImage);
 			}
-			
-			toolbox.HSplitTop(2.0f, 0, &toolbox);
-			
+
+			ToolBox.HSplitTop(2.0f, 0, &ToolBox);
+
 			// render image
-			if(selected_image == i)
+			if(m_SelectedImage == i)
 			{
 				CUIRect r;
-				view.Margin(10.0f, &r);
+				View.Margin(10.0f, &r);
 				if(r.h < r.w)
 					r.w = r.h;
 				else
 					r.h = r.w;
-				Graphics()->TextureSet(map.images[i]->tex_id);
+				Graphics()->TextureSet(m_Map.m_lImages[i]->m_TexId);
 				Graphics()->BlendNormal();
 				Graphics()->QuadsBegin();
-				Graphics()->QuadsDrawTL(r.x, r.y, r.w, r.h);
+				IGraphics::CQuadItem QuadItem(r.x, r.y, r.w, r.h);
+				Graphics()->QuadsDrawTL(&QuadItem, 1);
 				Graphics()->QuadsEnd();
-				
+
 			}
 		}
 	}
-	
-	CUIRect slot;
-	toolbox.HSplitTop(5.0f, &slot, &toolbox);
-	
-	// new image
-	static int new_image_button = 0;
-	toolbox.HSplitTop(10.0f, &slot, &toolbox);
-	toolbox.HSplitTop(12.0f, &slot, &toolbox);
-	if(DoButton_Editor(&new_image_button, "Add", 0, &slot, 0, "Load a new image to use in the map"))
-		invoke_file_dialog(LISTDIRTYPE_ALL, "Add Image", "Add", "mapres/", "", add_image, this);
-}
 
+	CUIRect Slot;
+	ToolBox.HSplitTop(5.0f, &Slot, &ToolBox);
 
-static int file_dialog_dirtypes = 0;
-static const char *file_dialog_title = 0;
-static const char *file_dialog_button_text = 0;
-static void (*file_dialog_func)(const char *filename, void *user);
-static void *file_dialog_user = 0;
-static char file_dialog_filename[512] = {0};
-static char file_dialog_path[512] = {0};
-static char file_dialog_complete_filename[512] = {0};
-static int files_num = 0;
-int files_startat = 0;
-int files_cur = 0;
-int files_stopat = 999;
-
-struct LISTDIRINFO
-{
-	CUIRect *rect;
-	EDITOR *editor;
+	// new image
+	static int s_NewImageButton = 0;
+	ToolBox.HSplitTop(10.0f, &Slot, &ToolBox);
+	ToolBox.HSplitTop(12.0f, &Slot, &ToolBox);
+	if(DoButton_Editor(&s_NewImageButton, "Add", 0, &Slot, 0, "Load a new image to use in the map"))
+		InvokeFileDialog(IStorage::TYPE_ALL, "Add Image", "Add", "mapres/", "", AddImage, this);
+}
+
+
+static int gs_FileDialogDirTypes = 0;
+static const char *gs_pFileDialogTitle = 0;
+static const char *gs_pFileDialogButtonText = 0;
+static void (*gs_pfnFileDialogFunc)(const char *pFileName, void *pUser);
+static void *gs_pFileDialogUser = 0;
+static char gs_FileDialogFileName[512] = {0};
+static char gs_aFileDialogPath[512] = {0};
+static char gs_aFileDialogCompleteFilename[512] = {0};
+static int gs_FilesNum = 0;
+int g_FilesStartAt = 0;
+int g_FilesCur = 0;
+int g_FilesStopAt = 999;
+
+struct CListDirInfo
+{
+	CUIRect *m_pRect;
+	CEditor *m_pEditor;
 };
 
-static void editor_listdir_callback(const char *name, int is_dir, void *user)
+static void EditorListdirCallback(const char *pName, int IsDir, void *pUser)
 {
-	if(name[0] == '.' || is_dir) // skip this shit!
+	if(pName[0] == '.' || IsDir) // skip this shit!
 		return;
-	
-	if(files_cur > files_num)
-		files_num = files_cur;
-	
-	files_cur++;
-	if(files_cur-1 < files_startat || files_cur > files_stopat)
+
+	if(g_FilesCur > gs_FilesNum)
+		gs_FilesNum = g_FilesCur;
+
+	g_FilesCur++;
+	if(g_FilesCur-1 < g_FilesStartAt || g_FilesCur > g_FilesStopAt)
 		return;
-	
-	LISTDIRINFO *info = (LISTDIRINFO *)user;
-	CUIRect *view = info->rect;
-	CUIRect button;
-	view->HSplitTop(15.0f, &button, view);
-	view->HSplitTop(2.0f, 0, view);
+
+	CListDirInfo *pInfo = (CListDirInfo *)pUser;
+	CUIRect *pView = pInfo->m_pRect;
+	CUIRect Button;
+	pView->HSplitTop(15.0f, &Button, pView);
+	pView->HSplitTop(2.0f, 0, pView);
 	//char buf[512];
-	
-	if(info->editor->DoButton_File((void*)(10+(int)button.y), name, 0, &button, 0, 0))
+
+	if(pInfo->m_pEditor->DoButton_File((void*)(10+(int)Button.y), pName, 0, &Button, 0, 0))
 	{
-		strncpy(file_dialog_filename, name, sizeof(file_dialog_filename));
-		
-		file_dialog_complete_filename[0] = 0;
-		strcat(file_dialog_complete_filename, file_dialog_path);
-		strcat(file_dialog_complete_filename, file_dialog_filename);
+		str_copy(gs_FileDialogFileName, pName, sizeof(gs_FileDialogFileName));
+
+		gs_aFileDialogCompleteFilename[0] = 0;
+		str_append(gs_aFileDialogCompleteFilename, gs_aFileDialogPath, sizeof(gs_aFileDialogCompleteFilename));
+		str_append(gs_aFileDialogCompleteFilename, gs_FileDialogFileName, sizeof(gs_aFileDialogCompleteFilename));
 
-		if(inp_mouse_doubleclick())
+		if(pInfo->m_pEditor->Input()->MouseDoubleClick())
 		{
-			if(file_dialog_func)
-				file_dialog_func(file_dialog_complete_filename, user);
-			info->editor->dialog = DIALOG_NONE;
+			if(gs_pfnFileDialogFunc)
+				gs_pfnFileDialogFunc(gs_aFileDialogCompleteFilename, pInfo->m_pEditor);
+			pInfo->m_pEditor->m_Dialog = DIALOG_NONE;
 		}
 	}
 }
 
-void EDITOR::render_file_dialog()
+void CEditor::RenderFileDialog()
 {
 	// GUI coordsys
 	Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h);
-	
-	CUIRect view = *UI()->Screen();
-	RenderTools()->DrawUIRect(&view, vec4(0,0,0,0.25f), 0, 0);
-	view.VMargin(150.0f, &view);
-	view.HMargin(50.0f, &view);
-	RenderTools()->DrawUIRect(&view, vec4(0,0,0,0.75f), CUI::CORNER_ALL, 5.0f);
-	view.Margin(10.0f, &view);
-
-	CUIRect title, filebox, filebox_label, buttonbar, scroll;
-	view.HSplitTop(18.0f, &title, &view);
-	view.HSplitTop(5.0f, 0, &view); // some spacing
-	view.HSplitBottom(14.0f, &view, &buttonbar);
-	view.HSplitBottom(10.0f, &view, 0); // some spacing
-	view.HSplitBottom(14.0f, &view, &filebox);
-	filebox.VSplitLeft(50.0f, &filebox_label, &filebox);
-	view.VSplitRight(15.0f, &view, &scroll);
-	
+
+	CUIRect View = *UI()->Screen();
+	RenderTools()->DrawUIRect(&View, vec4(0,0,0,0.25f), 0, 0);
+	View.VMargin(150.0f, &View);
+	View.HMargin(50.0f, &View);
+	RenderTools()->DrawUIRect(&View, vec4(0,0,0,0.75f), CUI::CORNER_ALL, 5.0f);
+	View.Margin(10.0f, &View);
+
+	CUIRect Title, FileBox, FileBoxLabel, ButtonBar, Scroll;
+	View.HSplitTop(18.0f, &Title, &View);
+	View.HSplitTop(5.0f, 0, &View); // some spacing
+	View.HSplitBottom(14.0f, &View, &ButtonBar);
+	View.HSplitBottom(10.0f, &View, 0); // some spacing
+	View.HSplitBottom(14.0f, &View, &FileBox);
+	FileBox.VSplitLeft(55.0f, &FileBoxLabel, &FileBox);
+	View.VSplitRight(15.0f, &View, &Scroll);
+
 	// title
-	RenderTools()->DrawUIRect(&title, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 5.0f);
-	title.VMargin(10.0f, &title);
-	UI()->DoLabel(&title, file_dialog_title, 14.0f, -1, -1);
-	
+	RenderTools()->DrawUIRect(&Title, vec4(1, 1, 1, 0.25f), CUI::CORNER_ALL, 4.0f);
+	Title.VMargin(10.0f, &Title);
+	UI()->DoLabel(&Title, gs_pFileDialogTitle, 12.0f, -1, -1);
+
 	// filebox
-	UI()->DoLabel(&filebox_label, "Filename:", 10.0f, -1, -1);
-	
-	static int filebox_id = 0;
-	DoEditBox(&filebox_id, &filebox, file_dialog_filename, sizeof(file_dialog_filename), 10.0f);
+	static int s_FileBoxId = 0;
+	UI()->DoLabel(&FileBoxLabel, "Filename:", 10.0f, -1, -1);
+	DoEditBox(&s_FileBoxId, &FileBox, gs_FileDialogFileName, sizeof(gs_FileDialogFileName), 10.0f);
 
-	file_dialog_complete_filename[0] = 0;
-	strcat(file_dialog_complete_filename, file_dialog_path);
-	strcat(file_dialog_complete_filename, file_dialog_filename);
-	
-	int num = (int)(view.h/17.0);
-	static float scrollvalue = 0;
-	static int scrollbar = 0;
-	scroll.HMargin(5.0f, &scroll);
-	scrollvalue = ui_do_scrollbar_v(&scrollbar, &scroll, scrollvalue);
-	
-	int scrollnum = files_num-num+10;
-	if(scrollnum > 0)
+	gs_aFileDialogCompleteFilename[0] = 0;
+	str_append(gs_aFileDialogCompleteFilename, gs_aFileDialogPath, sizeof(gs_aFileDialogCompleteFilename));
+	str_append(gs_aFileDialogCompleteFilename, gs_FileDialogFileName, sizeof(gs_aFileDialogCompleteFilename));
+
+	int Num = (int)(View.h/17.0);
+	static float s_ScrollValue = 0;
+	static int ScrollBar = 0;
+	Scroll.HMargin(5.0f, &Scroll);
+	s_ScrollValue = UiDoScrollbarV(&ScrollBar, &Scroll, s_ScrollValue);
+
+	int ScrollNum = gs_FilesNum-Num+10;
+	if(ScrollNum > 0)
 	{
-		if(inp_key_presses(KEY_MOUSE_WHEEL_UP))
-			scrollvalue -= 3.0f/scrollnum;
-		if(inp_key_presses(KEY_MOUSE_WHEEL_DOWN))
-			scrollvalue += 3.0f/scrollnum;
-			
-		if(scrollvalue < 0) scrollvalue = 0;
-		if(scrollvalue > 1) scrollvalue = 1;
+		if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP))
+			s_ScrollValue -= 3.0f/ScrollNum;
+		if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN))
+			s_ScrollValue += 3.0f/ScrollNum;
+
+		if(s_ScrollValue < 0) s_ScrollValue = 0;
+		if(s_ScrollValue > 1) s_ScrollValue = 1;
 	}
 	else
-		scrollnum = 0;
-	
-	files_startat = (int)(scrollnum*scrollvalue);
-	if(files_startat < 0)
-		files_startat = 0;
-		
-	files_stopat = files_startat+num;
-	
-	files_cur = 0;
-	
+		ScrollNum = 0;
+
+	g_FilesStartAt = (int)(ScrollNum*s_ScrollValue);
+	if(g_FilesStartAt < 0)
+		g_FilesStartAt = 0;
+
+	g_FilesStopAt = g_FilesStartAt+Num;
+
+	g_FilesCur = 0;
+
 	// set clipping
-	UI()->ClipEnable(&view);
-	
+	UI()->ClipEnable(&View);
+
 	// the list
-	LISTDIRINFO info;
-	info.rect = &view;
-	info.editor = this;
-	engine_listdir(file_dialog_dirtypes, file_dialog_path, editor_listdir_callback, &info);
-	
+	CListDirInfo Info;
+	Info.m_pRect = &View;
+	Info.m_pEditor = this;
+
+	// TODO: lazy ass coding, should store the interface pointer somewere
+	Kernel()->RequestInterface<IStorage>()->ListDirectory(gs_FileDialogDirTypes, gs_aFileDialogPath, EditorListdirCallback, &Info);
+
 	// disable clipping again
 	UI()->ClipDisable();
-	
+
 	// the buttons
-	static int ok_button = 0;	
-	static int cancel_button = 0;	
+	static int s_OkButton = 0;
+	static int s_CancelButton = 0;
 
-	CUIRect button;
-	buttonbar.VSplitRight(50.0f, &buttonbar, &button);
-	if(DoButton_Editor(&ok_button, file_dialog_button_text, 0, &button, 0, 0) || inp_key_pressed(KEY_RETURN))
+	CUIRect Button;
+	ButtonBar.VSplitRight(50.0f, &ButtonBar, &Button);
+	if(DoButton_Editor(&s_OkButton, gs_pFileDialogButtonText, 0, &Button, 0, 0) || Input()->KeyPressed(KEY_RETURN))
 	{
-		if(file_dialog_func)
-			file_dialog_func(file_dialog_complete_filename, file_dialog_user);
-		dialog = DIALOG_NONE;
+		if(gs_pfnFileDialogFunc)
+			gs_pfnFileDialogFunc(gs_aFileDialogCompleteFilename, gs_pFileDialogUser);
+		m_Dialog = DIALOG_NONE;
 	}
 
-	buttonbar.VSplitRight(40.0f, &buttonbar, &button);
-	buttonbar.VSplitRight(50.0f, &buttonbar, &button);
-	if(DoButton_Editor(&cancel_button, "Cancel", 0, &button, 0, 0) || inp_key_pressed(KEY_ESCAPE))
-		dialog = DIALOG_NONE;
+	ButtonBar.VSplitRight(40.0f, &ButtonBar, &Button);
+	ButtonBar.VSplitRight(50.0f, &ButtonBar, &Button);
+	if(DoButton_Editor(&s_CancelButton, "Cancel", 0, &Button, 0, 0) || Input()->KeyPressed(KEY_ESCAPE))
+		m_Dialog = DIALOG_NONE;
 }
 
-void EDITOR::invoke_file_dialog(int listdirtypes, const char *title, const char *button_text,
-	const char *basepath, const char *default_name,
-	void (*func)(const char *filename, void *user), void *user)
+void CEditor::InvokeFileDialog(int ListDirTypes, const char *pTitle, const char *pButtonText,
+	const char *pBasePath, const char *pDefaultName,
+	void (*pfnFunc)(const char *pFileName, void *pUser), void *pUser)
 {
-	file_dialog_dirtypes = listdirtypes;
-	file_dialog_title = title;
-	file_dialog_button_text = button_text;
-	file_dialog_func = func;
-	file_dialog_user = user;
-	file_dialog_filename[0] = 0;
-	file_dialog_path[0] = 0;
-	
-	if(default_name)
-		strncpy(file_dialog_filename, default_name, sizeof(file_dialog_filename));
-	if(basepath)
-		strncpy(file_dialog_path, basepath, sizeof(file_dialog_path));
-		
-	dialog = DIALOG_FILE;
+	gs_FileDialogDirTypes = ListDirTypes;
+	gs_pFileDialogTitle = pTitle;
+	gs_pFileDialogButtonText = pButtonText;
+	gs_pfnFileDialogFunc = pfnFunc;
+	gs_pFileDialogUser = pUser;
+	gs_FileDialogFileName[0] = 0;
+	gs_aFileDialogPath[0] = 0;
+
+	if(pDefaultName)
+		str_copy(gs_FileDialogFileName, pDefaultName, sizeof(gs_FileDialogFileName));
+	if(pBasePath)
+		str_copy(gs_aFileDialogPath, pBasePath, sizeof(gs_aFileDialogPath));
+
+	m_Dialog = DIALOG_FILE;
 }
 
 
 
-void EDITOR::render_modebar(CUIRect view)
+void CEditor::RenderModebar(CUIRect View)
 {
-	CUIRect button;
+	CUIRect Button;
 
 	// mode buttons
 	{
-		view.VSplitLeft(40.0f, &button, &view);
-		static int tile_button = 0;
-		if(DoButton_ButtonM(&tile_button, "Layers", mode == MODE_LAYERS, &button, 0, "Switch to edit layers."))
-			mode = MODE_LAYERS;
-
-		view.VSplitLeft(40.0f, &button, &view);
-		static int img_button = 0;
-		if(DoButton_ButtonR(&img_button, "Images", mode == MODE_IMAGES, &button, 0, "Switch to manage images."))
-			mode = MODE_IMAGES;
+		View.VSplitLeft(65.0f, &Button, &View);
+		Button.HSplitTop(30.0f, 0, &Button);
+		static int s_Button = 0;
+		const char *pButName = m_Mode == MODE_LAYERS ? "Layers" : "Images";
+		if(DoButton_Tab(&s_Button, pButName, 0, &Button, 0, "Switch between images and layers managment."))
+		{
+		    if(m_Mode == MODE_LAYERS)
+                m_Mode = MODE_IMAGES;
+            else
+                m_Mode = MODE_LAYERS;
+		}
 	}
 
-	view.VSplitLeft(5.0f, 0, &view);
-	
-	// spacing
-	//view.VSplitLeft(10.0f, 0, &view);
+	View.VSplitLeft(5.0f, 0, &View);
 }
 
-void EDITOR::render_statusbar(CUIRect view)
+void CEditor::RenderStatusbar(CUIRect View)
 {
-	CUIRect button;
-	view.VSplitRight(60.0f, &view, &button);
-	static int envelope_button = 0;
-	if(DoButton_Editor(&envelope_button, "Envelopes", show_envelope_editor, &button, 0, "Toggles the envelope editor."))
-		show_envelope_editor = (show_envelope_editor+1)%4;
-	
-	if(tooltip)
+	CUIRect Button;
+	View.VSplitRight(60.0f, &View, &Button);
+	static int s_EnvelopeButton = 0;
+	if(DoButton_Editor(&s_EnvelopeButton, "Envelopes", m_ShowEnvelopeEditor, &Button, 0, "Toggles the envelope editor."))
+		m_ShowEnvelopeEditor = (m_ShowEnvelopeEditor+1)%4;
+
+	if(m_pTooltip)
 	{
-		if(ui_got_context && ui_got_context == UI()->HotItem())
+		if(ms_pUiGotContext && ms_pUiGotContext == UI()->HotItem())
 		{
-			char buf[512];
-			sprintf(buf, "%s Right click for context menu.", tooltip);
-			UI()->DoLabel(&view, buf, 10.0f, -1, -1);
+			char aBuf[512];
+			str_format(aBuf, sizeof(aBuf),"%s Right click for context menu.", m_pTooltip);
+			UI()->DoLabel(&View, aBuf, 10.0f, -1, -1);
 		}
 		else
-			UI()->DoLabel(&view, tooltip, 10.0f, -1, -1);
+			UI()->DoLabel(&View, m_pTooltip, 10.0f, -1, -1);
 	}
 }
 
-void EDITOR::render_envelopeeditor(CUIRect view)
+void CEditor::RenderEnvelopeEditor(CUIRect View)
 {
-	if(selected_envelope < 0) selected_envelope = 0;
-	if(selected_envelope >= map.envelopes.len()) selected_envelope--;
+	if(m_SelectedEnvelope < 0) m_SelectedEnvelope = 0;
+	if(m_SelectedEnvelope >= m_Map.m_lEnvelopes.size()) m_SelectedEnvelope--;
 
-	ENVELOPE *envelope = 0;
-	if(selected_envelope >= 0 && selected_envelope < map.envelopes.len())
-		envelope = map.envelopes[selected_envelope];
+	CEnvelope *pEnvelope = 0;
+	if(m_SelectedEnvelope >= 0 && m_SelectedEnvelope < m_Map.m_lEnvelopes.size())
+		pEnvelope = m_Map.m_lEnvelopes[m_SelectedEnvelope];
 
-	bool show_colorbar = false;
-	if(envelope && envelope->channels == 4)
-		show_colorbar = true;
+	bool ShowColorBar = false;
+	if(pEnvelope && pEnvelope->m_Channels == 4)
+		ShowColorBar = true;
 
-	CUIRect toolbar, curvebar, colorbar;
-	view.HSplitTop(15.0f, &toolbar, &view);
-	view.HSplitTop(15.0f, &curvebar, &view);
-	toolbar.Margin(2.0f, &toolbar);
-	curvebar.Margin(2.0f, &curvebar);
+	CUIRect ToolBar, CurveBar, ColorBar;
+	View.HSplitTop(15.0f, &ToolBar, &View);
+	View.HSplitTop(15.0f, &CurveBar, &View);
+	ToolBar.Margin(2.0f, &ToolBar);
+	CurveBar.Margin(2.0f, &CurveBar);
 
-	if(show_colorbar)
+	if(ShowColorBar)
 	{
-		view.HSplitTop(20.0f, &colorbar, &view);
-		colorbar.Margin(2.0f, &colorbar);
-		render_background(colorbar, checker_texture, 16.0f, 1.0f);
+		View.HSplitTop(20.0f, &ColorBar, &View);
+		ColorBar.Margin(2.0f, &ColorBar);
+		RenderBackground(ColorBar, ms_CheckerTexture, 16.0f, 1.0f);
 	}
 
-	render_background(view, checker_texture, 32.0f, 0.1f);
+	RenderBackground(View, ms_CheckerTexture, 32.0f, 0.1f);
 
 	// do the toolbar
 	{
-		CUIRect button;
-		ENVELOPE *new_env = 0;
-		
-		toolbar.VSplitRight(50.0f, &toolbar, &button);
-		static int new_4d_button = 0;
-		if(DoButton_Editor(&new_4d_button, "Color+", 0, &button, 0, "Creates a new color envelope"))
-			new_env = map.new_envelope(4);
-
-		toolbar.VSplitRight(5.0f, &toolbar, &button);
-		toolbar.VSplitRight(50.0f, &toolbar, &button);
-		static int new_2d_button = 0;
-		if(DoButton_Editor(&new_2d_button, "Pos.+", 0, &button, 0, "Creates a new pos envelope"))
-			new_env = map.new_envelope(3);
-		
-		if(new_env) // add the default points
+		CUIRect Button;
+		CEnvelope *pNewEnv = 0;
+
+		ToolBar.VSplitRight(50.0f, &ToolBar, &Button);
+		static int s_New4dButton = 0;
+		if(DoButton_Editor(&s_New4dButton, "Color+", 0, &Button, 0, "Creates a new color envelope"))
+			pNewEnv = m_Map.NewEnvelope(4);
+
+		ToolBar.VSplitRight(5.0f, &ToolBar, &Button);
+		ToolBar.VSplitRight(50.0f, &ToolBar, &Button);
+		static int s_New2dButton = 0;
+		if(DoButton_Editor(&s_New2dButton, "Pos.+", 0, &Button, 0, "Creates a new pos envelope"))
+			pNewEnv = m_Map.NewEnvelope(3);
+
+		if(pNewEnv) // add the default points
 		{
-			if(new_env->channels == 4)
+			if(pNewEnv->m_Channels == 4)
 			{
-				new_env->add_point(0, 1,1,1,1);
-				new_env->add_point(1000, 1,1,1,1);
+				pNewEnv->AddPoint(0, 1,1,1,1);
+				pNewEnv->AddPoint(1000, 1,1,1,1);
 			}
 			else
 			{
-				new_env->add_point(0, 0);
-				new_env->add_point(1000, 0);
+				pNewEnv->AddPoint(0, 0);
+				pNewEnv->AddPoint(1000, 0);
 			}
 		}
-		
-		CUIRect shifter, inc, dec;
-		toolbar.VSplitLeft(60.0f, &shifter, &toolbar);
-		shifter.VSplitRight(15.0f, &shifter, &inc);
-		shifter.VSplitLeft(15.0f, &dec, &shifter);
-		char buf[512];
-		sprintf(buf, "%d/%d", selected_envelope+1, map.envelopes.len());
-		RenderTools()->DrawUIRect(&shifter, vec4(1,1,1,0.5f), 0, 0.0f);
-		UI()->DoLabel(&shifter, buf, 10.0f, 0, -1);
-		
-		static int prev_button = 0;
-		if(DoButton_ButtonDec(&prev_button, 0, 0, &dec, 0, "Previous Envelope"))
-			selected_envelope--;
-		
-		static int next_button = 0;
-		if(DoButton_ButtonInc(&next_button, 0, 0, &inc, 0, "Next Envelope"))
-			selected_envelope++;
-			
-		if(envelope)
+
+		CUIRect Shifter, Inc, Dec;
+		ToolBar.VSplitLeft(60.0f, &Shifter, &ToolBar);
+		Shifter.VSplitRight(15.0f, &Shifter, &Inc);
+		Shifter.VSplitLeft(15.0f, &Dec, &Shifter);
+		char aBuf[512];
+		str_format(aBuf, sizeof(aBuf),"%d/%d", m_SelectedEnvelope+1, m_Map.m_lEnvelopes.size());
+		RenderTools()->DrawUIRect(&Shifter, vec4(1,1,1,0.5f), 0, 0.0f);
+		UI()->DoLabel(&Shifter, aBuf, 10.0f, 0, -1);
+
+		static int s_PrevButton = 0;
+		if(DoButton_ButtonDec(&s_PrevButton, 0, 0, &Dec, 0, "Previous Envelope"))
+			m_SelectedEnvelope--;
+
+		static int s_NextButton = 0;
+		if(DoButton_ButtonInc(&s_NextButton, 0, 0, &Inc, 0, "Next Envelope"))
+			m_SelectedEnvelope++;
+
+		if(pEnvelope)
 		{
-			toolbar.VSplitLeft(15.0f, &button, &toolbar);
-			toolbar.VSplitLeft(35.0f, &button, &toolbar);
-			UI()->DoLabel(&button, "Name:", 10.0f, -1, -1);
-
-			toolbar.VSplitLeft(80.0f, &button, &toolbar);
-			
-			static int name_box = 0;
-			DoEditBox(&name_box, &button, envelope->name, sizeof(envelope->name), 10.0f);
+			ToolBar.VSplitLeft(15.0f, &Button, &ToolBar);
+			ToolBar.VSplitLeft(35.0f, &Button, &ToolBar);
+			UI()->DoLabel(&Button, "Name:", 10.0f, -1, -1);
+
+			ToolBar.VSplitLeft(80.0f, &Button, &ToolBar);
+
+			static int s_NameBox = 0;
+			DoEditBox(&s_NameBox, &Button, pEnvelope->m_aName, sizeof(pEnvelope->m_aName), 10.0f);
 		}
 	}
-	
-	if(envelope)
+
+	if(pEnvelope)
 	{
-		static array<int> selection;
-		static int envelope_editor_id = 0;
-		static int active_channels = 0xf;
-		
-		if(envelope)
+		static array<int> Selection;
+		static int sEnvelopeEditorId = 0;
+		static int s_ActiveChannels = 0xf;
+
+		if(pEnvelope)
 		{
-			CUIRect button;	
-			
-			toolbar.VSplitLeft(15.0f, &button, &toolbar);
+			CUIRect Button;
+
+			ToolBar.VSplitLeft(15.0f, &Button, &ToolBar);
 
-			static const char *names[4][4] = {
+			static const char *s_paNames[4][4] = {
 				{"X", "", "", ""},
 				{"X", "Y", "", ""},
 				{"X", "Y", "R", ""},
 				{"R", "G", "B", "A"},
 			};
-			
-			static int channel_buttons[4] = {0};
-			int bit = 1;
-			/*ui_draw_button_func draw_func;*/
-			
-			for(int i = 0; i < envelope->channels; i++, bit<<=1)
+
+			static int s_aChannelButtons[4] = {0};
+			int Bit = 1;
+			//ui_draw_button_func draw_func;
+
+			for(int i = 0; i < pEnvelope->m_Channels; i++, Bit<<=1)
 			{
-				toolbar.VSplitLeft(15.0f, &button, &toolbar);
-				
+				ToolBar.VSplitLeft(15.0f, &Button, &ToolBar);
+
 				/*if(i == 0) draw_func = draw_editor_button_l;
 				else if(i == envelope->channels-1) draw_func = draw_editor_button_r;
 				else draw_func = draw_editor_button_m;*/
-				
-				if(DoButton_Editor(&channel_buttons[i], names[envelope->channels-1][i], active_channels&bit, &button, 0, 0))
-					active_channels ^= bit;
+
+				if(DoButton_Editor(&s_aChannelButtons[i], s_paNames[pEnvelope->m_Channels-1][i], s_ActiveChannels&Bit, &Button, 0, 0))
+					s_ActiveChannels ^= Bit;
 			}
-		}		
-		
-		float end_time = envelope->end_time();
-		if(end_time < 1)
-			end_time = 1;
-		
-		envelope->find_top_bottom(active_channels);
-		float top = envelope->top;
-		float bottom = envelope->bottom;
-		
-		if(top < 1)
-			top = 1;
-		if(bottom >= 0)
-			bottom = 0;
-		
-		float timescale = end_time/view.w;
-		float valuescale = (top-bottom)/view.h;
-		
-		if(UI()->MouseInside(&view))
-			UI()->SetHotItem(&envelope_editor_id);
-			
-		if(UI()->HotItem() == &envelope_editor_id)
+		}
+
+		float EndTime = pEnvelope->EndTime();
+		if(EndTime < 1)
+			EndTime = 1;
+
+		pEnvelope->FindTopBottom(s_ActiveChannels);
+		float Top = pEnvelope->m_Top;
+		float Bottom = pEnvelope->m_Bottom;
+
+		if(Top < 1)
+			Top = 1;
+		if(Bottom >= 0)
+			Bottom = 0;
+
+		float TimeScale = EndTime/View.w;
+		float ValueScale = (Top-Bottom)/View.h;
+
+		if(UI()->MouseInside(&View))
+			UI()->SetHotItem(&sEnvelopeEditorId);
+
+		if(UI()->HotItem() == &sEnvelopeEditorId)
 		{
 			// do stuff
-			if(envelope)
+			if(pEnvelope)
 			{
 				if(UI()->MouseButtonClicked(1))
 				{
 					// add point
-					int time = (int)(((UI()->MouseX()-view.x)*timescale)*1000.0f);
-					//float env_y = (UI()->MouseY()-view.y)/timescale;
-					float channels[4];
-					envelope->eval(time, channels);
-					envelope->add_point(time,
-						f2fx(channels[0]), f2fx(channels[1]),
-						f2fx(channels[2]), f2fx(channels[3]));
+					int Time = (int)(((UI()->MouseX()-View.x)*TimeScale)*1000.0f);
+					//float env_y = (UI()->MouseY()-view.y)/TimeScale;
+					float aChannels[4];
+					pEnvelope->Eval(Time, aChannels);
+					pEnvelope->AddPoint(Time,
+						f2fx(aChannels[0]), f2fx(aChannels[1]),
+						f2fx(aChannels[2]), f2fx(aChannels[3]));
 				}
-				
-				tooltip = "Press right mouse button to create a new point";
+
+				m_pTooltip = "Press right mouse button to create a new point";
 			}
 		}
 
-		vec3 colors[] = {vec3(1,0.2f,0.2f), vec3(0.2f,1,0.2f), vec3(0.2f,0.2f,1), vec3(1,1,0.2f)};
+		vec3 aColors[] = {vec3(1,0.2f,0.2f), vec3(0.2f,1,0.2f), vec3(0.2f,0.2f,1), vec3(1,1,0.2f)};
 
 		// render lines
 		{
-			UI()->ClipEnable(&view);
+			UI()->ClipEnable(&View);
 			Graphics()->TextureSet(-1);
 			Graphics()->LinesBegin();
-			for(int c = 0; c < envelope->channels; c++)
+			for(int c = 0; c < pEnvelope->m_Channels; c++)
 			{
-				if(active_channels&(1<<c))
-					Graphics()->SetColor(colors[c].r,colors[c].g,colors[c].b,1);
+				if(s_ActiveChannels&(1<<c))
+					Graphics()->SetColor(aColors[c].r,aColors[c].g,aColors[c].b,1);
 				else
-					Graphics()->SetColor(colors[c].r*0.5f,colors[c].g*0.5f,colors[c].b*0.5f,1);
-				
-				float prev_x = 0;
-				float results[4];
-				envelope->eval(0.000001f, results);
-				float prev_value = results[c];
-				
-				int steps = (int)((view.w/UI()->Screen()->w) * Graphics()->ScreenWidth());
-				for(int i = 1; i <= steps; i++)
+					Graphics()->SetColor(aColors[c].r*0.5f,aColors[c].g*0.5f,aColors[c].b*0.5f,1);
+
+				float PrevX = 0;
+				float aResults[4];
+				pEnvelope->Eval(0.000001f, aResults);
+				float PrevValue = aResults[c];
+
+				int Steps = (int)((View.w/UI()->Screen()->w) * Graphics()->ScreenWidth());
+				for(int i = 1; i <= Steps; i++)
 				{
-					float a = i/(float)steps;
-					envelope->eval(a*end_time, results);
-					float v = results[c];
-					v = (v-bottom)/(top-bottom);
-					
-					Graphics()->LinesDraw(view.x + prev_x*view.w, view.y+view.h - prev_value*view.h, view.x + a*view.w, view.y+view.h - v*view.h);
-					prev_x = a;
-					prev_value = v;
+					float a = i/(float)Steps;
+					pEnvelope->Eval(a*EndTime, aResults);
+					float v = aResults[c];
+					v = (v-Bottom)/(Top-Bottom);
+
+					IGraphics::CLineItem LineItem(View.x + PrevX*View.w, View.y+View.h - PrevValue*View.h, View.x + a*View.w, View.y+View.h - v*View.h);
+					Graphics()->LinesDraw(&LineItem, 1);
+					PrevX = a;
+					PrevValue = v;
 				}
 			}
 			Graphics()->LinesEnd();
 			UI()->ClipDisable();
 		}
-		
+
 		// render curve options
 		{
-			for(int i = 0; i < envelope->points.len()-1; i++)
+			for(int i = 0; i < pEnvelope->m_lPoints.size()-1; i++)
 			{
-				float t0 = envelope->points[i].time/1000.0f/end_time;
-				float t1 = envelope->points[i+1].time/1000.0f/end_time;
+				float t0 = pEnvelope->m_lPoints[i].m_Time/1000.0f/EndTime;
+				float t1 = pEnvelope->m_lPoints[i+1].m_Time/1000.0f/EndTime;
 
 				//dbg_msg("", "%f", end_time);
-				
+
 				CUIRect v;
-				v.x = curvebar.x + (t0+(t1-t0)*0.5f) * curvebar.w;
-				v.y = curvebar.y;
-				v.h = curvebar.h;
-				v.w = curvebar.h;
+				v.x = CurveBar.x + (t0+(t1-t0)*0.5f) * CurveBar.w;
+				v.y = CurveBar.y;
+				v.h = CurveBar.h;
+				v.w = CurveBar.h;
 				v.x -= v.w/2;
-				void *id = &envelope->points[i].curvetype;
-				const char *type_name[] = {
+				void *pId = &pEnvelope->m_lPoints[i].m_Curvetype;
+				const char *paTypeName[] = {
 					"N", "L", "S", "F", "M"
 					};
-				
-				if(DoButton_Editor(id, type_name[envelope->points[i].curvetype], 0, &v, 0, "Switch curve type"))
-					envelope->points[i].curvetype = (envelope->points[i].curvetype+1)%NUM_CURVETYPES;
+
+				if(DoButton_Editor(pId, paTypeName[pEnvelope->m_lPoints[i].m_Curvetype], 0, &v, 0, "Switch curve type"))
+					pEnvelope->m_lPoints[i].m_Curvetype = (pEnvelope->m_lPoints[i].m_Curvetype+1)%NUM_CURVETYPES;
 			}
 		}
-		
+
 		// render colorbar
-		if(show_colorbar)
+		if(ShowColorBar)
 		{
 			Graphics()->TextureSet(-1);
 			Graphics()->QuadsBegin();
-			for(int i = 0; i < envelope->points.len()-1; i++)
+			for(int i = 0; i < pEnvelope->m_lPoints.size()-1; i++)
 			{
-				float r0 = fx2f(envelope->points[i].values[0]);
-				float g0 = fx2f(envelope->points[i].values[1]);
-				float b0 = fx2f(envelope->points[i].values[2]);
-				float a0 = fx2f(envelope->points[i].values[3]);
-				float r1 = fx2f(envelope->points[i+1].values[0]);
-				float g1 = fx2f(envelope->points[i+1].values[1]);
-				float b1 = fx2f(envelope->points[i+1].values[2]);
-				float a1 = fx2f(envelope->points[i+1].values[3]);
-
-				Graphics()->SetColorVertex(0, r0, g0, b0, a0);
-				Graphics()->SetColorVertex(1, r1, g1, b1, a1);
-				Graphics()->SetColorVertex(2, r1, g1, b1, a1);
-				Graphics()->SetColorVertex(3, r0, g0, b0, a0);
-
-				float x0 = envelope->points[i].time/1000.0f/end_time;
+				float r0 = fx2f(pEnvelope->m_lPoints[i].m_aValues[0]);
+				float g0 = fx2f(pEnvelope->m_lPoints[i].m_aValues[1]);
+				float b0 = fx2f(pEnvelope->m_lPoints[i].m_aValues[2]);
+				float a0 = fx2f(pEnvelope->m_lPoints[i].m_aValues[3]);
+				float r1 = fx2f(pEnvelope->m_lPoints[i+1].m_aValues[0]);
+				float g1 = fx2f(pEnvelope->m_lPoints[i+1].m_aValues[1]);
+				float b1 = fx2f(pEnvelope->m_lPoints[i+1].m_aValues[2]);
+				float a1 = fx2f(pEnvelope->m_lPoints[i+1].m_aValues[3]);
+
+				IGraphics::CColorVertex Array[4] = {IGraphics::CColorVertex(0, r0, g0, b0, a0),
+													IGraphics::CColorVertex(1, r1, g1, b1, a1),
+													IGraphics::CColorVertex(2, r1, g1, b1, a1),
+													IGraphics::CColorVertex(3, r0, g0, b0, a0)};
+				Graphics()->SetColorVertex(Array, 4);
+
+				float x0 = pEnvelope->m_lPoints[i].m_Time/1000.0f/EndTime;
 //				float y0 = (fx2f(envelope->points[i].values[c])-bottom)/(top-bottom);
-				float x1 = envelope->points[i+1].time/1000.0f/end_time;
+				float x1 = pEnvelope->m_lPoints[i+1].m_Time/1000.0f/EndTime;
 				//float y1 = (fx2f(envelope->points[i+1].values[c])-bottom)/(top-bottom);
 				CUIRect v;
-				v.x = colorbar.x + x0*colorbar.w;
-				v.y = colorbar.y;
-				v.w = (x1-x0)*colorbar.w;
-				v.h = colorbar.h;
-				
-				Graphics()->QuadsDrawTL(v.x, v.y, v.w, v.h);
+				v.x = ColorBar.x + x0*ColorBar.w;
+				v.y = ColorBar.y;
+				v.w = (x1-x0)*ColorBar.w;
+				v.h = ColorBar.h;
+
+				IGraphics::CQuadItem QuadItem(v.x, v.y, v.w, v.h);
+				Graphics()->QuadsDrawTL(&QuadItem, 1);
 			}
 			Graphics()->QuadsEnd();
 		}
-		
+
 		// render handles
 		{
-			static bool move = false;
-			
-			int current_value = 0, current_time = 0;
-			
+			static bool s_Move = false;
+
+			int CurrentValue = 0, CurrentTime = 0;
+
 			Graphics()->TextureSet(-1);
 			Graphics()->QuadsBegin();
-			for(int c = 0; c < envelope->channels; c++)
+			for(int c = 0; c < pEnvelope->m_Channels; c++)
 			{
-				if(!(active_channels&(1<<c)))
+				if(!(s_ActiveChannels&(1<<c)))
 					continue;
-				
-				for(int i = 0; i < envelope->points.len(); i++)
+
+				for(int i = 0; i < pEnvelope->m_lPoints.size(); i++)
 				{
-					float x0 = envelope->points[i].time/1000.0f/end_time;
-					float y0 = (fx2f(envelope->points[i].values[c])-bottom)/(top-bottom);
-					CUIRect final;
-					final.x = view.x + x0*view.w;
-					final.y = view.y+view.h - y0*view.h;
-					final.x -= 2.0f;
-					final.y -= 2.0f;
-					final.w = 4.0f;
-					final.h = 4.0f;
-					
-					void *id = &envelope->points[i].values[c];
-					
-					if(UI()->MouseInside(&final))
-						UI()->SetHotItem(id);
-						
-					float colormod = 1.0f;
+					float x0 = pEnvelope->m_lPoints[i].m_Time/1000.0f/EndTime;
+					float y0 = (fx2f(pEnvelope->m_lPoints[i].m_aValues[c])-Bottom)/(Top-Bottom);
+					CUIRect Final;
+					Final.x = View.x + x0*View.w;
+					Final.y = View.y+View.h - y0*View.h;
+					Final.x -= 2.0f;
+					Final.y -= 2.0f;
+					Final.w = 4.0f;
+					Final.h = 4.0f;
 
-					if(UI()->ActiveItem() == id)
+					void *pId = &pEnvelope->m_lPoints[i].m_aValues[c];
+
+					if(UI()->MouseInside(&Final))
+						UI()->SetHotItem(pId);
+
+					float ColorMod = 1.0f;
+
+					if(UI()->ActiveItem() == pId)
 					{
 						if(!UI()->MouseButton(0))
 						{
 							UI()->SetActiveItem(0);
-							move = false;
+							s_Move = false;
 						}
 						else
 						{
-							envelope->points[i].values[c] -= f2fx(mouse_delta_y*valuescale);
-							if(inp_key_pressed(KEY_LSHIFT) || inp_key_pressed(KEY_RSHIFT))
+							pEnvelope->m_lPoints[i].m_aValues[c] -= f2fx(m_MouseDeltaY*ValueScale);
+							if(Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT))
 							{
 								if(i != 0)
 								{
-									envelope->points[i].time += (int)((mouse_delta_x*timescale)*1000.0f);
-									if(envelope->points[i].time < envelope->points[i-1].time)
-										envelope->points[i].time = envelope->points[i-1].time + 1;
-									if(i+1 != envelope->points.len() && envelope->points[i].time > envelope->points[i+1].time)
-										envelope->points[i].time = envelope->points[i+1].time - 1;
+									pEnvelope->m_lPoints[i].m_Time += (int)((m_MouseDeltaX*TimeScale)*1000.0f);
+									if(pEnvelope->m_lPoints[i].m_Time < pEnvelope->m_lPoints[i-1].m_Time)
+										pEnvelope->m_lPoints[i].m_Time = pEnvelope->m_lPoints[i-1].m_Time + 1;
+									if(i+1 != pEnvelope->m_lPoints.size() && pEnvelope->m_lPoints[i].m_Time > pEnvelope->m_lPoints[i+1].m_Time)
+										pEnvelope->m_lPoints[i].m_Time = pEnvelope->m_lPoints[i+1].m_Time - 1;
 								}
 							}
 						}
-						
-						colormod = 100.0f;
+
+						ColorMod = 100.0f;
 						Graphics()->SetColor(1,1,1,1);
 					}
-					else if(UI()->HotItem() == id)
+					else if(UI()->HotItem() == pId)
 					{
 						if(UI()->MouseButton(0))
 						{
-							selection.clear();
-							selection.add(i);
-							UI()->SetActiveItem(id);
+							Selection.clear();
+							Selection.add(i);
+							UI()->SetActiveItem(pId);
 						}
 
 						// remove point
 						if(UI()->MouseButtonClicked(1))
-							envelope->points.removebyindex(i);
-							
-						colormod = 100.0f;
+							pEnvelope->m_lPoints.remove_index(i);
+
+						ColorMod = 100.0f;
 						Graphics()->SetColor(1,0.75f,0.75f,1);
-						tooltip = "Left mouse to drag. Hold shift to alter time point aswell. Right click to delete.";
+						m_pTooltip = "Left mouse to drag. Hold shift to alter time point aswell. Right click to delete.";
 					}
 
-					if(UI()->ActiveItem() == id || UI()->HotItem() == id)
+					if(UI()->ActiveItem() == pId || UI()->HotItem() == pId)
 					{
-						current_time = envelope->points[i].time;
-						current_value = envelope->points[i].values[c];
+						CurrentTime = pEnvelope->m_lPoints[i].m_Time;
+						CurrentValue = pEnvelope->m_lPoints[i].m_aValues[c];
 					}
-					
-					Graphics()->SetColor(colors[c].r*colormod, colors[c].g*colormod, colors[c].b*colormod, 1.0f);
-					Graphics()->QuadsDrawTL(final.x, final.y, final.w, final.h);
+
+					Graphics()->SetColor(aColors[c].r*ColorMod, aColors[c].g*ColorMod, aColors[c].b*ColorMod, 1.0f);
+					IGraphics::CQuadItem QuadItem(Final.x, Final.y, Final.w, Final.h);
+					Graphics()->QuadsDrawTL(&QuadItem, 1);
 				}
 			}
 			Graphics()->QuadsEnd();
 
-			char buf[512];
-			sprintf(buf, "%.3f %.3f", current_time/1000.0f, fx2f(current_value));
-			UI()->DoLabel(&toolbar, buf, 10.0f, 0, -1);
+			char aBuf[512];
+			str_format(aBuf, sizeof(aBuf),"%.3f %.3f", CurrentTime/1000.0f, fx2f(CurrentValue));
+			UI()->DoLabel(&ToolBar, aBuf, 10.0f, 0, -1);
 		}
 	}
 }
 
-int EDITOR::popup_menu_file(EDITOR *pEditor, CUIRect view)
+int CEditor::PopupMenuFile(CEditor *pEditor, CUIRect View)
 {
-	static int new_map_button = 0;
-	static int save_button = 0;
-	static int save_as_button = 0;
-	static int open_button = 0;
-	static int append_button = 0;
-	static int exit_button = 0;
-
-	CUIRect slot;
-	view.HSplitTop(2.0f, &slot, &view);
-	view.HSplitTop(12.0f, &slot, &view);
-	if(pEditor->DoButton_MenuItem(&new_map_button, "New", 0, &slot, 0, "Creates a new map"))
-	{
-		pEditor->reset();
+	static int s_NewMapButton = 0;
+	static int s_SaveButton = 0;
+	static int s_SaveAsButton = 0;
+	static int s_OpenButton = 0;
+	static int s_AppendButton = 0;
+	static int s_ExitButton = 0;
+
+	CUIRect Slot;
+	View.HSplitTop(2.0f, &Slot, &View);
+	View.HSplitTop(12.0f, &Slot, &View);
+	if(pEditor->DoButton_MenuItem(&s_NewMapButton, "New", 0, &Slot, 0, "Creates a new map"))
+	{
+		pEditor->Reset();
+		pEditor->m_aFileName[0] = 0;
 		return 1;
 	}
 
-	view.HSplitTop(10.0f, &slot, &view);
-	view.HSplitTop(12.0f, &slot, &view);
-	if(pEditor->DoButton_MenuItem(&open_button, "Open", 0, &slot, 0, "Opens a map for editing"))
+	View.HSplitTop(10.0f, &Slot, &View);
+	View.HSplitTop(12.0f, &Slot, &View);
+	if(pEditor->DoButton_MenuItem(&s_OpenButton, "Open", 0, &Slot, 0, "Opens a map for editing"))
 	{
-		pEditor->invoke_file_dialog(LISTDIRTYPE_ALL, "Open Map", "Open", "maps/", "", callback_open_map, pEditor);
+		pEditor->InvokeFileDialog(IStorage::TYPE_ALL, "Open Map", "Open", "maps/", "", CallbackOpenMap, pEditor);
 		return 1;
 	}
 
-	view.HSplitTop(10.0f, &slot, &view);
-	view.HSplitTop(12.0f, &slot, &view);
-	if(pEditor->DoButton_MenuItem(&append_button, "Append", 0, &slot, 0, "Opens a map and adds everything from that map to the current one"))
+	View.HSplitTop(10.0f, &Slot, &View);
+	View.HSplitTop(12.0f, &Slot, &View);
+	if(pEditor->DoButton_MenuItem(&s_AppendButton, "Append", 0, &Slot, 0, "Opens a map and adds everything from that map to the current one"))
 	{
-		pEditor->invoke_file_dialog(LISTDIRTYPE_ALL, "Append Map", "Append", "maps/", "", callback_append_map, pEditor);
+		pEditor->InvokeFileDialog(IStorage::TYPE_ALL, "Append Map", "Append", "maps/", "", CallbackAppendMap, pEditor);
 		return 1;
 	}
 
-	view.HSplitTop(10.0f, &slot, &view);
-	view.HSplitTop(12.0f, &slot, &view);
-	if(pEditor->DoButton_MenuItem(&save_button, "Save (NOT IMPL)", 0, &slot, 0, "Saves the current map"))
+	View.HSplitTop(10.0f, &Slot, &View);
+	View.HSplitTop(12.0f, &Slot, &View);
+	if(pEditor->DoButton_MenuItem(&s_SaveButton, "Save", 0, &Slot, 0, "Saves the current map"))
 	{
+		if(pEditor->m_aFileName[0])	
+			pEditor->Save(pEditor->m_aFileName);
+		else
+			pEditor->InvokeFileDialog(IStorage::TYPE_SAVE, "Save Map", "Save", "maps/", "", CallbackSaveMap, pEditor);
 		return 1;
 	}
 
-	view.HSplitTop(2.0f, &slot, &view);
-	view.HSplitTop(12.0f, &slot, &view);
-	if(pEditor->DoButton_MenuItem(&save_as_button, "Save As", 0, &slot, 0, "Saves the current map under a new name"))
+	View.HSplitTop(2.0f, &Slot, &View);
+	View.HSplitTop(12.0f, &Slot, &View);
+	if(pEditor->DoButton_MenuItem(&s_SaveAsButton, "Save As", 0, &Slot, 0, "Saves the current map under a new name"))
 	{
-		pEditor->invoke_file_dialog(LISTDIRTYPE_SAVE, "Save Map", "Save", "maps/", "", callback_save_map, pEditor);
+		pEditor->InvokeFileDialog(IStorage::TYPE_SAVE, "Save Map", "Save", "maps/", "", CallbackSaveMap, pEditor);
 		return 1;
 	}
-	
-	view.HSplitTop(10.0f, &slot, &view);
-	view.HSplitTop(12.0f, &slot, &view);
-	if(pEditor->DoButton_MenuItem(&exit_button, "Exit", 0, &slot, 0, "Exits from the editor"))
+
+	View.HSplitTop(10.0f, &Slot, &View);
+	View.HSplitTop(12.0f, &Slot, &View);
+	if(pEditor->DoButton_MenuItem(&s_ExitButton, "Exit", 0, &Slot, 0, "Exits from the editor"))
 	{
-		config.cl_editor = 0;
+		g_Config.m_ClEditor = 0;
 		return 1;
-	}	
-		
+	}
+
 	return 0;
 }
 
-void EDITOR::render_menubar(CUIRect menubar)
+void CEditor::RenderMenubar(CUIRect MenuBar)
 {
-	static CUIRect file /*, view, help*/;
+	static CUIRect s_File /*, view, help*/;
+
+	MenuBar.VSplitLeft(60.0f, &s_File, &MenuBar);
+	if(DoButton_Menu(&s_File, "File", 0, &s_File, 0, 0))
+		UiInvokePopupMenu(&s_File, 1, s_File.x, s_File.y+s_File.h-1.0f, 120, 150, PopupMenuFile, this);
 
-	menubar.VSplitLeft(60.0f, &file, &menubar);
-	if(DoButton_Menu(&file, "File", 0, &file, 0, 0))
-		ui_invoke_popup_menu(&file, 1, file.x, file.y+file.h-1.0f, 120, 150, popup_menu_file, this);
-	
 	/*
 	menubar.VSplitLeft(5.0f, 0, &menubar);
 	menubar.VSplitLeft(60.0f, &view, &menubar);
@@ -2615,288 +2538,320 @@ void EDITOR::render_menubar(CUIRect menubar)
 		*/
 }
 
-void EDITOR::render()
+void CEditor::Render()
 {
 	// basic start
-	Graphics()->Clear(1.0f,0.0f,1.0f);
-	CUIRect view = *UI()->Screen();
+	Graphics()->Clear(1.0f, 0.0f, 1.0f);
+	CUIRect View = *UI()->Screen();
 	Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h);
-	
+
 	// reset tip
-	tooltip = 0;
-	
+	m_pTooltip = 0;
+
 	// render checker
-	render_background(view, checker_texture, 32.0f, 1.0f);
-	
-	CUIRect menubar, modebar, toolbar, statusbar, envelope_editor, toolbox;
-	
-	if(gui_active)
+	RenderBackground(View, ms_CheckerTexture, 32.0f, 1.0f);
+
+	CUIRect MenuBar, CModeBar, ToolBar, StatusBar, EnvelopeEditor, ToolBox;
+
+	if(m_GuiActive)
 	{
-		
-		view.HSplitTop(16.0f, &menubar, &view);
-		view.VSplitLeft(80.0f, &toolbox, &view);
-		view.HSplitTop(16.0f, &toolbar, &view);
-		view.HSplitBottom(16.0f, &view, &statusbar);
 
-		if(show_envelope_editor)
+		View.HSplitTop(16.0f, &MenuBar, &View);
+		View.HSplitTop(53.0f, &ToolBar, &View);
+		View.VSplitLeft(80.0f, &ToolBox, &View);
+		View.HSplitBottom(16.0f, &View, &StatusBar);
+
+		if(m_ShowEnvelopeEditor)
 		{
 			float size = 125.0f;
-			if(show_envelope_editor == 2)
+			if(m_ShowEnvelopeEditor == 2)
 				size *= 2.0f;
-			else if(show_envelope_editor == 3)
+			else if(m_ShowEnvelopeEditor == 3)
 				size *= 3.0f;
-			view.HSplitBottom(size, &view, &envelope_editor);
+			View.HSplitBottom(size, &View, &EnvelopeEditor);
 		}
 	}
-	
+
 	//	a little hack for now
-	if(mode == MODE_LAYERS)
-		do_map_editor(view, toolbar);
-	
-	if(gui_active)
+	if(m_Mode == MODE_LAYERS)
+		DoMapEditor(View, ToolBar);
+
+	if(m_GuiActive)
 	{
-		float brightness = 0.25f;
-		render_background(menubar, background_texture, 128.0f, brightness*0);
-		menubar.Margin(2.0f, &menubar);
+		float Brightness = 0.25f;
+		RenderBackground(MenuBar, ms_BackgroundTexture, 128.0f, Brightness*0);
+		MenuBar.Margin(2.0f, &MenuBar);
 
-		render_background(toolbox, background_texture, 128.0f, brightness);
-		toolbox.Margin(2.0f, &toolbox);
-		
-		render_background(toolbar, background_texture, 128.0f, brightness);
-		toolbar.Margin(2.0f, &toolbar);
-		toolbar.VSplitLeft(150.0f, &modebar, &toolbar);
+		RenderBackground(ToolBox, ms_BackgroundTexture, 128.0f, Brightness);
+		ToolBox.Margin(2.0f, &ToolBox);
+
+		RenderBackground(ToolBar, ms_BackgroundTexture, 128.0f, Brightness);
+		ToolBar.Margin(2.0f, &ToolBar);
+		ToolBar.VSplitLeft(100.0f, &CModeBar, &ToolBar);
+
+		RenderBackground(StatusBar, ms_BackgroundTexture, 128.0f, Brightness);
+		StatusBar.Margin(2.0f, &StatusBar);
 
-		render_background(statusbar, background_texture, 128.0f, brightness);
-		statusbar.Margin(2.0f, &statusbar);
-		
 		// do the toolbar
-		if(mode == MODE_LAYERS)
-			do_toolbar(toolbar);
-		
-		if(show_envelope_editor)
+		if(m_Mode == MODE_LAYERS)
+			DoToolbar(ToolBar);
+
+		if(m_ShowEnvelopeEditor)
 		{
-			render_background(envelope_editor, background_texture, 128.0f, brightness);
-			envelope_editor.Margin(2.0f, &envelope_editor);
+			RenderBackground(EnvelopeEditor, ms_BackgroundTexture, 128.0f, Brightness);
+			EnvelopeEditor.Margin(2.0f, &EnvelopeEditor);
 		}
 	}
-		
-	
-	if(mode == MODE_LAYERS)
-		render_layers(toolbox, toolbar, view);
-	else if(mode == MODE_IMAGES)
-		render_images(toolbox, toolbar, view);
+
+
+	if(m_Mode == MODE_LAYERS)
+		RenderLayers(ToolBox, ToolBar, View);
+	else if(m_Mode == MODE_IMAGES)
+		RenderImages(ToolBox, ToolBar, View);
 
 	Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h);
 
-	if(gui_active)
+	if(m_GuiActive)
 	{
-		render_menubar(menubar);
-		
-		render_modebar(modebar);
-		if(show_envelope_editor)
-			render_envelopeeditor(envelope_editor);
+		RenderMenubar(MenuBar);
+
+		RenderModebar(CModeBar);
+		if(m_ShowEnvelopeEditor)
+			RenderEnvelopeEditor(EnvelopeEditor);
 	}
 
-	if(dialog == DIALOG_FILE)
+	if(m_Dialog == DIALOG_FILE)
 	{
-		static int null_ui_target = 0;
-		UI()->SetHotItem(&null_ui_target);
-		render_file_dialog();
+		static int s_NullUiTarget = 0;
+		UI()->SetHotItem(&s_NullUiTarget);
+		RenderFileDialog();
 	}
-	
-	
-	ui_do_popup_menu();
 
-	if(gui_active)
-		render_statusbar(statusbar);
+
+	UiDoPopupMenu();
+
+	if(m_GuiActive)
+		RenderStatusbar(StatusBar);
 
 	//
-	if(config.ed_showkeys)
+	if(g_Config.m_EdShowkeys)
 	{
 		Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h);
-		TEXT_CURSOR cursor;
-		gfx_text_set_cursor(&cursor, view.x+10, view.y+view.h-24-10, 24.0f, TEXTFLAG_RENDER);
-		
-		int nkeys = 0;
+		CTextCursor Cursor;
+		TextRender()->SetCursor(&Cursor, View.x+10, View.y+View.h-24-10, 24.0f, TEXTFLAG_RENDER);
+
+		int NKeys = 0;
 		for(int i = 0; i < KEY_LAST; i++)
 		{
-			if(inp_key_pressed(i))
+			if(Input()->KeyPressed(i))
 			{
-				if(nkeys)
-					gfx_text_ex(&cursor, " + ", -1);
-				gfx_text_ex(&cursor, inp_key_name(i), -1);
-				nkeys++;
+				if(NKeys)
+					TextRender()->TextEx(&Cursor, " + ", -1);
+				TextRender()->TextEx(&Cursor, Input()->KeyName(i), -1);
+				NKeys++;
 			}
 		}
 	}
-	
-	if(show_mouse_pointer)
+
+	if(m_ShowMousePointer)
 	{
 		// render butt ugly mouse cursor
 		float mx = UI()->MouseX();
 		float my = UI()->MouseY();
-		Graphics()->TextureSet(cursor_texture);
+		Graphics()->TextureSet(ms_CursorTexture);
 		Graphics()->QuadsBegin();
-		if(ui_got_context == UI()->HotItem())
+		if(ms_pUiGotContext == UI()->HotItem())
 			Graphics()->SetColor(1,0,0,1);
-		Graphics()->QuadsDrawTL(mx,my, 16.0f, 16.0f);
+		IGraphics::CQuadItem QuadItem(mx,my, 16.0f, 16.0f);
+		Graphics()->QuadsDrawTL(&QuadItem, 1);
 		Graphics()->QuadsEnd();
 	}
-	
+
 }
 
-void EDITOR::reset(bool create_default)
+void CEditor::Reset(bool CreateDefault)
 {
-	map.clean();
+	m_Map.Clean();
 
 	// create default layers
-	if(create_default)
-		map.create_default(entities_texture);
-	
+	if(CreateDefault)
+		m_Map.CreateDefault(ms_EntitiesTexture);
+
 	/*
 	{
 	}*/
-	
-	selected_layer = 0;
-	selected_group = 0;
-	selected_quad = -1;
-	selected_points = 0;
-	selected_envelope = 0;
-	selected_image = 0;
+
+	m_SelectedLayer = 0;
+	m_SelectedGroup = 0;
+	m_SelectedQuad = -1;
+	m_SelectedPoints = 0;
+	m_SelectedEnvelope = 0;
+	m_SelectedImage = 0;
 }
 
-void MAP::make_game_layer(LAYER *layer)
+void CEditorMap::MakeGameLayer(CLayer *pLayer)
 {
-	game_layer = (LAYER_GAME *)layer;
-	game_layer->tex_id = entities_texture;
+	m_pGameLayer = (CLayerGame *)pLayer;
+	m_pGameLayer->m_pEditor = m_pEditor;
+	m_pGameLayer->m_TexId = m_pEditor->ms_EntitiesTexture;
 }
 
-void MAP::make_game_group(LAYERGROUP *group)
+void CEditorMap::MakeGameGroup(CLayerGroup *pGroup)
 {
-	game_group = group;
-	game_group->game_group = true;
-	game_group->name = "Game";
+	m_pGameGroup = pGroup;
+	m_pGameGroup->m_GameGroup = true;
+	m_pGameGroup->m_pName = "Game";
 }
 
 
 
-void MAP::clean()
+void CEditorMap::Clean()
 {
-	groups.deleteall();
-	envelopes.deleteall();
-	images.deleteall();
-	
-	game_layer = 0x0;
-	game_group = 0x0;
+	m_lGroups.delete_all();
+	m_lEnvelopes.delete_all();
+	m_lImages.delete_all();
+
+	m_pGameLayer = 0x0;
+	m_pGameGroup = 0x0;
 }
 
-void MAP::create_default(int entities_texture)
+void CEditorMap::CreateDefault(int EntitiesTexture)
 {
-	make_game_group(new_group());
-	make_game_layer(new LAYER_GAME(50, 50));
-	game_group->add_layer(game_layer);
+	MakeGameGroup(NewGroup());
+	MakeGameLayer(new CLayerGame(50, 50));
+	m_pGameGroup->AddLayer(m_pGameLayer);
 }
 
-void EDITOR::Init(class IGraphics *pGraphics)
+void CEditor::Init()
 {
-	m_pGraphics = pGraphics;
-	
-	checker_texture = Graphics()->LoadTexture("editor/checker.png", IMG_AUTO, 0);
-	background_texture = Graphics()->LoadTexture("editor/background.png", IMG_AUTO, 0);
-	cursor_texture = Graphics()->LoadTexture("editor/cursor.png", IMG_AUTO, 0);
-	entities_texture = Graphics()->LoadTexture("editor/entities.png", IMG_AUTO, 0);
-	
-	tileset_picker.make_palette();
-	tileset_picker.readonly = true;
-	
-	reset();
+	m_pInput = Kernel()->RequestInterface<IInput>();
+	m_pClient = Kernel()->RequestInterface<IClient>();
+	m_pGraphics = Kernel()->RequestInterface<IGraphics>();
+	m_pTextRender = Kernel()->RequestInterface<ITextRender>();
+	m_RenderTools.m_pGraphics = m_pGraphics;
+	m_RenderTools.m_pUI = &m_UI;
+	m_UI.SetGraphics(m_pGraphics, m_pTextRender);
+	m_Map.m_pEditor = this;
+
+	ms_CheckerTexture = Graphics()->LoadTexture("editor/checker.png", CImageInfo::FORMAT_AUTO, 0);
+	ms_BackgroundTexture = Graphics()->LoadTexture("editor/background.png", CImageInfo::FORMAT_AUTO, 0);
+	ms_CursorTexture = Graphics()->LoadTexture("editor/cursor.png", CImageInfo::FORMAT_AUTO, 0);
+	ms_EntitiesTexture = Graphics()->LoadTexture("editor/entities.png", CImageInfo::FORMAT_AUTO, 0);
+
+	m_TilesetPicker.m_pEditor = this;
+	m_TilesetPicker.MakePalette();
+	m_TilesetPicker.m_Readonly = true;
+
+	m_Brush.m_pMap = &m_Map;
+
+	Reset();
 }
 
-void EDITOR::UpdateAndRender()
+void CEditor::DoMapBorder()
 {
-	static int mouse_x = 0;
-	static int mouse_y = 0;
-	
-	if(animate)
-		animate_time = (time_get()-animate_start)/(float)time_freq();
+    CLayerTiles *pT = (CLayerTiles *)GetSelectedLayerType(0, LAYERTYPE_TILES);
+    
+    for(int i = 0; i < pT->m_Width*2; ++i)
+        pT->m_pTiles[i].m_Index = 1;
+        
+    for(int i = 0; i < pT->m_Width*pT->m_Height; ++i)
+    {
+        if(i%pT->m_Width < 2 || i%pT->m_Width > pT->m_Width-3)
+            pT->m_pTiles[i].m_Index = 1;
+    }
+    
+    for(int i = ((pT->m_Width-2)*pT->m_Height); i < pT->m_Width*pT->m_Height; ++i)
+        pT->m_pTiles[i].m_Index = 1;
+}
+
+void CEditor::UpdateAndRender()
+{
+	static int s_MouseX = 0;
+	static int s_MouseY = 0;
+
+	if(m_Animate)
+		m_AnimateTime = (time_get()-m_AnimateStart)/(float)time_freq();
 	else
-		animate_time = 0;
-	ui_got_context = 0;
+		m_AnimateTime = 0;
+	ms_pUiGotContext = 0;
 
 	// handle mouse movement
-	float mx, my, mwx, mwy;
+	float mx, my, Mwx, Mwy;
 	int rx, ry;
 	{
-		inp_mouse_relative(&rx, &ry);
-		mouse_delta_x = rx;
-		mouse_delta_y = ry;
-		
-		if(!lock_mouse)
+		Input()->MouseRelative(&rx, &ry);
+		m_MouseDeltaX = rx;
+		m_MouseDeltaY = ry;
+
+		if(!m_LockMouse)
 		{
-			mouse_x += rx;
-			mouse_y += ry;
+			s_MouseX += rx;
+			s_MouseY += ry;
 		}
-		
-		if(mouse_x < 0) mouse_x = 0;
-		if(mouse_y < 0) mouse_y = 0;
-		if(mouse_x > UI()->Screen()->w) mouse_x = (int)UI()->Screen()->w;
-		if(mouse_y > UI()->Screen()->h) mouse_y = (int)UI()->Screen()->h;
+
+		if(s_MouseX < 0) s_MouseX = 0;
+		if(s_MouseY < 0) s_MouseY = 0;
+		if(s_MouseX > UI()->Screen()->w) s_MouseX = (int)UI()->Screen()->w;
+		if(s_MouseY > UI()->Screen()->h) s_MouseY = (int)UI()->Screen()->h;
 
 		// update the ui
-		mx = mouse_x;
-		my = mouse_y;
-		mwx = 0;
-		mwy = 0;
-		
+		mx = s_MouseX;
+		my = s_MouseY;
+		Mwx = 0;
+		Mwy = 0;
+
 		// fix correct world x and y
-		LAYERGROUP *g = get_selected_group();
+		CLayerGroup *g = GetSelectedGroup();
 		if(g)
 		{
-			float points[4];
-			g->mapping(points);
-
-			float world_width = points[2]-points[0];
-			float world_height = points[3]-points[1];
-			
-			mwx = points[0] + world_width * (mouse_x/UI()->Screen()->w);
-			mwy = points[1] + world_height * (mouse_y/UI()->Screen()->h);
-			mouse_delta_wx = mouse_delta_x*(world_width / UI()->Screen()->w);
-			mouse_delta_wy = mouse_delta_y*(world_height / UI()->Screen()->h);
+			float aPoints[4];
+			g->Mapping(aPoints);
+
+			float WorldWidth = aPoints[2]-aPoints[0];
+			float WorldHeight = aPoints[3]-aPoints[1];
+
+			Mwx = aPoints[0] + WorldWidth * (s_MouseX/UI()->Screen()->w);
+			Mwy = aPoints[1] + WorldHeight * (s_MouseY/UI()->Screen()->h);
+			m_MouseDeltaWx = m_MouseDeltaX*(WorldWidth / UI()->Screen()->w);
+			m_MouseDeltaWy = m_MouseDeltaY*(WorldHeight / UI()->Screen()->h);
 		}
-		
-		int buttons = 0;
-		if(inp_key_pressed(KEY_MOUSE_1)) buttons |= 1;
-		if(inp_key_pressed(KEY_MOUSE_2)) buttons |= 2;
-		if(inp_key_pressed(KEY_MOUSE_3)) buttons |= 4;
-		
-		UI()->Update(mx,my,mwx,mwy,buttons);
+
+		int Buttons = 0;
+		if(Input()->KeyPressed(KEY_MOUSE_1)) Buttons |= 1;
+		if(Input()->KeyPressed(KEY_MOUSE_2)) Buttons |= 2;
+		if(Input()->KeyPressed(KEY_MOUSE_3)) Buttons |= 4;
+
+		UI()->Update(mx,my,Mwx,Mwy,Buttons);
 	}
-	
+
 	// toggle gui
-	if(inp_key_down(KEY_TAB))
-		gui_active = !gui_active;
+	if(Input()->KeyDown(KEY_TAB))
+		m_GuiActive = !m_GuiActive;
 
-	if(inp_key_down(KEY_F5))
-		save("maps/debug_test2.map");
+	if(Input()->KeyDown(KEY_F5))
+		Save("maps/debug_test2.map");
 
-	if(inp_key_down(KEY_F6))
-		load("maps/debug_test2.map");
-	
-	if(inp_key_down(KEY_F8))
-		load("maps/debug_test.map");
+	if(Input()->KeyDown(KEY_F6))
+		Load("maps/debug_test2.map");
 	
-	if(inp_key_down(KEY_F10))
-		show_mouse_pointer = false;
+	if(Input()->KeyDown(KEY_F8))
+		Load("maps/debug_test.map");
 	
-	render();
-	
-	if(inp_key_down(KEY_F10))
+	if(Input()->KeyDown(KEY_F7))
+		Save("maps/quicksave.map");
+
+	if(Input()->KeyDown(KEY_F10))
+		m_ShowMousePointer = false;
+
+	Render();
+
+	if(Input()->KeyDown(KEY_F10))
 	{
 		Graphics()->TakeScreenshot();
-		show_mouse_pointer = true;
+		m_ShowMousePointer = true;
 	}
-	
-	inp_clear_events();
+
+	Input()->ClearEvents();
 }
 
-IEditor *CreateEditor() { return new EDITOR; }
+IEditor *CreateEditor() { return new CEditor; }
diff --git a/src/game/editor/ed_editor.h b/src/game/editor/ed_editor.h
new file mode 100644
index 00000000..1730fb0a
--- /dev/null
+++ b/src/game/editor/ed_editor.h
@@ -0,0 +1,615 @@
+#ifndef GAME_EDITOR_ED_EDITOR_H
+#define GAME_EDITOR_ED_EDITOR_H
+
+#include <base/system.h>
+#include <base/math.h>
+#include <base/tl/array.h>
+#include <base/tl/algorithm.h>
+
+#include <math.h>
+#include <game/mapitems.h>
+#include <game/client/render.h>
+
+#include <engine/shared/datafile.h>
+#include <engine/shared/config.h>
+#include <engine/editor.h>
+#include <engine/graphics.h>
+
+#include <game/client/ui.h>
+
+typedef void (*INDEX_MODIFY_FUNC)(int *pIndex);
+
+//CRenderTools m_RenderTools;
+
+// CEditor SPECIFIC
+enum
+{
+	MODE_LAYERS=0,
+	MODE_IMAGES,
+	
+	DIALOG_NONE=0,
+	DIALOG_FILE,
+};
+
+struct CEntity
+{
+	CPoint m_Position;
+	int m_Type;
+};
+
+class CEnvelope
+{
+public:
+	int m_Channels;
+	array<CEnvPoint> m_lPoints;
+	char m_aName[32];
+	float m_Bottom, m_Top;
+	
+	CEnvelope(int Chan)
+	{
+		m_Channels = Chan;
+		m_aName[0] = 0;
+		m_Bottom = 0;
+		m_Top = 0;
+	}
+	
+	void Resort()
+	{
+		sort(m_lPoints.all());
+		FindTopBottom(0xf);
+	}
+
+	void FindTopBottom(int ChannelMask)
+	{
+		m_Top = -1000000000.0f;
+		m_Bottom = 1000000000.0f;
+		for(int i = 0; i < m_lPoints.size(); i++)
+		{
+			for(int c = 0; c < m_Channels; c++)
+			{
+				if(ChannelMask&(1<<c))
+				{
+					float v = fx2f(m_lPoints[i].m_aValues[c]);
+					if(v > m_Top) m_Top = v;
+					if(v < m_Bottom) m_Bottom = v;
+				}
+			}
+		}
+	}
+	
+	int Eval(float Time, float *pResult)
+	{
+		CRenderTools::RenderEvalEnvelope(m_lPoints.base_ptr(), m_lPoints.size(), m_Channels, Time, pResult);
+		return m_Channels;
+	}
+	
+	void AddPoint(int Time, int v0, int v1=0, int v2=0, int v3=0)
+	{
+		CEnvPoint p;
+		p.m_Time = Time;
+		p.m_aValues[0] = v0;
+		p.m_aValues[1] = v1;
+		p.m_aValues[2] = v2;
+		p.m_aValues[3] = v3;
+		p.m_Curvetype = CURVETYPE_LINEAR;
+		m_lPoints.add(p);
+		Resort();
+	}
+	
+	float EndTime()
+	{
+		if(m_lPoints.size())
+			return m_lPoints[m_lPoints.size()-1].m_Time*(1.0f/1000.0f);
+		return 0;
+	}
+};
+
+
+class CLayer;
+class CLayerGroup;
+class CEditorMap;
+
+class CLayer
+{
+public:
+	class CEditor *m_pEditor;
+	class IGraphics *Graphics();
+	class ITextRender *TextRender();
+
+	CLayer()
+	{
+		m_Type = LAYERTYPE_INVALID;
+		m_pTypeName = "(invalid)";
+		m_Visible = true;
+		m_Readonly = false;
+		m_Flags = 0;
+		m_pEditor = 0;
+	}
+	
+	virtual ~CLayer()
+	{
+	}
+	
+	
+	virtual void BrushSelecting(CUIRect Rect) {}
+	virtual int BrushGrab(CLayerGroup *pBrush, CUIRect Rect) { return 0; }
+	virtual void FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect) {}
+	virtual void BrushDraw(CLayer *pBrush, float x, float y) {}
+	virtual void BrushPlace(CLayer *pBrush, float x, float y) {}
+	virtual void BrushFlipX() {}
+	virtual void BrushFlipY() {}
+	virtual void BrushRotate(float Amount) {}
+	
+	virtual void Render() {}
+	virtual int RenderProperties(CUIRect *pToolbox) { return 0; }
+	
+	virtual void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc) {}
+	virtual void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc) {}
+	
+	virtual void GetSize(float *w, float *h) { *w = 0; *h = 0;}
+	
+	const char *m_pTypeName;
+	int m_Type;
+	int m_Flags;
+
+	bool m_Readonly;
+	bool m_Visible;
+};
+
+class CLayerGroup
+{
+public:
+	class CEditorMap *m_pMap;
+	
+	array<CLayer*> m_lLayers;
+	
+	int m_OffsetX;
+	int m_OffsetY;
+
+	int m_ParallaxX;
+	int m_ParallaxY;
+	
+	int m_UseClipping;
+	int m_ClipX;
+	int m_ClipY;
+	int m_ClipW;
+	int m_ClipH;
+	
+	const char *m_pName;
+	bool m_GameGroup;
+	bool m_Visible;
+	
+	CLayerGroup();
+	~CLayerGroup();
+	
+	void Convert(CUIRect *pRect);
+	void Render();
+	void MapScreen();
+	void Mapping(float *pPoints);
+
+	void GetSize(float *w, float *h);
+	
+	void DeleteLayer(int Index);
+	int SwapLayers(int Index0, int Index1);
+	
+	bool IsEmpty() const 
+	{
+		return m_lLayers.size() == 0;
+	}
+	
+	void Clear() 
+	{ 
+		m_lLayers.delete_all();
+	}
+	
+	void AddLayer(CLayer *l)
+	{
+		m_lLayers.add(l);
+	}
+
+	void ModifyImageIndex(INDEX_MODIFY_FUNC Func)
+	{
+		for(int i = 0; i < m_lLayers.size(); i++)
+			m_lLayers[i]->ModifyImageIndex(Func);
+	}
+	
+	void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC Func)
+	{
+		for(int i = 0; i < m_lLayers.size(); i++)
+			m_lLayers[i]->ModifyEnvelopeIndex(Func);
+	}
+};
+
+class CEditorImage : public CImageInfo
+{
+public:
+	CEditor *m_pEditor;
+	
+	CEditorImage(CEditor *pEditor)
+	{
+		m_pEditor = pEditor;
+		m_TexId = -1;
+		m_aName[0] = 0;
+		m_External = 0;
+		m_Width = 0;
+		m_Height = 0;
+		m_pData = 0;
+		m_Format = 0;
+	}
+	
+	~CEditorImage();
+	
+	void AnalyseTileFlags();
+	
+	int m_TexId;
+	int m_External;
+	char m_aName[128];
+	unsigned char m_aTileFlags[256];
+};
+
+class CEditorMap
+{
+	void MakeGameGroup(CLayerGroup *pGroup);
+	void MakeGameLayer(CLayer *pLayer);
+public:
+	CEditor *m_pEditor;
+
+	CEditorMap()
+	{
+		Clean();
+	}
+
+	array<CLayerGroup*> m_lGroups;
+	array<CEditorImage*> m_lImages;
+	array<CEnvelope*> m_lEnvelopes;
+	
+	class CLayerGame *m_pGameLayer;
+	CLayerGroup *m_pGameGroup;
+	
+	CEnvelope *NewEnvelope(int Channels)
+	{
+		CEnvelope *e = new CEnvelope(Channels);
+		m_lEnvelopes.add(e);
+		return e;
+	}
+	
+	CLayerGroup *NewGroup()
+	{
+		CLayerGroup *g = new CLayerGroup;
+		g->m_pMap = this;
+		m_lGroups.add(g);
+		return g;
+	}
+	
+	int SwapGroups(int Index0, int Index1)
+	{
+		if(Index0 < 0 || Index0 >= m_lGroups.size()) return Index0;
+		if(Index1 < 0 || Index1 >= m_lGroups.size()) return Index0;
+		if(Index0 == Index1) return Index0;
+		swap(m_lGroups[Index0], m_lGroups[Index1]);
+		return Index1;
+	}
+	
+	void DeleteGroup(int Index)
+	{
+		if(Index < 0 || Index >= m_lGroups.size()) return;
+		delete m_lGroups[Index];
+		m_lGroups.remove_index(Index);
+	}
+	
+	void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc)
+	{
+		for(int i = 0; i < m_lGroups.size(); i++)
+			m_lGroups[i]->ModifyImageIndex(pfnFunc);
+	}
+	
+	void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc)
+	{
+		for(int i = 0; i < m_lGroups.size(); i++)
+			m_lGroups[i]->ModifyEnvelopeIndex(pfnFunc);
+	}
+	
+	void Clean();
+	void CreateDefault(int EntitiesTexture);
+
+	// io	
+	int Save(class IStorage *pStorage, const char *pFilename);
+	int Load(class IStorage *pStorage, const char *pFilename);
+};
+
+
+struct CProperty
+{
+	const char *m_pName;
+	int m_Value;
+	int m_Type;
+	int m_Min;
+	int m_Max;
+};
+
+enum
+{
+	PROPTYPE_NULL=0,
+	PROPTYPE_BOOL,
+	PROPTYPE_INT_STEP,
+	PROPTYPE_INT_SCROLL,
+	PROPTYPE_COLOR,
+	PROPTYPE_IMAGE,
+	PROPTYPE_ENVELOPE,
+};
+
+typedef struct
+{
+	int x, y;
+	int w, h;
+} RECTi;
+
+class CLayerTiles : public CLayer
+{
+public:
+	CLayerTiles(int w, int h);
+	~CLayerTiles();
+
+	void Resize(int NewW, int NewH);
+
+	void MakePalette();
+	virtual void Render();
+
+	int ConvertX(float x) const;
+	int ConvertY(float y) const;
+	void Convert(CUIRect Rect, RECTi *pOut);
+	void Snap(CUIRect *pRect);
+	void Clamp(RECTi *pRect);
+
+	virtual void BrushSelecting(CUIRect Rect);
+	virtual int BrushGrab(CLayerGroup *pBrush, CUIRect Rect);
+	virtual void FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect);
+	virtual void BrushDraw(CLayer *pBrush, float wx, float wy);
+	virtual void BrushFlipX();
+	virtual void BrushFlipY();
+	
+	virtual int RenderProperties(CUIRect *pToolbox);
+
+	virtual void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc);
+	virtual void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc);
+	
+	void PrepareForSave();
+
+	void GetSize(float *w, float *h) { *w = m_Width*32.0f;  *h = m_Height*32.0f; }
+	
+	int m_TexId;
+	int m_Game;
+	int m_Image;
+	int m_Width;
+	int m_Height;
+	CTile *m_pTiles;
+};
+
+class CLayerQuads : public CLayer
+{
+public:
+	CLayerQuads();
+	~CLayerQuads();
+
+	virtual void Render();
+	CQuad *NewQuad();
+
+	virtual void BrushSelecting(CUIRect Rect);
+	virtual int BrushGrab(CLayerGroup *pBrush, CUIRect Rect);
+	virtual void BrushPlace(CLayer *pBrush, float wx, float wy);
+	virtual void BrushFlipX();
+	virtual void BrushFlipY();
+	virtual void BrushRotate(float Amount);
+	
+	virtual int RenderProperties(CUIRect *pToolbox);
+
+	virtual void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc);
+	virtual void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc);
+	
+	void GetSize(float *w, float *h);
+	
+	int m_Image;
+	array<CQuad> m_lQuads;
+};
+
+class CLayerGame : public CLayerTiles
+{
+public:
+	CLayerGame(int w, int h);
+	~CLayerGame();
+
+	virtual int RenderProperties(CUIRect *pToolbox);
+};
+
+class CEditor : public IEditor
+{
+	class IInput *m_pInput;
+	class IClient *m_pClient;
+	class IGraphics *m_pGraphics;
+	class ITextRender *m_pTextRender;
+	CRenderTools m_RenderTools;
+	CUI m_UI;
+public:
+	class IInput *Input() { return m_pInput; };
+	class IClient *Client() { return m_pClient; };
+	class IGraphics *Graphics() { return m_pGraphics; };
+	class ITextRender *TextRender() { return m_pTextRender; };
+	CUI *UI() { return &m_UI; }
+	CRenderTools *RenderTools() { return &m_RenderTools; }
+
+	CEditor() : m_TilesetPicker(16, 16)
+	{
+		m_pInput = 0;
+		m_pClient = 0;
+		m_pGraphics = 0;
+		m_pTextRender = 0;
+
+		m_Mode = MODE_LAYERS;
+		m_Dialog = 0;
+		m_pTooltip = 0;
+
+		m_aFileName[0] = 0;
+
+		m_WorldOffsetX = 0;
+		m_WorldOffsetY = 0;
+		m_EditorOffsetX = 0.0f;
+		m_EditorOffsetY = 0.0f;
+		
+		m_WorldZoom = 1.0f;
+		m_ZoomLevel = 200;
+		m_LockMouse = false;
+		m_ShowMousePointer = true;
+		m_MouseDeltaX = 0;
+		m_MouseDeltaY = 0;
+		m_MouseDeltaWx = 0;
+		m_MouseDeltaWy = 0;
+		
+		m_GuiActive = true;
+		m_ProofBorders = false;
+		
+		m_ShowDetail = true;
+		m_Animate = false;
+		m_AnimateStart = 0;
+		m_AnimateTime = 0;
+		m_AnimateSpeed = 1;
+		
+		m_ShowEnvelopeEditor = 0;
+		
+		ms_CheckerTexture = 0;
+		ms_BackgroundTexture = 0;
+		ms_CursorTexture = 0;
+		ms_EntitiesTexture = 0;
+		
+		ms_pUiGotContext = 0;
+	}
+	
+	virtual void Init();
+	virtual void UpdateAndRender();
+	
+	void InvokeFileDialog(int ListdirType, const char *pTitle, const char *pButtonText,
+		const char *pBasepath, const char *pDefaultName,
+		void (*pfnFunc)(const char *pFilename, void *pUser), void *pUser);
+	
+	void Reset(bool CreateDefault=true);
+	int Save(const char *pFilename);
+	int Load(const char *pFilename);
+	int Append(const char *pFilename);
+	void Render();
+
+	CQuad *GetSelectedQuad();
+	CLayer *GetSelectedLayerType(int Index, int Type);
+	CLayer *GetSelectedLayer(int Index);
+	CLayerGroup *GetSelectedGroup();
+	
+	int DoProperties(CUIRect *pToolbox, CProperty *pProps, int *pIds, int *pNewVal);
+	
+	int m_Mode;
+	int m_Dialog;
+	const char *m_pTooltip;
+
+	char m_aFileName[512];
+
+	float m_WorldOffsetX;
+	float m_WorldOffsetY;
+	float m_EditorOffsetX;
+	float m_EditorOffsetY;
+	float m_WorldZoom;
+	int m_ZoomLevel;
+	bool m_LockMouse;
+	bool m_ShowMousePointer;
+	bool m_GuiActive;
+	bool m_ProofBorders;
+	float m_MouseDeltaX;
+	float m_MouseDeltaY;
+	float m_MouseDeltaWx;
+	float m_MouseDeltaWy;
+	
+	bool m_ShowDetail;
+	bool m_Animate;
+	int64 m_AnimateStart;
+	float m_AnimateTime;
+	float m_AnimateSpeed;
+	
+	int m_ShowEnvelopeEditor;
+	
+	int m_SelectedLayer;
+	int m_SelectedGroup;
+	int m_SelectedQuad;
+	int m_SelectedPoints;
+	int m_SelectedEnvelope;
+	int m_SelectedImage;
+	
+	static int ms_CheckerTexture;
+	static int ms_BackgroundTexture;
+	static int ms_CursorTexture;
+	static int ms_EntitiesTexture;
+	
+	CLayerGroup m_Brush;
+	CLayerTiles m_TilesetPicker;
+	
+	static const void *ms_pUiGotContext;
+	
+	CEditorMap m_Map;
+	
+    void DoMapBorder();
+	int DoButton_Editor_Common(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip);
+	int DoButton_Editor(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip);
+
+	int DoButton_Tab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip);
+	int DoButton_Ex(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip, int Corners);
+	int DoButton_ButtonDec(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip);
+	int DoButton_ButtonInc(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip);
+
+	int DoButton_File(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip);
+	
+	int DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip);
+	int DoButton_MenuItem(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags=0, const char *pToolTip=0);
+	
+	int DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, bool Hidden=false);
+
+	void RenderBackground(CUIRect View, int Texture, float Size, float Brightness);
+
+	void UiInvokePopupMenu(void *pId, int Flags, float x, float y, float w, float h, int (*pfnFunc)(CEditor *pEditor, CUIRect Rect), void *pExtra=0);
+	void UiDoPopupMenu();
+	
+	int UiDoValueSelector(void *pId, CUIRect *r, const char *pLabel, int Current, int Min, int Max, float Scale);
+
+	static int PopupGroup(CEditor *pEditor, CUIRect View);
+	static int PopupLayer(CEditor *pEditor, CUIRect View);
+	static int PopupQuad(CEditor *pEditor, CUIRect View);
+	static int PopupPoint(CEditor *pEditor, CUIRect View);
+	static int PopupSelectImage(CEditor *pEditor, CUIRect View);
+	static int PopupImage(CEditor *pEditor, CUIRect View);
+	static int PopupMenuFile(CEditor *pEditor, CUIRect View);
+
+
+	void PopupSelectImageInvoke(int Current, float x, float y);
+	int PopupSelectImageResult();
+	
+	vec4 ButtonColorMul(const void *pId);
+
+	void DoQuadPoint(CQuad *pQuad, int QuadIndex, int v);
+	void DoMapEditor(CUIRect View, CUIRect Toolbar);
+	void DoToolbar(CUIRect Toolbar);
+	void DoQuad(CQuad *pQuad, int Index);
+	float UiDoScrollbarV(const void *id, const CUIRect *pRect, float Current);
+	vec4 GetButtonColor(const void *id, int Checked);
+	
+	static void ReplaceImage(const char *pFilename, void *pUser);
+	static void AddImage(const char *pFilename, void *pUser);
+	
+	void RenderImages(CUIRect Toolbox, CUIRect Toolbar, CUIRect View);
+	void RenderLayers(CUIRect Toolbox, CUIRect Toolbar, CUIRect View);
+	void RenderModebar(CUIRect View);
+	void RenderStatusbar(CUIRect View);
+	void RenderEnvelopeEditor(CUIRect View);
+	
+	void RenderMenubar(CUIRect Menubar);
+	void RenderFileDialog();
+};
+
+// make sure to inline this function
+inline class IGraphics *CLayer::Graphics() { return m_pEditor->Graphics(); }
+inline class ITextRender *CLayer::TextRender() { return m_pEditor->TextRender(); }
+
+#endif
diff --git a/src/game/editor/ed_editor.hpp b/src/game/editor/ed_editor.hpp
deleted file mode 100644
index 98d1d960..00000000
--- a/src/game/editor/ed_editor.hpp
+++ /dev/null
@@ -1,589 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-
-#include <base/system.h>
-#include <base/math.hpp>
-
-#include <stdlib.h>
-#include <math.h>
-#include "array.hpp"
-#include "../mapitems.hpp"
-#include "../client/render.hpp"
-
-#include <engine/e_client_interface.h>
-#include <engine/e_datafile.h>
-#include <engine/e_config.h>
-#include <engine/client/editor.h>
-
-#include <game/client/ui.hpp>
-
-typedef void (*INDEX_MODIFY_FUNC)(int *index);
-
-//CRenderTools m_RenderTools;
-
-// EDITOR SPECIFIC
-template<typename T>
-void swap(T &a, T &b)
-{
-	T tmp = a;
-	a = b;
-	b = tmp;
-}
-
-enum
-{
-	MODE_LAYERS=0,
-	MODE_IMAGES,
-	
-	DIALOG_NONE=0,
-	DIALOG_FILE,
-};
-
-typedef struct
-{
-	POINT position;
-	int type;
-} ENTITY;
-
-class ENVELOPE
-{
-public:
-	int channels;
-	array<ENVPOINT> points;
-	char name[32];
-	float bottom, top;
-	
-	ENVELOPE(int chan)
-	{
-		channels = chan;
-		name[0] = 0;
-		bottom = 0;
-		top = 0;
-	}
-	
-	static int sort_comp(const void *v0, const void *v1)
-	{
-		const ENVPOINT *p0 = (const ENVPOINT *)v0;
-		const ENVPOINT *p1 = (const ENVPOINT *)v1;
-		if(p0->time < p1->time)
-			return -1;
-		if(p0->time > p1->time)
-			return 1;
-		return 0;
-	}
-	
-	void resort()
-	{
-		qsort(points.getptr(), points.len(), sizeof(ENVPOINT), sort_comp);
-		find_top_bottom(0xf);
-	}
-
-	void find_top_bottom(int channelmask)
-	{
-		top = -1000000000.0f;
-		bottom = 1000000000.0f;
-		for(int i = 0; i < points.len(); i++)
-		{
-			for(int c = 0; c < channels; c++)
-			{
-				if(channelmask&(1<<c))
-				{
-					float v = fx2f(points[i].values[c]);
-					if(v > top) top = v;
-					if(v < bottom) bottom = v;
-				}
-			}
-		}
-	}
-	
-	int eval(float time, float *result)
-	{
-		CRenderTools::render_eval_envelope(points.getptr(), points.len(), channels, time, result);
-		return channels;
-	}
-	
-	void add_point(int time, int v0, int v1=0, int v2=0, int v3=0)
-	{
-		ENVPOINT p;
-		p.time = time;
-		p.values[0] = v0;
-		p.values[1] = v1;
-		p.values[2] = v2;
-		p.values[3] = v3;
-		p.curvetype = CURVETYPE_LINEAR;
-		points.add(p);
-		resort();
-	}
-	
-	float end_time()
-	{
-		if(points.len())
-			return points[points.len()-1].time*(1.0f/1000.0f);
-		return 0;
-	}
-};
-
-
-class LAYER;
-class LAYERGROUP;
-class MAP;
-
-class LAYER
-{
-public:
-	class EDITOR *editor;
-	class IGraphics *Graphics();
-
-	LAYER()
-	{
-		type = LAYERTYPE_INVALID;
-		type_name = "(invalid)";
-		visible = true;
-		readonly = false;
-		flags = 0;
-		editor = 0;
-	}
-	
-	virtual ~LAYER()
-	{
-	}
-	
-	
-	virtual void brush_selecting(CUIRect rect) {}
-	virtual int brush_grab(LAYERGROUP *brush, CUIRect rect) { return 0; }
-	virtual void brush_draw(LAYER *brush, float x, float y) {}
-	virtual void brush_place(LAYER *brush, float x, float y) {}
-	virtual void brush_flip_x() {}
-	virtual void brush_flip_y() {}
-	virtual void brush_rotate(float amount) {}
-	
-	virtual void render() {}
-	virtual int render_properties(CUIRect *toolbox) { return 0; }
-	
-	virtual void modify_image_index(INDEX_MODIFY_FUNC func) {}
-	virtual void modify_envelope_index(INDEX_MODIFY_FUNC func) {}
-	
-	virtual void get_size(float *w, float *h) { *w = 0; *h = 0;}
-	
-	const char *type_name;
-	int type;
-	int flags;
-
-	bool readonly;
-	bool visible;
-};
-
-class LAYERGROUP
-{
-public:
-	class MAP *m_pMap;
-	
-	array<LAYER*> layers;
-	
-	int offset_x;
-	int offset_y;
-
-	int parallax_x;
-	int parallax_y;
-	
-	int use_clipping;
-	int clip_x;
-	int clip_y;
-	int clip_w;
-	int clip_h;
-	
-	const char *name;
-	bool game_group;
-	bool visible;
-	
-	LAYERGROUP();
-	~LAYERGROUP();
-	
-	void convert(CUIRect *rect);
-	void render();
-	void mapscreen();
-	void mapping(float *points);
-	
-	bool is_empty() const;
-	void clear();
-	void add_layer(LAYER *l);
-
-	void get_size(float *w, float *h);
-	
-	void delete_layer(int index);
-	int swap_layers(int index0, int index1);
-
-	void modify_image_index(INDEX_MODIFY_FUNC func)
-	{
-		for(int i = 0; i < layers.len(); i++)
-			layers[i]->modify_image_index(func);
-	}
-	
-	void modify_envelope_index(INDEX_MODIFY_FUNC func)
-	{
-		for(int i = 0; i < layers.len(); i++)
-			layers[i]->modify_envelope_index(func);
-	}
-};
-
-class EDITOR_IMAGE : public IMAGE_INFO
-{
-public:
-	EDITOR *editor;
-	
-	EDITOR_IMAGE(EDITOR *ed)
-	{
-		editor = editor;
-		tex_id = -1;
-		name[0] = 0;
-		external = 0;
-		width = 0;
-		height = 0;
-		data = 0;
-		format = 0;
-	}
-	
-	~EDITOR_IMAGE();
-	
-	void analyse_tileflags();
-	
-	int tex_id;
-	int external;
-	char name[128];
-	unsigned char tileflags[256];
-};
-
-class MAP
-{
-	void make_game_group(LAYERGROUP *group);
-	void make_game_layer(LAYER *layer);
-public:
-	EDITOR *editor;
-
-	MAP()
-	{
-		clean();
-	}
-
-	array<LAYERGROUP*> groups;
-	array<EDITOR_IMAGE*> images;
-	array<ENVELOPE*> envelopes;
-	
-	class LAYER_GAME *game_layer;
-	LAYERGROUP *game_group;
-	
-	ENVELOPE *new_envelope(int channels)
-	{
-		ENVELOPE *e = new ENVELOPE(channels);
-		envelopes.add(e);
-		return e;
-	}
-	
-	LAYERGROUP *new_group()
-	{
-		LAYERGROUP *g = new LAYERGROUP;
-		g->m_pMap = this;
-		groups.add(g);
-		return g;
-	}
-	
-	int swap_groups(int index0, int index1)
-	{
-		if(index0 < 0 || index0 >= groups.len()) return index0;
-		if(index1 < 0 || index1 >= groups.len()) return index0;
-		if(index0 == index1) return index0;
-		swap(groups[index0], groups[index1]);
-		return index1;
-	}
-	
-	void delete_group(int index)
-	{
-		if(index < 0 || index >= groups.len()) return;
-		delete groups[index];
-		groups.removebyindex(index);
-	}
-	
-	void modify_image_index(INDEX_MODIFY_FUNC func)
-	{
-		for(int i = 0; i < groups.len(); i++)
-			groups[i]->modify_image_index(func);
-	}
-	
-	void modify_envelope_index(INDEX_MODIFY_FUNC func)
-	{
-		for(int i = 0; i < groups.len(); i++)
-			groups[i]->modify_envelope_index(func);
-	}
-	
-	void clean();
-	void create_default(int entities_texture);
-
-	// io	
-	int save(const char *filename);
-	int load(const char *filename);
-};
-
-
-struct PROPERTY
-{
-	const char *name;
-	int value;
-	int type;
-	int min;
-	int max;
-};
-
-enum
-{
-	PROPTYPE_NULL=0,
-	PROPTYPE_BOOL,
-	PROPTYPE_INT_STEP,
-	PROPTYPE_INT_SCROLL,
-	PROPTYPE_COLOR,
-	PROPTYPE_IMAGE,
-	PROPTYPE_ENVELOPE,
-};
-
-class EDITOR : public IEditor
-{
-	class IGraphics *m_pGraphics;
-	CRenderTools m_RenderTools;
-	CUI m_UI;
-public:
-	
-	class IGraphics *Graphics() { return m_pGraphics; };
-	CUI *UI() { return &m_UI; }
-	CRenderTools *RenderTools() { return &m_RenderTools; }
-
-	EDITOR()
-	{
-		mode = MODE_LAYERS;
-		dialog = 0;
-		tooltip = 0;
-
-		world_offset_x = 0;
-		world_offset_y = 0;
-		editor_offset_x = 0.0f;
-		editor_offset_y = 0.0f;
-		
-		world_zoom = 1.0f;
-		zoom_level = 100;
-		lock_mouse = false;
-		show_mouse_pointer = true;
-		mouse_delta_x = 0;
-		mouse_delta_y = 0;
-		mouse_delta_wx = 0;
-		mouse_delta_wy = 0;
-		
-		gui_active = true;
-		proof_borders = false;
-		
-		show_detail = true;
-		animate = false;
-		animate_start = 0;
-		animate_time = 0;
-		animate_speed = 1;
-		
-		show_envelope_editor = 0;
-	}
-	
-	virtual void Init(class IGraphics *pGraphics);
-	virtual void UpdateAndRender();
-	
-	void invoke_file_dialog(int listdir_type, const char *title, const char *button_text,
-		const char *basepath, const char *default_name,
-		void (*func)(const char *filename, void *user), void *user);
-	
-	void reset(bool create_default=true);
-	int save(const char *filename);
-	int load(const char *filename);
-	int append(const char *filename);
-	void render();
-
-	QUAD *get_selected_quad();
-	LAYER *get_selected_layer_type(int index, int type);
-	LAYER *get_selected_layer(int index);
-	LAYERGROUP *get_selected_group();
-	
-	int do_properties(CUIRect *toolbox, PROPERTY *props, int *ids, int *new_val);
-	
-	int mode;
-	int dialog;
-	const char *tooltip;
-
-	float world_offset_x;
-	float world_offset_y;
-	float editor_offset_x;
-	float editor_offset_y;
-	float world_zoom;
-	int zoom_level;
-	bool lock_mouse;
-	bool show_mouse_pointer;
-	bool gui_active;
-	bool proof_borders;
-	float mouse_delta_x;
-	float mouse_delta_y;
-	float mouse_delta_wx;
-	float mouse_delta_wy;
-	
-	bool show_detail;
-	bool animate;
-	int64 animate_start;
-	float animate_time;
-	float animate_speed;
-	
-	int show_envelope_editor;
-	
-	int selected_layer;
-	int selected_group;
-	int selected_quad;
-	int selected_points;
-	int selected_envelope;
-	int selected_image;
-	
-	MAP map;
-	
-	int DoButton_Editor_Common(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip);
-	int DoButton_Editor(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip);
-
-	int DoButton_ButtonL(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip);
-	int DoButton_ButtonM(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip);
-	int DoButton_ButtonR(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip);
-	int DoButton_ButtonDec(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip);
-	int DoButton_ButtonInc(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip);
-
-	int DoButton_File(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip);
-	
-	int DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip);
-	int DoButton_MenuItem(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags=0, const char *pToolTip=0);
-	
-	int DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, bool Hidden=false);
-	//static void draw_editor_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
-	//static void draw_editor_button_menuitem(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
-
-	void render_background(CUIRect view, int texture, float size, float brightness);
-
-	void ui_invoke_popup_menu(void *id, int flags, float x, float y, float w, float h, int (*func)(EDITOR *pEditor, CUIRect rect), void *extra=0);
-	void ui_do_popup_menu();
-	
-	int ui_do_value_selector(void *id, CUIRect *r, const char *label, int current, int min, int max, float scale);
-
-	static int popup_group(EDITOR *pEditor, CUIRect view);
-	static int popup_layer(EDITOR *pEditor, CUIRect view);
-	static int popup_quad(EDITOR *pEditor, CUIRect view);
-	static int popup_point(EDITOR *pEditor, CUIRect view);
-	static int popup_select_image(EDITOR *pEditor, CUIRect view);
-	static int popup_image(EDITOR *pEditor, CUIRect view);
-	static int popup_menu_file(EDITOR *pEditor, CUIRect view);
-
-
-	void popup_select_image_invoke(int current, float x, float y);
-	int popup_select_image_result();
-	
-	vec4 button_color_mul(const void *id);
-
-	void do_quad_point(QUAD *q, int quad_index, int v);
-	void do_map_editor(CUIRect view, CUIRect toolbar);
-	void do_toolbar(CUIRect toolbar);
-	void do_quad(QUAD *q, int index);
-	float ui_do_scrollbar_v(const void *id, const CUIRect *rect, float current);
-	vec4 get_button_color(const void *id, int checked);
-	
-	static void replace_image(const char *filename, void *user);
-	static void add_image(const char *filename, void *user);
-	
-	void render_images(CUIRect toolbox, CUIRect toolbar, CUIRect view);
-	void render_layers(CUIRect toolbox, CUIRect toolbar, CUIRect view);
-	void render_modebar(CUIRect view);
-	void render_statusbar(CUIRect view);
-	void render_envelopeeditor(CUIRect view);
-	
-	void render_menubar(CUIRect menubar);
-	void render_file_dialog();
-};
-
-// make sure to inline this function
-inline class IGraphics *LAYER::Graphics() { return editor->Graphics(); }
-
-//extern EDITOR editor;
-
-typedef struct
-{
-	int x, y;
-	int w, h;
-} RECTi;
-
-class LAYER_TILES : public LAYER
-{
-public:
-	LAYER_TILES(int w, int h);
-	~LAYER_TILES();
-
-	void resize(int new_w, int new_h);
-
-	void make_palette();
-	virtual void render();
-
-	int convert_x(float x) const;
-	int convert_y(float y) const;
-	void convert(CUIRect rect, RECTi *out);
-	void snap(CUIRect *rect);
-	void clamp(RECTi *rect);
-
-	virtual void brush_selecting(CUIRect rect);
-	virtual int brush_grab(LAYERGROUP *brush, CUIRect rect);
-	virtual void brush_draw(LAYER *brush, float wx, float wy);
-	virtual void brush_flip_x();
-	virtual void brush_flip_y();
-	
-	virtual int render_properties(CUIRect *toolbox);
-
-	virtual void modify_image_index(INDEX_MODIFY_FUNC func);
-	virtual void modify_envelope_index(INDEX_MODIFY_FUNC func);
-	
-	void prepare_for_save();
-
-	void get_size(float *w, float *h) { *w = width*32.0f;  *h = height*32.0f; }
-	
-	int tex_id;
-	int game;
-	int image;
-	int width;
-	int height;
-	TILE *tiles;
-};
-
-class LAYER_QUADS : public LAYER
-{
-public:
-	LAYER_QUADS();
-	~LAYER_QUADS();
-
-	virtual void render();
-	QUAD *new_quad();
-
-	virtual void brush_selecting(CUIRect rect);
-	virtual int brush_grab(LAYERGROUP *brush, CUIRect rect);
-	virtual void brush_place(LAYER *brush, float wx, float wy);
-	virtual void brush_flip_x();
-	virtual void brush_flip_y();
-	virtual void brush_rotate(float amount);
-	
-	virtual int render_properties(CUIRect *toolbox);
-
-	virtual void modify_image_index(INDEX_MODIFY_FUNC func);
-	virtual void modify_envelope_index(INDEX_MODIFY_FUNC func);
-	
-	void get_size(float *w, float *h);
-	
-	int image;
-	array<QUAD> quads;
-};
-
-class LAYER_GAME : public LAYER_TILES
-{
-public:
-	LAYER_GAME(int w, int h);
-	~LAYER_GAME();
-
-	virtual int render_properties(CUIRect *toolbox);
-};
diff --git a/src/game/editor/ed_io.cpp b/src/game/editor/ed_io.cpp
index b8c025fb..8ca4f704 100644
--- a/src/game/editor/ed_io.cpp
+++ b/src/game/editor/ed_io.cpp
@@ -1,10 +1,9 @@
-#include <string.h>
-#include <stdio.h>
-#include <engine/client/graphics.h>
-#include "ed_editor.hpp"
+#include <engine/graphics.h>
+#include <engine/storage.h>
+#include "ed_editor.h"
 
 template<typename T>
-static int make_version(int i, const T &v)
+static int MakeVersion(int i, const T &v)
 { return (i<<16)+sizeof(T); }
 
 // backwards compatiblity
@@ -93,7 +92,7 @@ void editor_load_old(DATAFILE *df, MAP *map)
 		{
 			mapres_tilemap *tmap = (mapres_tilemap *)datafile_get_item(df, start+t,0,0);
 			
-			LAYER_TILES *l = new LAYER_TILES(tmap->width, tmap->height);
+			CLayerTiles *l = new CLayerTiles(tmap->width, tmap->height);
 			
 			if(tmap->main)
 			{
@@ -113,7 +112,7 @@ void editor_load_old(DATAFILE *df, MAP *map)
 
 			// process the data
 			unsigned char *src_data = (unsigned char *)datafile_get_data(df, tmap->data);
-			TILE *dst_data = l->tiles;
+			CTile *dst_data = l->tiles;
 			
 			for(int y = 0; y < tmap->height; y++)
 				for(int x = 0; x < tmap->width; x++, dst_data++, src_data+=2)
@@ -138,12 +137,12 @@ void editor_load_old(DATAFILE *df, MAP *map)
 			EDITOR_IMAGE *img = new EDITOR_IMAGE;
 			img->width = imgres->width;
 			img->height = imgres->height;
-			img->format = IMG_RGBA;
+			img->format = CImageInfo::FORMAT_RGBA;
 			
 			// copy image data
 			img->data = mem_alloc(img->width*img->height*4, 1);
 			mem_copy(img->data, data, img->width*img->height*4);
-			img->tex_id = Graphics()->LoadTextureRaw(img->width, img->height, img->format, img->data, IMG_AUTO, 0);
+			img->tex_id = Graphics()->LoadTextureRaw(img->width, img->height, img->format, img->data, CImageInfo::FORMAT_AUTO, 0);
 			map->images.add(img);
 			
 			// unload image
@@ -153,7 +152,7 @@ void editor_load_old(DATAFILE *df, MAP *map)
 	
 	// load entities
 	{
-		LAYER_GAME *g = map->game_layer;
+		CLayerGame *g = map->game_layer;
 		g->resize(game_width, game_height);
 		for(int t = MAPRES_ENTS_START; t < MAPRES_ENTS_END; t++)
 		{
@@ -190,190 +189,192 @@ void editor_load_old(DATAFILE *df, MAP *map)
 	}
 }*/
 
-int EDITOR::save(const char *filename)
+int CEditor::Save(const char *pFilename)
 {
-	return map.save(filename);
+	return m_Map.Save(Kernel()->RequestInterface<IStorage>(), pFilename);
 }
 
-int MAP::save(const char *filename)
+int CEditorMap::Save(class IStorage *pStorage, const char *pFileName)
 {
-	dbg_msg("editor", "saving to '%s'...", filename);
-	DATAFILE_OUT *df = datafile_create(filename);
-	if(!df)
+	dbg_msg("editor", "saving to '%s'...", pFileName);
+	CDataFileWriter df;
+	if(!df.Open(pStorage, pFileName))
 	{
-		dbg_msg("editor", "failed to open file '%s'...", filename);
+		dbg_msg("editor", "failed to open file '%s'...", pFileName);
 		return 0;
 	}
 		
 	// save version
 	{
-		MAPITEM_VERSION item;
-		item.version = 1;
-		datafile_add_item(df, MAPITEMTYPE_VERSION, 0, sizeof(item), &item);
+		CMapItemVersion Item;
+		Item.m_Version = 1;
+		df.AddItem(MAPITEMTYPE_VERSION, 0, sizeof(Item), &Item);
 	}
 
 	// save images
-	for(int i = 0; i < images.len(); i++)
+	for(int i = 0; i < m_lImages.size(); i++)
 	{
-		EDITOR_IMAGE *img = images[i];
+		CEditorImage *pImg = m_lImages[i];
 		
 		// analyse the image for when saving (should be done when we load the image)
 		// TODO!
-		img->analyse_tileflags();
+		pImg->AnalyseTileFlags();
 		
-		MAPITEM_IMAGE item;
-		item.version = 1;
+		CMapItemImage Item;
+		Item.m_Version = 1;
 		
-		item.width = img->width;
-		item.height = img->height;
-		item.external = img->external;
-		item.image_name = datafile_add_data(df, strlen(img->name)+1, img->name);
-		if(img->external)
-			item.image_data = -1;
+		Item.m_Width = pImg->m_Width;
+		Item.m_Height = pImg->m_Height;
+		Item.m_External = pImg->m_External;
+		Item.m_ImageName = df.AddData(str_length(pImg->m_aName)+1, pImg->m_aName);
+		if(pImg->m_External)
+			Item.m_ImageData = -1;
 		else
-			item.image_data = datafile_add_data(df, item.width*item.height*4, img->data);
-		datafile_add_item(df, MAPITEMTYPE_IMAGE, i, sizeof(item), &item);
+			Item.m_ImageData = df.AddData(Item.m_Width*Item.m_Height*4, pImg->m_pData);
+		df.AddItem(MAPITEMTYPE_IMAGE, i, sizeof(Item), &Item);
 	}
 	
 	// save layers
-	int layer_count = 0;
-	for(int g = 0; g < groups.len(); g++)
+	int LayerCount = 0;
+	for(int g = 0; g < m_lGroups.size(); g++)
 	{
-		LAYERGROUP *group = groups[g];
-		MAPITEM_GROUP gitem;
-		gitem.version = MAPITEM_GROUP::CURRENT_VERSION;
+		CLayerGroup *pGroup = m_lGroups[g];
+		CMapItemGroup GItem;
+		GItem.m_Version = CMapItemGroup::CURRENT_VERSION;
 		
-		gitem.parallax_x = group->parallax_x;
-		gitem.parallax_y = group->parallax_y;
-		gitem.offset_x = group->offset_x;
-		gitem.offset_y = group->offset_y;
-		gitem.use_clipping = group->use_clipping;
-		gitem.clip_x = group->clip_x;
-		gitem.clip_y = group->clip_y;
-		gitem.clip_w = group->clip_w;
-		gitem.clip_h = group->clip_h;
-		gitem.start_layer = layer_count;
-		gitem.num_layers = 0;
+		GItem.m_ParallaxX = pGroup->m_ParallaxX;
+		GItem.m_ParallaxY = pGroup->m_ParallaxY;
+		GItem.m_OffsetX = pGroup->m_OffsetX;
+		GItem.m_OffsetY = pGroup->m_OffsetY;
+		GItem.m_UseClipping = pGroup->m_UseClipping;
+		GItem.m_ClipX = pGroup->m_ClipX;
+		GItem.m_ClipY = pGroup->m_ClipY;
+		GItem.m_ClipW = pGroup->m_ClipW;
+		GItem.m_ClipH = pGroup->m_ClipH;
+		GItem.m_StartLayer = LayerCount;
+		GItem.m_NumLayers = 0;
 		
-		for(int l = 0; l < group->layers.len(); l++)
+		for(int l = 0; l < pGroup->m_lLayers.size(); l++)
 		{
-			if(group->layers[l]->type == LAYERTYPE_TILES)
+			if(pGroup->m_lLayers[l]->m_Type == LAYERTYPE_TILES)
 			{
 				dbg_msg("editor", "saving tiles layer");
-				LAYER_TILES *layer = (LAYER_TILES *)group->layers[l];
-				layer->prepare_for_save();
+				CLayerTiles *pLayer = (CLayerTiles *)pGroup->m_lLayers[l];
+				pLayer->PrepareForSave();
 				
-				MAPITEM_LAYER_TILEMAP item;
-				item.version = 2;
+				CMapItemLayerTilemap Item;
+				Item.m_Version = 2;
 				
-				item.layer.flags = layer->flags;
-				item.layer.type = layer->type;
+				Item.m_Layer.m_Flags = pLayer->m_Flags;
+				Item.m_Layer.m_Type = pLayer->m_Type;
 				
-				item.color.r = 255; // not in use right now
-				item.color.g = 255;
-				item.color.b = 255;
-				item.color.a = 255;
-				item.color_env = -1;
-				item.color_env_offset = 0;
+				Item.m_Color.r = 255; // not in use right now
+				Item.m_Color.g = 255;
+				Item.m_Color.b = 255;
+				Item.m_Color.a = 255;
+				Item.m_ColorEnv = -1;
+				Item.m_ColorEnvOffset = 0;
 				
-				item.width = layer->width;
-				item.height = layer->height;
-				item.flags = layer->game;
-				item.image = layer->image;
-				item.data = datafile_add_data(df, layer->width*layer->height*sizeof(TILE), layer->tiles);
-				datafile_add_item(df, MAPITEMTYPE_LAYER, layer_count, sizeof(item), &item);
+				Item.m_Width = pLayer->m_Width;
+				Item.m_Height = pLayer->m_Height;
+				Item.m_Flags = pLayer->m_Game;
+				Item.m_Image = pLayer->m_Image;
+				Item.m_Data = df.AddData(pLayer->m_Width*pLayer->m_Height*sizeof(CTile), pLayer->m_pTiles);
+				df.AddItem(MAPITEMTYPE_LAYER, LayerCount, sizeof(Item), &Item);
 				
-				gitem.num_layers++;
-				layer_count++;
+				GItem.m_NumLayers++;
+				LayerCount++;
 			}
-			else if(group->layers[l]->type == LAYERTYPE_QUADS)
+			else if(pGroup->m_lLayers[l]->m_Type == LAYERTYPE_QUADS)
 			{
 				dbg_msg("editor", "saving quads layer");
-				LAYER_QUADS *layer = (LAYER_QUADS *)group->layers[l];
-				if(layer->quads.len())
+				CLayerQuads *pLayer = (CLayerQuads *)pGroup->m_lLayers[l];
+				if(pLayer->m_lQuads.size())
 				{
-					MAPITEM_LAYER_QUADS item;
-					item.version = 1;
-					item.layer.flags =  layer->flags;
-					item.layer.type = layer->type;
-					item.image = layer->image;
+					CMapItemLayerQuads Item;
+					Item.m_Version = 1;
+					Item.m_Layer.m_Flags =  pLayer->m_Flags;
+					Item.m_Layer.m_Type = pLayer->m_Type;
+					Item.m_Image = pLayer->m_Image;
 					
 					// add the data
-					item.num_quads = layer->quads.len();
-					item.data = datafile_add_data_swapped(df, layer->quads.len()*sizeof(QUAD), layer->quads.getptr());
-					datafile_add_item(df, MAPITEMTYPE_LAYER, layer_count, sizeof(item), &item);
+					Item.m_NumQuads = pLayer->m_lQuads.size();
+					Item.m_Data = df.AddDataSwapped(pLayer->m_lQuads.size()*sizeof(CQuad), pLayer->m_lQuads.base_ptr());
+					df.AddItem(MAPITEMTYPE_LAYER, LayerCount, sizeof(Item), &Item);
 					
 					// clean up
 					//mem_free(quads);
 
-					gitem.num_layers++;
-					layer_count++;
+					GItem.m_NumLayers++;
+					LayerCount++;
 				}
 			}
 		}
 		
-		datafile_add_item(df, MAPITEMTYPE_GROUP, g, sizeof(gitem), &gitem);
+		df.AddItem(MAPITEMTYPE_GROUP, g, sizeof(GItem), &GItem);
 	}
 	
 	// save envelopes
-	int point_count = 0;
-	for(int e = 0; e < envelopes.len(); e++)
+	int PointCount = 0;
+	for(int e = 0; e < m_lEnvelopes.size(); e++)
 	{
-		MAPITEM_ENVELOPE item;
-		item.version = 1;
-		item.channels = envelopes[e]->channels;
-		item.start_point = point_count;
-		item.num_points = envelopes[e]->points.len();
-		item.name = -1;
+		CMapItemEnvelope Item;
+		Item.m_Version = 1;
+		Item.m_Channels = m_lEnvelopes[e]->m_Channels;
+		Item.m_StartPoint = PointCount;
+		Item.m_NumPoints = m_lEnvelopes[e]->m_lPoints.size();
+		Item.m_Name = -1;
 		
-		datafile_add_item(df, MAPITEMTYPE_ENVELOPE, e, sizeof(item), &item);
-		point_count += item.num_points;
+		df.AddItem(MAPITEMTYPE_ENVELOPE, e, sizeof(Item), &Item);
+		PointCount += Item.m_NumPoints;
 	}
 	
 	// save points
-	int totalsize = sizeof(ENVPOINT) * point_count;
-	ENVPOINT *points = (ENVPOINT *)mem_alloc(totalsize, 1);
-	point_count = 0;
+	int TotalSize = sizeof(CEnvPoint) * PointCount;
+	CEnvPoint *pPoints = (CEnvPoint *)mem_alloc(TotalSize, 1);
+	PointCount = 0;
 	
-	for(int e = 0; e < envelopes.len(); e++)
+	for(int e = 0; e < m_lEnvelopes.size(); e++)
 	{
-		int count = envelopes[e]->points.len();
-		mem_copy(&points[point_count], envelopes[e]->points.getptr(), sizeof(ENVPOINT)*count);
-		point_count += count;
+		int Count = m_lEnvelopes[e]->m_lPoints.size();
+		mem_copy(&pPoints[PointCount], m_lEnvelopes[e]->m_lPoints.base_ptr(), sizeof(CEnvPoint)*Count);
+		PointCount += Count;
 	}
 
-	datafile_add_item(df, MAPITEMTYPE_ENVPOINTS, 0, totalsize, points);
+	df.AddItem(MAPITEMTYPE_ENVPOINTS, 0, TotalSize, pPoints);
 	
 	// finish the data file
-	datafile_finish(df);
+	df.Finish();
 	dbg_msg("editor", "done");
 	
 	// send rcon.. if we can
-	if(client_rcon_authed())
+	/*
+	if(Client()->RconAuthed())
 	{
-		client_rcon("sv_map_reload 1");
-	}
+		Client()->Rcon("sv_map_reload 1");
+	}*/
 	
 	return 1;
 }
 
-int EDITOR::load(const char *filename)
+int CEditor::Load(const char *pFileName)
 {
-	reset();
-	return map.load(filename);
+	Reset();
+	return m_Map.Load(Kernel()->RequestInterface<IStorage>(), pFileName);
 }
 
-int MAP::load(const char *filename)
+int CEditorMap::Load(class IStorage *pStorage, const char *pFileName)
 {
-	DATAFILE *df = datafile_load(filename);
-	if(!df)
+	CDataFileReader DataFile;
+	//DATAFILE *df = datafile_load(filename);
+	if(!DataFile.Open(pStorage, pFileName))
 		return 0;
 		
-	clean();
+	Clean();
 
 	// check version
-	MAPITEM_VERSION *item = (MAPITEM_VERSION *)datafile_find_item(df, MAPITEMTYPE_VERSION, 0);
-	if(!item)
+	CMapItemVersion *pItem = (CMapItemVersion *)DataFile.FindItem(MAPITEMTYPE_VERSION, 0);
+	if(!pItem)
 	{
 		// import old map
 		/*MAP old_mapstuff;
@@ -381,224 +382,231 @@ int MAP::load(const char *filename)
 		editor_load_old(df, this);
 		*/
 	}
-	else if(item->version == 1)
+	else if(pItem->m_Version == 1)
 	{
 		//editor.reset(false);
 		
 		// load images
 		{
-			int start, num;
-			datafile_get_type(df, MAPITEMTYPE_IMAGE, &start, &num);
-			for(int i = 0; i < num; i++)
+			int Start, Num;
+			DataFile.GetType( MAPITEMTYPE_IMAGE, &Start, &Num);
+			for(int i = 0; i < Num; i++)
 			{
-				MAPITEM_IMAGE *item = (MAPITEM_IMAGE *)datafile_get_item(df, start+i, 0, 0);
-				char *name = (char *)datafile_get_data(df, item->image_name);
+				CMapItemImage *pItem = (CMapItemImage *)DataFile.GetItem(Start+i, 0, 0);
+				char *pName = (char *)DataFile.GetData(pItem->m_ImageName);
 
 				// copy base info				
-				EDITOR_IMAGE *img = new EDITOR_IMAGE(editor);
-				img->external = item->external;
+				CEditorImage *pImg = new CEditorImage(m_pEditor);
+				pImg->m_External = pItem->m_External;
 
-				if(item->external)
+				if(pItem->m_External)
 				{
-					char buf[256];
-					sprintf(buf, "mapres/%s.png", name);
+					char aBuf[256];
+					str_format(aBuf, sizeof(aBuf),"mapres/%s.png", pName);
 					
 					// load external
-					EDITOR_IMAGE imginfo(editor);
-					if(editor->Graphics()->LoadPNG(&imginfo, buf))
+					CEditorImage ImgInfo(m_pEditor);
+					if(m_pEditor->Graphics()->LoadPNG(&ImgInfo, aBuf))
 					{
-						*img = imginfo;
-						img->tex_id = editor->Graphics()->LoadTextureRaw(imginfo.width, imginfo.height, imginfo.format, imginfo.data, IMG_AUTO, 0);
-						img->external = 1;
+						*pImg = ImgInfo;
+						pImg->m_TexId = m_pEditor->Graphics()->LoadTextureRaw(ImgInfo.m_Width, ImgInfo.m_Height, ImgInfo.m_Format, ImgInfo.m_pData, CImageInfo::FORMAT_AUTO, 0);
+						pImg->m_External = 1;
 					}
 				}
 				else
 				{
-					img->width = item->width;
-					img->height = item->height;
-					img->format = IMG_RGBA;
+					pImg->m_Width = pItem->m_Width;
+					pImg->m_Height = pItem->m_Height;
+					pImg->m_Format = CImageInfo::FORMAT_RGBA;
 					
 					// copy image data
-					void *data = datafile_get_data(df, item->image_data);
-					img->data = mem_alloc(img->width*img->height*4, 1);
-					mem_copy(img->data, data, img->width*img->height*4);
-					img->tex_id = editor->Graphics()->LoadTextureRaw(img->width, img->height, img->format, img->data, IMG_AUTO, 0);
+					void *pData = DataFile.GetData(pItem->m_ImageData);
+					pImg->m_pData = mem_alloc(pImg->m_Width*pImg->m_Height*4, 1);
+					mem_copy(pImg->m_pData, pData, pImg->m_Width*pImg->m_Height*4);
+					pImg->m_TexId = m_pEditor->Graphics()->LoadTextureRaw(pImg->m_Width, pImg->m_Height, pImg->m_Format, pImg->m_pData, CImageInfo::FORMAT_AUTO, 0);
 				}
 
 				// copy image name
-				if(name)
-					strncpy(img->name, name, 128);
+				if(pName)
+					str_copy(pImg->m_aName, pName, 128);
 
-				images.add(img);
+				m_lImages.add(pImg);
 				
 				// unload image
-				datafile_unload_data(df, item->image_data);
-				datafile_unload_data(df, item->image_name);
+				DataFile.UnloadData(pItem->m_ImageData);
+				DataFile.UnloadData(pItem->m_ImageName);
 			}
 		}
 		
 		// load groups
 		{
-			int layers_start, layers_num;
-			datafile_get_type(df, MAPITEMTYPE_LAYER, &layers_start, &layers_num);
+			int LayersStart, LayersNum;
+			DataFile.GetType(MAPITEMTYPE_LAYER, &LayersStart, &LayersNum);
 			
-			int start, num;
-			datafile_get_type(df, MAPITEMTYPE_GROUP, &start, &num);
-			for(int g = 0; g < num; g++)
+			int Start, Num;
+			DataFile.GetType(MAPITEMTYPE_GROUP, &Start, &Num);
+			for(int g = 0; g < Num; g++)
 			{
-				MAPITEM_GROUP *gitem = (MAPITEM_GROUP *)datafile_get_item(df, start+g, 0, 0);
+				CMapItemGroup *pGItem = (CMapItemGroup *)DataFile.GetItem(Start+g, 0, 0);
 				
-				if(gitem->version < 1 || gitem->version > MAPITEM_GROUP::CURRENT_VERSION)
+				if(pGItem->m_Version < 1 || pGItem->m_Version > CMapItemGroup::CURRENT_VERSION)
 					continue;
 				
-				LAYERGROUP *group = new_group();
-				group->parallax_x = gitem->parallax_x;
-				group->parallax_y = gitem->parallax_y;
-				group->offset_x = gitem->offset_x;
-				group->offset_y = gitem->offset_y;
+				CLayerGroup *pGroup = NewGroup();
+				pGroup->m_ParallaxX = pGItem->m_ParallaxX;
+				pGroup->m_ParallaxY = pGItem->m_ParallaxY;
+				pGroup->m_OffsetX = pGItem->m_OffsetX;
+				pGroup->m_OffsetY = pGItem->m_OffsetY;
 				
-				if(gitem->version >= 2)
+				if(pGItem->m_Version >= 2)
 				{
-					group->use_clipping = gitem->use_clipping;
-					group->clip_x = gitem->clip_x;
-					group->clip_y = gitem->clip_y;
-					group->clip_w = gitem->clip_w;
-					group->clip_h = gitem->clip_h;
+					pGroup->m_UseClipping = pGItem->m_UseClipping;
+					pGroup->m_ClipX = pGItem->m_ClipX;
+					pGroup->m_ClipY = pGItem->m_ClipY;
+					pGroup->m_ClipW = pGItem->m_ClipW;
+					pGroup->m_ClipH = pGItem->m_ClipH;
 				}
 				
-				for(int l = 0; l < gitem->num_layers; l++)
+				for(int l = 0; l < pGItem->m_NumLayers; l++)
 				{
-					LAYER *layer = 0;
-					MAPITEM_LAYER *layer_item = (MAPITEM_LAYER *)datafile_get_item(df, layers_start+gitem->start_layer+l, 0, 0);
-					if(!layer_item)
+					CLayer *pLayer = 0;
+					CMapItemLayer *pLayerItem = (CMapItemLayer *)DataFile.GetItem(LayersStart+pGItem->m_StartLayer+l, 0, 0);
+					if(!pLayerItem)
 						continue;
 						
-					if(layer_item->type == LAYERTYPE_TILES)
+					if(pLayerItem->m_Type == LAYERTYPE_TILES)
 					{
-						MAPITEM_LAYER_TILEMAP *tilemap_item = (MAPITEM_LAYER_TILEMAP *)layer_item;
-						LAYER_TILES *tiles = 0;
+						CMapItemLayerTilemap *pTilemapItem = (CMapItemLayerTilemap *)pLayerItem;
+						CLayerTiles *pTiles = 0;
 						
-						if(tilemap_item->flags&1)
+						if(pTilemapItem->m_Flags&1)
 						{
-							tiles = new LAYER_GAME(tilemap_item->width, tilemap_item->height);
-							make_game_layer(tiles);
-							make_game_group(group);
+							pTiles = new CLayerGame(pTilemapItem->m_Width, pTilemapItem->m_Height);
+							MakeGameLayer(pTiles);
+							MakeGameGroup(pGroup);
 						}
 						else
-							tiles = new LAYER_TILES(tilemap_item->width, tilemap_item->height);
+						{
+							pTiles = new CLayerTiles(pTilemapItem->m_Width, pTilemapItem->m_Height);
+							pTiles->m_pEditor = m_pEditor;
+						}
 
-						layer = tiles;
+						pLayer = pTiles;
 						
-						group->add_layer(tiles);
-						void *data = datafile_get_data(df, tilemap_item->data);
-						tiles->image = tilemap_item->image;
-						tiles->game = tilemap_item->flags&1;
+						pGroup->AddLayer(pTiles);
+						void *pData = DataFile.GetData(pTilemapItem->m_Data);
+						pTiles->m_Image = pTilemapItem->m_Image;
+						pTiles->m_Game = pTilemapItem->m_Flags&1;
 						
-						mem_copy(tiles->tiles, data, tiles->width*tiles->height*sizeof(TILE));
+						mem_copy(pTiles->m_pTiles, pData, pTiles->m_Width*pTiles->m_Height*sizeof(CTile));
 						
-						if(tiles->game && tilemap_item->version == make_version(1, *tilemap_item))
+						if(pTiles->m_Game && pTilemapItem->m_Version == MakeVersion(1, *pTilemapItem))
 						{
-							for(int i = 0; i < tiles->width*tiles->height; i++)
+							for(int i = 0; i < pTiles->m_Width*pTiles->m_Height; i++)
 							{
-								if(tiles->tiles[i].index)
-									tiles->tiles[i].index += ENTITY_OFFSET;
+								if(pTiles->m_pTiles[i].m_Index)
+									pTiles->m_pTiles[i].m_Index += ENTITY_OFFSET;
 							}
 						}
 						
-						datafile_unload_data(df, tilemap_item->data);
+						DataFile.UnloadData(pTilemapItem->m_Data);
 					}
-					else if(layer_item->type == LAYERTYPE_QUADS)
+					else if(pLayerItem->m_Type == LAYERTYPE_QUADS)
 					{
-						MAPITEM_LAYER_QUADS *quads_item = (MAPITEM_LAYER_QUADS *)layer_item;
-						LAYER_QUADS *quads = new LAYER_QUADS;
-						layer = quads;
-						quads->image = quads_item->image;
-						if(quads->image < -1 || quads->image >= images.len())
-							quads->image = -1;
-						void *data = datafile_get_data_swapped(df, quads_item->data);
-						group->add_layer(quads);
-						quads->quads.setsize(quads_item->num_quads);
-						mem_copy(quads->quads.getptr(), data, sizeof(QUAD)*quads_item->num_quads);
-						datafile_unload_data(df, quads_item->data);
+						CMapItemLayerQuads *pQuadsItem = (CMapItemLayerQuads *)pLayerItem;
+						CLayerQuads *pQuads = new CLayerQuads;
+						pQuads->m_pEditor = m_pEditor;
+						pLayer = pQuads;
+						pQuads->m_Image = pQuadsItem->m_Image;
+						if(pQuads->m_Image < -1 || pQuads->m_Image >= m_lImages.size())
+							pQuads->m_Image = -1;
+						void *pData = DataFile.GetDataSwapped(pQuadsItem->m_Data);
+						pGroup->AddLayer(pQuads);
+						pQuads->m_lQuads.set_size(pQuadsItem->m_NumQuads);
+						mem_copy(pQuads->m_lQuads.base_ptr(), pData, sizeof(CQuad)*pQuadsItem->m_NumQuads);
+						DataFile.UnloadData(pQuadsItem->m_Data);
 					}
 					
-					if(layer)
-						layer->flags = layer_item->flags;
+					if(pLayer)
+						pLayer->m_Flags = pLayerItem->m_Flags;
 				}
 			}
 		}
 		
 		// load envelopes
 		{
-			ENVPOINT *points = 0;
+			CEnvPoint *pPoints = 0;
 			
 			{
-				int start, num;
-				datafile_get_type(df, MAPITEMTYPE_ENVPOINTS, &start, &num);
-				if(num)
-					points = (ENVPOINT *)datafile_get_item(df, start, 0, 0);
+				int Start, Num;
+				DataFile.GetType(MAPITEMTYPE_ENVPOINTS, &Start, &Num);
+				if(Num)
+					pPoints = (CEnvPoint *)DataFile.GetItem(Start, 0, 0);
 			}
 			
-			int start, num;
-			datafile_get_type(df, MAPITEMTYPE_ENVELOPE, &start, &num);
-			for(int e = 0; e < num; e++)
+			int Start, Num;
+			DataFile.GetType(MAPITEMTYPE_ENVELOPE, &Start, &Num);
+			for(int e = 0; e < Num; e++)
 			{
-				MAPITEM_ENVELOPE *item = (MAPITEM_ENVELOPE *)datafile_get_item(df, start+e, 0, 0);
-				ENVELOPE *env = new ENVELOPE(item->channels);
-				env->points.setsize(item->num_points);
-				mem_copy(env->points.getptr(), &points[item->start_point], sizeof(ENVPOINT)*item->num_points);
-				envelopes.add(env);
+				CMapItemEnvelope *pItem = (CMapItemEnvelope *)DataFile.GetItem(Start+e, 0, 0);
+				CEnvelope *pEnv = new CEnvelope(pItem->m_Channels);
+				pEnv->m_lPoints.set_size(pItem->m_NumPoints);
+				mem_copy(pEnv->m_lPoints.base_ptr(), &pPoints[pItem->m_StartPoint], sizeof(CEnvPoint)*pItem->m_NumPoints);
+				m_lEnvelopes.add(pEnv);
 			}
 		}
 	}
 	
-	datafile_unload(df);
-	
-	return 0;
+	return 1;
 }
 
-static int modify_add_amount = 0;
-static void modify_add(int *index)
+static int gs_ModifyAddAmount = 0;
+static void ModifyAdd(int *pIndex)
 {
-	if(*index >= 0)
-		*index += modify_add_amount;
+	if(*pIndex >= 0)
+		*pIndex += gs_ModifyAddAmount;
 }
 
-int EDITOR::append(const char *filename)
+int CEditor::Append(const char *pFileName)
 {
-	MAP new_map;
-	int err;
-	err = new_map.load(filename);
-	if(err)
-		return err;
+	CEditorMap NewMap;
+	NewMap.m_pEditor = this;
+
+	int Err;
+	Err = NewMap.Load(Kernel()->RequestInterface<IStorage>(), pFileName);
+	if(Err)
+		return Err;
 
 	// modify indecies	
-	modify_add_amount = map.images.len();
-	new_map.modify_image_index(modify_add);
+	gs_ModifyAddAmount = m_Map.m_lImages.size();
+	NewMap.ModifyImageIndex(ModifyAdd);
 	
-	modify_add_amount = map.envelopes.len();
-	new_map.modify_envelope_index(modify_add);
+	gs_ModifyAddAmount = m_Map.m_lEnvelopes.size();
+	NewMap.ModifyEnvelopeIndex(ModifyAdd);
 	
 	// transfer images
-	for(int i = 0; i < new_map.images.len(); i++)
-		map.images.add(new_map.images[i]);
-	new_map.images.clear();
+	for(int i = 0; i < NewMap.m_lImages.size(); i++)
+		m_Map.m_lImages.add(NewMap.m_lImages[i]);
+	NewMap.m_lImages.clear();
 	
 	// transfer envelopes
-	for(int i = 0; i < new_map.envelopes.len(); i++)
-		map.envelopes.add(new_map.envelopes[i]);
-	new_map.envelopes.clear();
+	for(int i = 0; i < NewMap.m_lEnvelopes.size(); i++)
+		m_Map.m_lEnvelopes.add(NewMap.m_lEnvelopes[i]);
+	NewMap.m_lEnvelopes.clear();
 
 	// transfer groups
 	
-	for(int i = 0; i < new_map.groups.len(); i++)
+	for(int i = 0; i < NewMap.m_lGroups.size(); i++)
 	{
-		if(new_map.groups[i] == new_map.game_group)
-			delete new_map.groups[i];
+		if(NewMap.m_lGroups[i] == NewMap.m_pGameGroup)
+			delete NewMap.m_lGroups[i];
 		else
-			map.groups.add(new_map.groups[i]);
+		{
+			NewMap.m_lGroups[i]->m_pMap = &m_Map;
+			m_Map.m_lGroups.add(NewMap.m_lGroups[i]);
+		}
 	}
-	new_map.groups.clear();
+	NewMap.m_lGroups.clear();
 	
 	// all done \o/
 	return 0;
diff --git a/src/game/editor/ed_layer_game.cpp b/src/game/editor/ed_layer_game.cpp
index 9010bc71..82a9cb1d 100644
--- a/src/game/editor/ed_layer_game.cpp
+++ b/src/game/editor/ed_layer_game.cpp
@@ -1,20 +1,20 @@
-#include "ed_editor.hpp"
+#include "ed_editor.h"
 
 
-LAYER_GAME::LAYER_GAME(int w, int h)
-: LAYER_TILES(w, h)
+CLayerGame::CLayerGame(int w, int h)
+: CLayerTiles(w, h)
 {
-	type_name = "Game";
-	game = 1;
+	m_pTypeName = "Game";
+	m_Game = 1;
 }
 
-LAYER_GAME::~LAYER_GAME()
+CLayerGame::~CLayerGame()
 {
 }
 
-int LAYER_GAME::render_properties(CUIRect *toolbox)
+int CLayerGame::RenderProperties(CUIRect *pToolbox)
 {
-	int r = LAYER_TILES::render_properties(toolbox);
-	image = -1;
+	int r = CLayerTiles::RenderProperties(pToolbox);
+	m_Image = -1;
 	return r;
 }
diff --git a/src/game/editor/ed_layer_quads.cpp b/src/game/editor/ed_layer_quads.cpp
index ce1ba4b6..3aeffc73 100644
--- a/src/game/editor/ed_layer_quads.cpp
+++ b/src/game/editor/ed_layer_quads.cpp
@@ -1,213 +1,216 @@
-#include <base/math.hpp>
+#include <base/math.h>
 
-#include <engine/client/graphics.h>
+#include <engine/graphics.h>
 
-#include "ed_editor.hpp"
-#include <game/generated/gc_data.hpp>
-#include <game/client/render.hpp>
+#include "ed_editor.h"
+#include <game/generated/client_data.h>
+#include <game/client/render.h>
 
-LAYER_QUADS::LAYER_QUADS()
+CLayerQuads::CLayerQuads()
 {
-	type = LAYERTYPE_QUADS;
-	type_name = "Quads";
-	image = -1;
+	m_Type = LAYERTYPE_QUADS;
+	m_pTypeName = "Quads";
+	m_Image = -1;
 }
 
-LAYER_QUADS::~LAYER_QUADS()
+CLayerQuads::~CLayerQuads()
 {
 }
 
-static void envelope_eval(float time_offset, int env, float *channels, void *user)
+static void EnvelopeEval(float TimeOffset, int Env, float *pChannels, void *pUser)
 {
-	EDITOR *pEditor = (EDITOR *)user;
-	if(env < 0 || env > pEditor->map.envelopes.len())
+	CEditor *pEditor = (CEditor *)pUser;
+	if(Env < 0 || Env > pEditor->m_Map.m_lEnvelopes.size())
 	{
-		channels[0] = 0;
-		channels[1] = 0;
-		channels[2] = 0;
-		channels[3] = 0;
+		pChannels[0] = 0;
+		pChannels[1] = 0;
+		pChannels[2] = 0;
+		pChannels[3] = 0;
 		return;
 	}
 		
-	ENVELOPE *e = pEditor->map.envelopes[env];
-	float t = pEditor->animate_time+time_offset;
-	t *= pEditor->animate_speed;
-	e->eval(t, channels);
+	CEnvelope *e = pEditor->m_Map.m_lEnvelopes[Env];
+	float t = pEditor->m_AnimateTime+TimeOffset;
+	t *= pEditor->m_AnimateSpeed;
+	e->Eval(t, pChannels);
 }
 
-void LAYER_QUADS::render()
+void CLayerQuads::Render()
 {
 	Graphics()->TextureSet(-1);
-	if(image >= 0 && image < editor->map.images.len())
-		Graphics()->TextureSet(editor->map.images[image]->tex_id);
+	if(m_Image >= 0 && m_Image < m_pEditor->m_Map.m_lImages.size())
+		Graphics()->TextureSet(m_pEditor->m_Map.m_lImages[m_Image]->m_TexId);
 		
-	editor->RenderTools()->render_quads(quads.getptr(), quads.len(), LAYERRENDERFLAG_OPAQUE|LAYERRENDERFLAG_TRANSPARENT, envelope_eval, editor);
+	m_pEditor->RenderTools()->RenderQuads(m_lQuads.base_ptr(), m_lQuads.size(), LAYERRENDERFLAG_OPAQUE|LAYERRENDERFLAG_TRANSPARENT, EnvelopeEval, m_pEditor);
 }
 
-QUAD *LAYER_QUADS::new_quad()
+CQuad *CLayerQuads::NewQuad()
 {
-	QUAD *q = &quads[quads.add(QUAD())];
+	CQuad *q = &m_lQuads[m_lQuads.add(CQuad())];
 
-	q->pos_env = -1;
-	q->color_env = -1;
-	q->pos_env_offset = 0;
-	q->color_env_offset = 0;
+	q->m_PosEnv = -1;
+	q->m_ColorEnv = -1;
+	q->m_PosEnvOffset = 0;
+	q->m_ColorEnvOffset = 0;
 	int x = 0, y = 0;
-	q->points[0].x = x;
-	q->points[0].y = y;
-	q->points[1].x = x+64;
-	q->points[1].y = y;
-	q->points[2].x = x;
-	q->points[2].y = y+64;
-	q->points[3].x = x+64;
-	q->points[3].y = y+64;
-
-	q->points[4].x = x+32; // pivot
-	q->points[4].y = y+32;
+	q->m_aPoints[0].x = x;
+	q->m_aPoints[0].y = y;
+	q->m_aPoints[1].x = x+64;
+	q->m_aPoints[1].y = y;
+	q->m_aPoints[2].x = x;
+	q->m_aPoints[2].y = y+64;
+	q->m_aPoints[3].x = x+64;
+	q->m_aPoints[3].y = y+64;
+
+	q->m_aPoints[4].x = x+32; // pivot
+	q->m_aPoints[4].y = y+32;
 	
 	for(int i = 0; i < 5; i++)
 	{
-		q->points[i].x <<= 10;
-		q->points[i].y <<= 10;
+		q->m_aPoints[i].x <<= 10;
+		q->m_aPoints[i].y <<= 10;
 	}
 	
 
-	q->texcoords[0].x = 0;
-	q->texcoords[0].y = 0;
+	q->m_aTexcoords[0].x = 0;
+	q->m_aTexcoords[0].y = 0;
 	
-	q->texcoords[1].x = 1<<10;
-	q->texcoords[1].y = 0;
+	q->m_aTexcoords[1].x = 1<<10;
+	q->m_aTexcoords[1].y = 0;
 	
-	q->texcoords[2].x = 0;
-	q->texcoords[2].y = 1<<10;
+	q->m_aTexcoords[2].x = 0;
+	q->m_aTexcoords[2].y = 1<<10;
 	
-	q->texcoords[3].x = 1<<10;
-	q->texcoords[3].y = 1<<10;
+	q->m_aTexcoords[3].x = 1<<10;
+	q->m_aTexcoords[3].y = 1<<10;
 	
-	q->colors[0].r = 255; q->colors[0].g = 255; q->colors[0].b = 255; q->colors[0].a = 255;
-	q->colors[1].r = 255; q->colors[1].g = 255; q->colors[1].b = 255; q->colors[1].a = 255;
-	q->colors[2].r = 255; q->colors[2].g = 255; q->colors[2].b = 255; q->colors[2].a = 255;
-	q->colors[3].r = 255; q->colors[3].g = 255; q->colors[3].b = 255; q->colors[3].a = 255;
+	q->m_aColors[0].r = 255; q->m_aColors[0].g = 255; q->m_aColors[0].b = 255; q->m_aColors[0].a = 255;
+	q->m_aColors[1].r = 255; q->m_aColors[1].g = 255; q->m_aColors[1].b = 255; q->m_aColors[1].a = 255;
+	q->m_aColors[2].r = 255; q->m_aColors[2].g = 255; q->m_aColors[2].b = 255; q->m_aColors[2].a = 255;
+	q->m_aColors[3].r = 255; q->m_aColors[3].g = 255; q->m_aColors[3].b = 255; q->m_aColors[3].a = 255;
 
 	return q;
 }
 
-void LAYER_QUADS::brush_selecting(CUIRect rect)
+void CLayerQuads::BrushSelecting(CUIRect Rect)
 {
 	// draw selection rectangle
+	IGraphics::CLineItem Array[4] = {
+		IGraphics::CLineItem(Rect.x, Rect.y, Rect.x+Rect.w, Rect.y),
+		IGraphics::CLineItem(Rect.x+Rect.w, Rect.y, Rect.x+Rect.w, Rect.y+Rect.h),
+		IGraphics::CLineItem(Rect.x+Rect.w, Rect.y+Rect.h, Rect.x, Rect.y+Rect.h),
+		IGraphics::CLineItem(Rect.x, Rect.y+Rect.h, Rect.x, Rect.y)};
 	Graphics()->TextureSet(-1);
 	Graphics()->LinesBegin();
-	Graphics()->LinesDraw(rect.x, rect.y, rect.x+rect.w, rect.y);
-	Graphics()->LinesDraw(rect.x+rect.w, rect.y, rect.x+rect.w, rect.y+rect.h);
-	Graphics()->LinesDraw(rect.x+rect.w, rect.y+rect.h, rect.x, rect.y+rect.h);
-	Graphics()->LinesDraw(rect.x, rect.y+rect.h, rect.x, rect.y);
+	Graphics()->LinesDraw(Array, 4);
 	Graphics()->LinesEnd();
 }
 
-int LAYER_QUADS::brush_grab(LAYERGROUP *brush, CUIRect rect)
+int CLayerQuads::BrushGrab(CLayerGroup *pBrush, CUIRect Rect)
 {
 	// create new layers
-	LAYER_QUADS *grabbed = new LAYER_QUADS();
-	grabbed->image = image;
-	brush->add_layer(grabbed);
+	CLayerQuads *pGrabbed = new CLayerQuads();
+	pGrabbed->m_pEditor = m_pEditor;
+	pGrabbed->m_Image = m_Image;
+	pBrush->AddLayer(pGrabbed);
 	
 	//dbg_msg("", "%f %f %f %f", rect.x, rect.y, rect.w, rect.h);
-	for(int i = 0; i < quads.len(); i++)
+	for(int i = 0; i < m_lQuads.size(); i++)
 	{
-		QUAD *q = &quads[i];
-		float px = fx2f(q->points[4].x);
-		float py = fx2f(q->points[4].y);
+		CQuad *q = &m_lQuads[i];
+		float px = fx2f(q->m_aPoints[4].x);
+		float py = fx2f(q->m_aPoints[4].y);
 		
-		if(px > rect.x && px < rect.x+rect.w && py > rect.y && py < rect.y+rect.h)
+		if(px > Rect.x && px < Rect.x+Rect.w && py > Rect.y && py < Rect.y+Rect.h)
 		{
 			dbg_msg("", "grabbed one");
-			QUAD n;
+			CQuad n;
 			n = *q;
 			
 			for(int p = 0; p < 5; p++)
 			{
-				n.points[p].x -= f2fx(rect.x);
-				n.points[p].y -= f2fx(rect.y);
+				n.m_aPoints[p].x -= f2fx(Rect.x);
+				n.m_aPoints[p].y -= f2fx(Rect.y);
 			}
 			
-			grabbed->quads.add(n);
+			pGrabbed->m_lQuads.add(n);
 		}
 	}
 	
-	return grabbed->quads.len()?1:0;
+	return pGrabbed->m_lQuads.size()?1:0;
 }
 
-void LAYER_QUADS::brush_place(LAYER *brush, float wx, float wy)
+void CLayerQuads::BrushPlace(CLayer *pBrush, float wx, float wy)
 {
-	LAYER_QUADS *l = (LAYER_QUADS *)brush;
-	for(int i = 0; i < l->quads.len(); i++)
+	CLayerQuads *l = (CLayerQuads *)pBrush;
+	for(int i = 0; i < l->m_lQuads.size(); i++)
 	{
-		QUAD n = l->quads[i];
+		CQuad n = l->m_lQuads[i];
 		
 		for(int p = 0; p < 5; p++)
 		{
-			n.points[p].x += f2fx(wx);
-			n.points[p].y += f2fx(wy);
+			n.m_aPoints[p].x += f2fx(wx);
+			n.m_aPoints[p].y += f2fx(wy);
 		}
 			
-		quads.add(n);
+		m_lQuads.add(n);
 	}
 }
 
-void LAYER_QUADS::brush_flip_x()
+void CLayerQuads::BrushFlipX()
 {
 }
 
-void LAYER_QUADS::brush_flip_y()
+void CLayerQuads::BrushFlipY()
 {
 }
 
-void rotate(vec2 *center, vec2 *point, float rotation)
+void Rotate(vec2 *pCenter, vec2 *pPoint, float Rotation)
 {
-	float x = point->x - center->x;
-	float y = point->y - center->y;
-	point->x = x * cosf(rotation) - y * sinf(rotation) + center->x;
-	point->y = x * sinf(rotation) + y * cosf(rotation) + center->y;
+	float x = pPoint->x - pCenter->x;
+	float y = pPoint->y - pCenter->y;
+	pPoint->x = x * cosf(Rotation) - y * sinf(Rotation) + pCenter->x;
+	pPoint->y = x * sinf(Rotation) + y * cosf(Rotation) + pCenter->y;
 }
 
-void LAYER_QUADS::brush_rotate(float amount)
+void CLayerQuads::BrushRotate(float Amount)
 {
-	vec2 center;
-	get_size(&center.x, &center.y);
-	center.x /= 2;
-	center.y /= 2;
+	vec2 Center;
+	GetSize(&Center.x, &Center.y);
+	Center.x /= 2;
+	Center.y /= 2;
 
-	for(int i = 0; i < quads.len(); i++)
+	for(int i = 0; i < m_lQuads.size(); i++)
 	{
-		QUAD *q = &quads[i];
+		CQuad *q = &m_lQuads[i];
 		
 		for(int p = 0; p < 5; p++)
 		{
-			vec2 pos(fx2f(q->points[p].x), fx2f(q->points[p].y));
-			rotate(&center, &pos, amount);
-			q->points[p].x = f2fx(pos.x);
-			q->points[p].y = f2fx(pos.y);
+			vec2 Pos(fx2f(q->m_aPoints[p].x), fx2f(q->m_aPoints[p].y));
+			Rotate(&Center, &Pos, Amount);
+			q->m_aPoints[p].x = f2fx(Pos.x);
+			q->m_aPoints[p].y = f2fx(Pos.y);
 		}
 	}
 }
 
-void LAYER_QUADS::get_size(float *w, float *h)
+void CLayerQuads::GetSize(float *w, float *h)
 {
 	*w = 0; *h = 0;
 	
-	for(int i = 0; i < quads.len(); i++)
+	for(int i = 0; i < m_lQuads.size(); i++)
 	{
 		for(int p = 0; p < 5; p++)
 		{
-			*w = max(*w, fx2f(quads[i].points[p].x));
-			*h = max(*h, fx2f(quads[i].points[p].y));
+			*w = max(*w, fx2f(m_lQuads[i].m_aPoints[p].x));
+			*h = max(*h, fx2f(m_lQuads[i].m_aPoints[p].y));
 		}
 	}
 }
 
-extern int selected_points;
+extern int gs_SelectedPoints;
 
-int LAYER_QUADS::render_properties(CUIRect *toolbox)
+int CLayerQuads::RenderProperties(CUIRect *pToolBox)
 {
 	// layer props
 	enum
@@ -216,37 +219,37 @@ int LAYER_QUADS::render_properties(CUIRect *toolbox)
 		NUM_PROPS,
 	};
 	
-	PROPERTY props[] = {
-		{"Image", image, PROPTYPE_IMAGE, -1, 0},
+	CProperty aProps[] = {
+		{"Image", m_Image, PROPTYPE_IMAGE, -1, 0},
 		{0},
 	};
 	
-	static int ids[NUM_PROPS] = {0};
-	int new_val = 0;
-	int prop = editor->do_properties(toolbox, props, ids, &new_val);		
+	static int s_aIds[NUM_PROPS] = {0};
+	int NewVal = 0;
+	int Prop = m_pEditor->DoProperties(pToolBox, aProps, s_aIds, &NewVal);		
 	
-	if(prop == PROP_IMAGE)
+	if(Prop == PROP_IMAGE)
 	{
-		if(new_val >= 0)
-			image = new_val%editor->map.images.len();
+		if(NewVal >= 0)
+			m_Image = NewVal%m_pEditor->m_Map.m_lImages.size();
 		else
-			image = -1;
+			m_Image = -1;
 	}
 
 	return 0;
 }
 
 
-void LAYER_QUADS::modify_image_index(INDEX_MODIFY_FUNC func)
+void CLayerQuads::ModifyImageIndex(INDEX_MODIFY_FUNC Func)
 {
-	func(&image);
+	Func(&m_Image);
 }
 
-void LAYER_QUADS::modify_envelope_index(INDEX_MODIFY_FUNC func)
+void CLayerQuads::ModifyEnvelopeIndex(INDEX_MODIFY_FUNC Func)
 {
-	for(int i = 0; i < quads.len(); i++)
+	for(int i = 0; i < m_lQuads.size(); i++)
 	{
-		func(&quads[i].pos_env);
-		func(&quads[i].color_env);
+		Func(&m_lQuads[i].m_PosEnv);
+		Func(&m_lQuads[i].m_ColorEnv);
 	}
 }
diff --git a/src/game/editor/ed_layer_tiles.cpp b/src/game/editor/ed_layer_tiles.cpp
index 0d42cb78..ecd7c62c 100644
--- a/src/game/editor/ed_layer_tiles.cpp
+++ b/src/game/editor/ed_layer_tiles.cpp
@@ -1,247 +1,281 @@
-#include <base/math.hpp>
+#include <base/math.h>
 
-#include <engine/client/graphics.h>
+#include <engine/graphics.h>
+#include <engine/textrender.h>
 
-#include <game/generated/gc_data.hpp>
-#include <game/client/render.hpp>
-#include "ed_editor.hpp"
+#include <game/generated/client_data.h>
+#include <game/client/render.h>
+#include "ed_editor.h"
 
-LAYER_TILES::LAYER_TILES(int w, int h)
+CLayerTiles::CLayerTiles(int w, int h)
 {
-	type = LAYERTYPE_TILES;
-	type_name = "Tiles";
-	width = w;
-	height = h;
-	image = -1;
-	tex_id = -1;
-	game = 0;
+	m_Type = LAYERTYPE_TILES;
+	m_pTypeName = "Tiles";
+	m_Width = w;
+	m_Height = h;
+	m_Image = -1;
+	m_TexId = -1;
+	m_Game = 0;
 	
-	tiles = new TILE[width*height];
-	mem_zero(tiles, width*height*sizeof(TILE));
+	m_pTiles = new CTile[m_Width*m_Height];
+	mem_zero(m_pTiles, m_Width*m_Height*sizeof(CTile));
 }
 
-LAYER_TILES::~LAYER_TILES()
+CLayerTiles::~CLayerTiles()
 {
-	delete [] tiles;
+	delete [] m_pTiles;
 }
 
-void LAYER_TILES::prepare_for_save()
+void CLayerTiles::PrepareForSave()
 {
-	for(int y = 0; y < height; y++)
-		for(int x = 0; x < width; x++)
-			tiles[y*width+x].flags &= TILEFLAG_VFLIP|TILEFLAG_HFLIP;
+	for(int y = 0; y < m_Height; y++)
+		for(int x = 0; x < m_Width; x++)
+			m_pTiles[y*m_Width+x].m_Flags &= TILEFLAG_VFLIP|TILEFLAG_HFLIP;
 
-	if(image != -1)
+	if(m_Image != -1)
 	{
-		for(int y = 0; y < height; y++)
-			for(int x = 0; x < width; x++)
-				tiles[y*width+x].flags |= editor->map.images[image]->tileflags[tiles[y*width+x].index];
+		for(int y = 0; y < m_Height; y++)
+			for(int x = 0; x < m_Width; x++)
+				m_pTiles[y*m_Width+x].m_Flags |= m_pEditor->m_Map.m_lImages[m_Image]->m_aTileFlags[m_pTiles[y*m_Width+x].m_Index];
 	}
 }
 
-void LAYER_TILES::make_palette()
+void CLayerTiles::MakePalette()
 {
-	for(int y = 0; y < height; y++)
-		for(int x = 0; x < width; x++)
-			tiles[y*width+x].index = y*16+x;
+	for(int y = 0; y < m_Height; y++)
+		for(int x = 0; x < m_Width; x++)
+			m_pTiles[y*m_Width+x].m_Index = y*16+x;
 }
 
-void LAYER_TILES::render()
+void CLayerTiles::Render()
 {
-	if(image >= 0 && image < editor->map.images.len())
-		tex_id = editor->map.images[image]->tex_id;
-	Graphics()->TextureSet(tex_id);
-	editor->RenderTools()->render_tilemap(tiles, width, height, 32.0f, vec4(1,1,1,1), LAYERRENDERFLAG_OPAQUE|LAYERRENDERFLAG_TRANSPARENT);
+	if(m_Image >= 0 && m_Image < m_pEditor->m_Map.m_lImages.size())
+		m_TexId = m_pEditor->m_Map.m_lImages[m_Image]->m_TexId;
+	Graphics()->TextureSet(m_TexId);
+	m_pEditor->RenderTools()->RenderTilemap(m_pTiles, m_Width, m_Height, 32.0f, vec4(1,1,1,1), LAYERRENDERFLAG_OPAQUE|LAYERRENDERFLAG_TRANSPARENT);
 }
 
-int LAYER_TILES::convert_x(float x) const { return (int)(x/32.0f); }
-int LAYER_TILES::convert_y(float y) const { return (int)(y/32.0f); }
+int CLayerTiles::ConvertX(float x) const { return (int)(x/32.0f); }
+int CLayerTiles::ConvertY(float y) const { return (int)(y/32.0f); }
 
-void LAYER_TILES::convert(CUIRect rect, RECTi *out)
+void CLayerTiles::Convert(CUIRect Rect, RECTi *pOut)
 {
-	out->x = convert_x(rect.x);
-	out->y = convert_y(rect.y);
-	out->w = convert_x(rect.x+rect.w+31) - out->x;
-	out->h = convert_y(rect.y+rect.h+31) - out->y;
+	pOut->x = ConvertX(Rect.x);
+	pOut->y = ConvertY(Rect.y);
+	pOut->w = ConvertX(Rect.x+Rect.w+31) - pOut->x;
+	pOut->h = ConvertY(Rect.y+Rect.h+31) - pOut->y;
 }
 
-void LAYER_TILES::snap(CUIRect *rect)
+void CLayerTiles::Snap(CUIRect *pRect)
 {
-	RECTi out;
-	convert(*rect, &out);
-	rect->x = out.x*32.0f;
-	rect->y = out.y*32.0f;
-	rect->w = out.w*32.0f;
-	rect->h = out.h*32.0f;
+	RECTi Out;
+	Convert(*pRect, &Out);
+	pRect->x = Out.x*32.0f;
+	pRect->y = Out.y*32.0f;
+	pRect->w = Out.w*32.0f;
+	pRect->h = Out.h*32.0f;
 }
 
-void LAYER_TILES::clamp(RECTi *rect)
+void CLayerTiles::Clamp(RECTi *pRect)
 {
-	if(rect->x < 0)
+	if(pRect->x < 0)
 	{
-		rect->w += rect->x;
-		rect->x = 0;
+		pRect->w += pRect->x;
+		pRect->x = 0;
 	}
 		
-	if(rect->y < 0)
+	if(pRect->y < 0)
 	{
-		rect->h += rect->y;
-		rect->y = 0;
+		pRect->h += pRect->y;
+		pRect->y = 0;
 	}
 	
-	if(rect->x+rect->w > width)
-		rect->w = width-rect->x;
+	if(pRect->x+pRect->w > m_Width)
+		pRect->w = m_Width - pRect->x;
 
-	if(rect->y+rect->h > height)
-		rect->h = height-rect->y;
+	if(pRect->y+pRect->h > m_Height)
+		pRect->h = m_Height - pRect->y;
 		
-	if(rect->h < 0)
-		rect->h = 0;
-	if(rect->w < 0)
-		rect->w = 0;
+	if(pRect->h < 0)
+		pRect->h = 0;
+	if(pRect->w < 0)
+		pRect->w = 0;
 }
 
-void LAYER_TILES::brush_selecting(CUIRect rect)
+void CLayerTiles::BrushSelecting(CUIRect Rect)
 {
 	Graphics()->TextureSet(-1);
-	editor->Graphics()->QuadsBegin();
-	editor->Graphics()->SetColor(1,1,1,0.4f);
-	snap(&rect);
-	editor->Graphics()->QuadsDrawTL(rect.x, rect.y, rect.w, rect.h);
-	editor->Graphics()->QuadsEnd();
-	char buf[16];
-	str_format(buf, sizeof(buf), "%d,%d", convert_x(rect.w), convert_y(rect.h));
-	gfx_text(0, rect.x+3.0f, rect.y+3.0f, 15.0f*editor->world_zoom, buf, -1);
+	m_pEditor->Graphics()->QuadsBegin();
+	m_pEditor->Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.4f);
+	Snap(&Rect);
+	IGraphics::CQuadItem QuadItem(Rect.x, Rect.y, Rect.w, Rect.h);
+	m_pEditor->Graphics()->QuadsDrawTL(&QuadItem, 1);
+	m_pEditor->Graphics()->QuadsEnd();
+	char aBuf[16];
+	str_format(aBuf, sizeof(aBuf), "%d,%d", ConvertX(Rect.w), ConvertY(Rect.h));
+	TextRender()->Text(0, Rect.x+3.0f, Rect.y+3.0f, 15.0f*m_pEditor->m_WorldZoom, aBuf, -1);
 }
 
-int LAYER_TILES::brush_grab(LAYERGROUP *brush, CUIRect rect)
+int CLayerTiles::BrushGrab(CLayerGroup *pBrush, CUIRect Rect)
 {
 	RECTi r;
-	convert(rect, &r);
-	clamp(&r);
+	Convert(Rect, &r);
+	Clamp(&r);
 	
 	if(!r.w || !r.h)
 		return 0;
 	
 	// create new layers
-	LAYER_TILES *grabbed = new LAYER_TILES(r.w, r.h);
-	grabbed->tex_id = tex_id;
-	grabbed->image = image;
-	brush->add_layer(grabbed);
+	CLayerTiles *pGrabbed = new CLayerTiles(r.w, r.h);
+	pGrabbed->m_pEditor = m_pEditor;
+	pGrabbed->m_TexId = m_TexId;
+	pGrabbed->m_Image = m_Image;
+	pBrush->AddLayer(pGrabbed);
 	
 	// copy the tiles
 	for(int y = 0; y < r.h; y++)
 		for(int x = 0; x < r.w; x++)
-			grabbed->tiles[y*grabbed->width+x] = tiles[(r.y+y)*width+(r.x+x)];
+			pGrabbed->m_pTiles[y*pGrabbed->m_Width+x] = m_pTiles[(r.y+y)*m_Width+(r.x+x)];
 	
 	return 1;
 }
 
-void LAYER_TILES::brush_draw(LAYER *brush, float wx, float wy)
+void CLayerTiles::FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect)
 {
-	if(readonly)
+	if(m_Readonly)
+		return;
+		
+	int sx = ConvertX(Rect.x);
+	int sy = ConvertY(Rect.y);
+	int w = ConvertX(Rect.w);
+	int h = ConvertY(Rect.h);
+	
+	CLayerTiles *pLt = static_cast<CLayerTiles*>(pBrush);
+	
+	for(int y = 0; y <= h; y++)
+	{
+		for(int x = 0; x <= w; x++)
+		{
+			int fx = x+sx;
+			int fy = y+sy;
+			
+			if(fx < 0 || fx >= m_Width || fy < 0 || fy >= m_Height)
+				continue;
+			
+			if(Empty)	
+                m_pTiles[fy*m_Width+fx].m_Index = 1;
+            else
+                m_pTiles[fy*m_Width+fx] = pLt->m_pTiles[(y*pLt->m_Width + x%pLt->m_Width) % (pLt->m_Width*pLt->m_Height)];
+		}
+	}
+}
+
+void CLayerTiles::BrushDraw(CLayer *pBrush, float wx, float wy)
+{
+	if(m_Readonly)
 		return;
 	
 	//
-	LAYER_TILES *l = (LAYER_TILES *)brush;
-	int sx = convert_x(wx);
-	int sy = convert_y(wy);
+	CLayerTiles *l = (CLayerTiles *)pBrush;
+	int sx = ConvertX(wx);
+	int sy = ConvertY(wy);
 	
-	for(int y = 0; y < l->height; y++)
-		for(int x = 0; x < l->width; x++)
+	for(int y = 0; y < l->m_Height; y++)
+		for(int x = 0; x < l->m_Width; x++)
 		{
 			int fx = x+sx;
 			int fy = y+sy;
-			if(fx<0 || fx >= width || fy < 0 || fy >= height)
+			if(fx<0 || fx >= m_Width || fy < 0 || fy >= m_Height)
 				continue;
 				
-			tiles[fy*width+fx] = l->tiles[y*l->width+x];
+			m_pTiles[fy*m_Width+fx] = l->m_pTiles[y*l->m_Width+x];
 		}
 }
 
-void LAYER_TILES::brush_flip_x()
+void CLayerTiles::BrushFlipX()
 {
-	for(int y = 0; y < height; y++)
-		for(int x = 0; x < width/2; x++)
+	for(int y = 0; y < m_Height; y++)
+		for(int x = 0; x < m_Width/2; x++)
 		{
-			TILE tmp = tiles[y*width+x];
-			tiles[y*width+x] = tiles[y*width+width-1-x];
-			tiles[y*width+width-1-x] = tmp;
+			CTile Tmp = m_pTiles[y*m_Width+x];
+			m_pTiles[y*m_Width+x] = m_pTiles[y*m_Width+m_Width-1-x];
+			m_pTiles[y*m_Width+m_Width-1-x] = Tmp;
 		}
 
-	for(int y = 0; y < height; y++)
-		for(int x = 0; x < width; x++)
-			tiles[y*width+x].flags ^= TILEFLAG_VFLIP;
+	for(int y = 0; y < m_Height; y++)
+		for(int x = 0; x < m_Width; x++)
+			m_pTiles[y*m_Width+x].m_Flags ^= TILEFLAG_VFLIP;
 }
 
-void LAYER_TILES::brush_flip_y()
+void CLayerTiles::BrushFlipY()
 {
-	for(int y = 0; y < height/2; y++)
-		for(int x = 0; x < width; x++)
+	for(int y = 0; y < m_Height/2; y++)
+		for(int x = 0; x < m_Width; x++)
 		{
-			TILE tmp = tiles[y*width+x];
-			tiles[y*width+x] = tiles[(height-1-y)*width+x];
-			tiles[(height-1-y)*width+x] = tmp;
+			CTile Tmp = m_pTiles[y*m_Width+x];
+			m_pTiles[y*m_Width+x] = m_pTiles[(m_Height-1-y)*m_Width+x];
+			m_pTiles[(m_Height-1-y)*m_Width+x] = Tmp;
 		}
 
-	for(int y = 0; y < height; y++)
-		for(int x = 0; x < width; x++)
-			tiles[y*width+x].flags ^= TILEFLAG_HFLIP;
+	for(int y = 0; y < m_Height; y++)
+		for(int x = 0; x < m_Width; x++)
+			m_pTiles[y*m_Width+x].m_Flags ^= TILEFLAG_HFLIP;
 }
 
-void LAYER_TILES::resize(int new_w, int new_h)
+void CLayerTiles::Resize(int NewW, int NewH)
 {
-	TILE *new_data = new TILE[new_w*new_h];
-	mem_zero(new_data, new_w*new_h*sizeof(TILE));
+	CTile *pNewData = new CTile[NewW*NewH];
+	mem_zero(pNewData, NewW*NewH*sizeof(CTile));
 
 	// copy old data	
-	for(int y = 0; y < min(new_h, height); y++)
-		mem_copy(&new_data[y*new_w], &tiles[y*width], min(width, new_w)*sizeof(TILE));
+	for(int y = 0; y < min(NewH, m_Height); y++)
+		mem_copy(&pNewData[y*NewW], &m_pTiles[y*m_Width], min(m_Width, NewW)*sizeof(CTile));
 	
 	// replace old
-	delete [] tiles;
-	tiles = new_data;
-	width = new_w;
-	height = new_h;
+	delete [] m_pTiles;
+	m_pTiles = pNewData;
+	m_Width = NewW;
+	m_Height = NewH;
 }
 
 
-int LAYER_TILES::render_properties(CUIRect *toolbox)
+int CLayerTiles::RenderProperties(CUIRect *pToolBox)
 {
-	CUIRect button;
-	toolbox->HSplitBottom(12.0f, toolbox, &button);
-	bool in_gamegroup = editor->map.game_group->layers.find(this) != -1;
-	if(editor->map.game_layer == this)
-		in_gamegroup = false;
-	static int colcl_button = 0;
-	if(editor->DoButton_Editor(&colcl_button, "Clear Collision", in_gamegroup?0:-1, &button, 0, "Removes collision from this layer"))
+	CUIRect Button;
+	pToolBox->HSplitBottom(12.0f, pToolBox, &Button);
+	
+	bool InGameGroup = !find_linear(m_pEditor->m_Map.m_pGameGroup->m_lLayers.all(), this).empty();
+	if(m_pEditor->m_Map.m_pGameLayer == this)
+		InGameGroup = false;
+	static int s_ColclButton = 0;
+	if(m_pEditor->DoButton_Editor(&s_ColclButton, "Clear Collision", InGameGroup?0:-1, &Button, 0, "Removes collision from this layer"))
 	{
-		LAYER_TILES *gl = editor->map.game_layer;
-		int w = min(gl->width, width);
-		int h = min(gl->height, height);
+		CLayerTiles *gl = m_pEditor->m_Map.m_pGameLayer;
+		int w = min(gl->m_Width, m_Width);
+		int h = min(gl->m_Height, m_Height);
 		for(int y = 0; y < h; y++)
 			for(int x = 0; x < w; x++)
 			{
-				if(gl->tiles[y*gl->width+x].index <= TILE_SOLID)
-					if(tiles[y*width+x].index)
-						gl->tiles[y*gl->width+x].index = TILE_AIR;
+				if(gl->m_pTiles[y*gl->m_Width+x].m_Index <= TILE_SOLID)
+					if(m_pTiles[y*m_Width+x].m_Index)
+						gl->m_pTiles[y*gl->m_Width+x].m_Index = TILE_AIR;
 			}
 			
 		return 1;
 	}
-	static int col_button = 0;
-	toolbox->HSplitBottom(5.0f, toolbox, &button);
-	toolbox->HSplitBottom(12.0f, toolbox, &button);
-	if(editor->DoButton_Editor(&col_button, "Make Collision", in_gamegroup?0:-1, &button, 0, "Constructs collision from this layer"))
+	static int s_ColButton = 0;
+	pToolBox->HSplitBottom(5.0f, pToolBox, &Button);
+	pToolBox->HSplitBottom(12.0f, pToolBox, &Button);
+	if(m_pEditor->DoButton_Editor(&s_ColButton, "Make Collision", InGameGroup?0:-1, &Button, 0, "Constructs collision from this layer"))
 	{
-		LAYER_TILES *gl = editor->map.game_layer;
-		int w = min(gl->width, width);
-		int h = min(gl->height, height);
+		CLayerTiles *gl = m_pEditor->m_Map.m_pGameLayer;
+		int w = min(gl->m_Width, m_Width);
+		int h = min(gl->m_Height, m_Height);
 		for(int y = 0; y < h; y++)
 			for(int x = 0; x < w; x++)
 			{
-				if(gl->tiles[y*gl->width+x].index <= TILE_SOLID)
-					gl->tiles[y*gl->width+x].index = tiles[y*width+x].index?TILE_SOLID:TILE_AIR;
+				if(gl->m_pTiles[y*gl->m_Width+x].m_Index <= TILE_SOLID)
+					gl->m_pTiles[y*gl->m_Width+x].m_Index = m_pTiles[y*m_Width+x].m_Index?TILE_SOLID:TILE_AIR;
 			}
 			
 		return 1;
@@ -255,44 +289,44 @@ int LAYER_TILES::render_properties(CUIRect *toolbox)
 		NUM_PROPS,
 	};
 	
-	PROPERTY props[] = {
-		{"Width", width, PROPTYPE_INT_STEP, 1, 1000000000},
-		{"Height", height, PROPTYPE_INT_STEP, 1, 1000000000},
-		{"Image", image, PROPTYPE_IMAGE, 0, 0},
+	CProperty aProps[] = {
+		{"Width", m_Width, PROPTYPE_INT_STEP, 1, 1000000000},
+		{"Height", m_Height, PROPTYPE_INT_STEP, 1, 1000000000},
+		{"Image", m_Image, PROPTYPE_IMAGE, 0, 0},
 		{0},
 	};
 	
-	if(editor->map.game_layer == this) // remove the image from the selection if this is the game layer
-		props[2].name = 0;
+	if(m_pEditor->m_Map.m_pGameLayer == this) // remove the image from the selection if this is the game layer
+		aProps[2].m_pName = 0;
 	
-	static int ids[NUM_PROPS] = {0};
-	int new_val = 0;
-	int prop = editor->do_properties(toolbox, props, ids, &new_val);		
+	static int s_aIds[NUM_PROPS] = {0};
+	int NewVal = 0;
+	int Prop = m_pEditor->DoProperties(pToolBox, aProps, s_aIds, &NewVal);		
 	
-	if(prop == PROP_WIDTH && new_val > 1)
-		resize(new_val, height);
-	else if(prop == PROP_HEIGHT && new_val > 1)
-		resize(width, new_val);
-	else if(prop == PROP_IMAGE)
+	if(Prop == PROP_WIDTH && NewVal > 1)
+		Resize(NewVal, m_Height);
+	else if(Prop == PROP_HEIGHT && NewVal > 1)
+		Resize(m_Width, NewVal);
+	else if(Prop == PROP_IMAGE)
 	{
-		if (new_val == -1)
+		if (NewVal == -1)
 		{
-			tex_id = -1;
-			image = -1;
+			m_TexId = -1;
+			m_Image = -1;
 		}
 		else
-			image = new_val%editor->map.images.len();
+			m_Image = NewVal%m_pEditor->m_Map.m_lImages.size();
 	}
 	
 	return 0;
 }
 
 
-void LAYER_TILES::modify_image_index(INDEX_MODIFY_FUNC func)
+void CLayerTiles::ModifyImageIndex(INDEX_MODIFY_FUNC Func)
 {
-	func(&image);
+	Func(&m_Image);
 }
 
-void LAYER_TILES::modify_envelope_index(INDEX_MODIFY_FUNC func)
+void CLayerTiles::ModifyEnvelopeIndex(INDEX_MODIFY_FUNC Func)
 {
 }
diff --git a/src/game/editor/ed_popups.cpp b/src/game/editor/ed_popups.cpp
index 59140153..2e58ae3a 100644
--- a/src/game/editor/ed_popups.cpp
+++ b/src/game/editor/ed_popups.cpp
@@ -1,111 +1,114 @@
-#include <stdio.h>
-#include <engine/client/graphics.h>
-#include "ed_editor.hpp"
+#include <engine/graphics.h>
+#include <engine/input.h>
+#include <engine/keys.h>
+#include "ed_editor.h"
 
 
 // popup menu handling
 static struct
 {
-	CUIRect rect;
-	void *id;
-	int (*func)(EDITOR *pEditor, CUIRect rect);
-	int is_menu;
-	void *extra;
-} ui_popups[8];
+	CUIRect m_Rect;
+	void *m_pId;
+	int (*m_pfnFunc)(CEditor *pEditor, CUIRect Rect);
+	int m_IsMenu;
+	void *m_pExtra;
+} s_UiPopups[8];
 
-static int ui_num_popups = 0;
+static int g_UiNumPopups = 0;
 
-void EDITOR::ui_invoke_popup_menu(void *id, int flags, float x, float y, float w, float h, int (*func)(EDITOR *pEditor, CUIRect rect), void *extra)
+void CEditor::UiInvokePopupMenu(void *Id, int Flags, float x, float y, float w, float h, int (*pfnFunc)(CEditor *pEditor, CUIRect Rect), void *pExtra)
 {
 	dbg_msg("", "invoked");
-	ui_popups[ui_num_popups].id = id;
-	ui_popups[ui_num_popups].is_menu = flags;
-	ui_popups[ui_num_popups].rect.x = x;
-	ui_popups[ui_num_popups].rect.y = y;
-	ui_popups[ui_num_popups].rect.w = w;
-	ui_popups[ui_num_popups].rect.h = h;
-	ui_popups[ui_num_popups].func = func;
-	ui_popups[ui_num_popups].extra = extra;
-	ui_num_popups++;
+	s_UiPopups[g_UiNumPopups].m_pId = Id;
+	s_UiPopups[g_UiNumPopups].m_IsMenu = Flags;
+	s_UiPopups[g_UiNumPopups].m_Rect.x = x;
+	s_UiPopups[g_UiNumPopups].m_Rect.y = y;
+	s_UiPopups[g_UiNumPopups].m_Rect.w = w;
+	s_UiPopups[g_UiNumPopups].m_Rect.h = h;
+	s_UiPopups[g_UiNumPopups].m_pfnFunc = pfnFunc;
+	s_UiPopups[g_UiNumPopups].m_pExtra = pExtra;
+	g_UiNumPopups++;
 }
 
-void EDITOR::ui_do_popup_menu()
+void CEditor::UiDoPopupMenu()
 {
-	for(int i = 0; i < ui_num_popups; i++)
+	for(int i = 0; i < g_UiNumPopups; i++)
 	{
-		bool inside = UI()->MouseInside(&ui_popups[i].rect);
-		UI()->SetHotItem(&ui_popups[i].id);
+		bool Inside = UI()->MouseInside(&s_UiPopups[i].m_Rect);
+		UI()->SetHotItem(&s_UiPopups[i].m_pId);
 		
-		if(UI()->ActiveItem() == &ui_popups[i].id)
+		if(UI()->ActiveItem() == &s_UiPopups[i].m_pId)
 		{
 			if(!UI()->MouseButton(0))
 			{
-				if(!inside)
-					ui_num_popups--;
+				if(!Inside)
+					g_UiNumPopups--;
 				UI()->SetActiveItem(0);
 			}
 		}
-		else if(UI()->HotItem() == &ui_popups[i].id)
+		else if(UI()->HotItem() == &s_UiPopups[i].m_pId)
 		{
 			if(UI()->MouseButton(0))
-				UI()->SetActiveItem(&ui_popups[i].id);
+				UI()->SetActiveItem(&s_UiPopups[i].m_pId);
 		}
 		
-		int corners = CUI::CORNER_ALL;
-		if(ui_popups[i].is_menu)
-			corners = CUI::CORNER_R|CUI::CORNER_B;
+		int Corners = CUI::CORNER_ALL;
+		if(s_UiPopups[i].m_IsMenu)
+			Corners = CUI::CORNER_R|CUI::CORNER_B;
 		
-		CUIRect r = ui_popups[i].rect;
-		RenderTools()->DrawUIRect(&r, vec4(0.5f,0.5f,0.5f,0.75f), corners, 3.0f);
+		CUIRect r = s_UiPopups[i].m_Rect;
+		RenderTools()->DrawUIRect(&r, vec4(0.5f,0.5f,0.5f,0.75f), Corners, 3.0f);
 		r.Margin(1.0f, &r);
-		RenderTools()->DrawUIRect(&r, vec4(0,0,0,0.75f), corners, 3.0f);
+		RenderTools()->DrawUIRect(&r, vec4(0,0,0,0.75f), Corners, 3.0f);
 		r.Margin(4.0f, &r);
 		
-		if(ui_popups[i].func(this, r))
-			ui_num_popups--;
+		if(s_UiPopups[i].m_pfnFunc(this, r))
+			g_UiNumPopups--;
 			
-		if(inp_key_down(KEY_ESCAPE))
-			ui_num_popups--;
+		if(Input()->KeyDown(KEY_ESCAPE))
+			g_UiNumPopups--;
 	}
 }
 
 
-int EDITOR::popup_group(EDITOR *pEditor, CUIRect view)
+int CEditor::PopupGroup(CEditor *pEditor, CUIRect View)
 {
 	// remove group button
-	CUIRect button;
-	view.HSplitBottom(12.0f, &view, &button);
-	static int delete_button = 0;
+	CUIRect Button;
+	View.HSplitBottom(12.0f, &View, &Button);
+	static int s_DeleteButton = 0;
 	
 	// don't allow deletion of game group
-	if(pEditor->map.game_group != pEditor->get_selected_group() &&
-		pEditor->DoButton_Editor(&delete_button, "Delete Group", 0, &button, 0, "Delete group"))
+	if(pEditor->m_Map.m_pGameGroup != pEditor->GetSelectedGroup() &&
+		pEditor->DoButton_Editor(&s_DeleteButton, "Delete Group", 0, &Button, 0, "Delete group"))
 	{
-		pEditor->map.delete_group(pEditor->selected_group);
+		pEditor->m_Map.DeleteGroup(pEditor->m_SelectedGroup);
 		return 1;
 	}
 
 	// new tile layer
-	view.HSplitBottom(10.0f, &view, &button);
-	view.HSplitBottom(12.0f, &view, &button);
-	static int new_quad_layer_button = 0;
-	if(pEditor->DoButton_Editor(&new_quad_layer_button, "Add Quads Layer", 0, &button, 0, "Creates a new quad layer"))
+	View.HSplitBottom(10.0f, &View, &Button);
+	View.HSplitBottom(12.0f, &View, &Button);
+	static int s_NewQuadLayerButton = 0;
+	if(pEditor->DoButton_Editor(&s_NewQuadLayerButton, "Add Quads Layer", 0, &Button, 0, "Creates a new quad layer"))
 	{
-		LAYER *l = new LAYER_QUADS;
-		pEditor->map.groups[pEditor->selected_group]->add_layer(l);
-		pEditor->selected_layer = pEditor->map.groups[pEditor->selected_group]->layers.len()-1;
+		CLayer *l = new CLayerQuads;
+		l->m_pEditor = pEditor;
+		pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->AddLayer(l);
+		pEditor->m_SelectedLayer = pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_lLayers.size()-1;
 		return 1;
 	}
 
 	// new quad layer
-	view.HSplitBottom(5.0f, &view, &button);
-	view.HSplitBottom(12.0f, &view, &button);
-	static int new_tile_layer_button = 0;
-	if(pEditor->DoButton_Editor(&new_tile_layer_button, "Add Tile Layer", 0, &button, 0, "Creates a new tile layer"))
+	View.HSplitBottom(5.0f, &View, &Button);
+	View.HSplitBottom(12.0f, &View, &Button);
+	static int s_NewTileLayerButton = 0;
+	if(pEditor->DoButton_Editor(&s_NewTileLayerButton, "Add Tile Layer", 0, &Button, 0, "Creates a new tile layer"))
 	{
-		LAYER *l = new LAYER_TILES(50, 50);
-		pEditor->map.groups[pEditor->selected_group]->add_layer(l);
-		pEditor->selected_layer = pEditor->map.groups[pEditor->selected_group]->layers.len()-1;
+		CLayer *l = new CLayerTiles(50, 50);
+		l->m_pEditor = pEditor;
+		pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->AddLayer(l);
+		pEditor->m_SelectedLayer = pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_lLayers.size()-1;
 		return 1;
 	}
 	
@@ -124,68 +127,68 @@ int EDITOR::popup_group(EDITOR *pEditor, CUIRect view)
 		NUM_PROPS,
 	};
 	
-	PROPERTY props[] = {
-		{"Order", pEditor->selected_group, PROPTYPE_INT_STEP, 0, pEditor->map.groups.len()-1},
-		{"Pos X", -pEditor->map.groups[pEditor->selected_group]->offset_x, PROPTYPE_INT_SCROLL, -1000000, 1000000},
-		{"Pos Y", -pEditor->map.groups[pEditor->selected_group]->offset_y, PROPTYPE_INT_SCROLL, -1000000, 1000000},
-		{"Para X", pEditor->map.groups[pEditor->selected_group]->parallax_x, PROPTYPE_INT_SCROLL, -1000000, 1000000},
-		{"Para Y", pEditor->map.groups[pEditor->selected_group]->parallax_y, PROPTYPE_INT_SCROLL, -1000000, 1000000},
-
-		{"Use Clipping", pEditor->map.groups[pEditor->selected_group]->use_clipping, PROPTYPE_BOOL, 0, 1},
-		{"Clip X", pEditor->map.groups[pEditor->selected_group]->clip_x, PROPTYPE_INT_SCROLL, -1000000, 1000000},
-		{"Clip Y", pEditor->map.groups[pEditor->selected_group]->clip_y, PROPTYPE_INT_SCROLL, -1000000, 1000000},
-		{"Clip W", pEditor->map.groups[pEditor->selected_group]->clip_w, PROPTYPE_INT_SCROLL, -1000000, 1000000},
-		{"Clip H", pEditor->map.groups[pEditor->selected_group]->clip_h, PROPTYPE_INT_SCROLL, -1000000, 1000000},
+	CProperty aProps[] = {
+		{"Order", pEditor->m_SelectedGroup, PROPTYPE_INT_STEP, 0, pEditor->m_Map.m_lGroups.size()-1},
+		{"Pos X", -pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_OffsetX, PROPTYPE_INT_SCROLL, -1000000, 1000000},
+		{"Pos Y", -pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_OffsetY, PROPTYPE_INT_SCROLL, -1000000, 1000000},
+		{"Para X", pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ParallaxX, PROPTYPE_INT_SCROLL, -1000000, 1000000},
+		{"Para Y", pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ParallaxY, PROPTYPE_INT_SCROLL, -1000000, 1000000},
+
+		{"Use Clipping", pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_UseClipping, PROPTYPE_BOOL, 0, 1},
+		{"Clip X", pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ClipX, PROPTYPE_INT_SCROLL, -1000000, 1000000},
+		{"Clip Y", pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ClipY, PROPTYPE_INT_SCROLL, -1000000, 1000000},
+		{"Clip W", pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ClipW, PROPTYPE_INT_SCROLL, -1000000, 1000000},
+		{"Clip H", pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ClipH, PROPTYPE_INT_SCROLL, -1000000, 1000000},
 		{0},
 	};
 	
-	static int ids[NUM_PROPS] = {0};
-	int new_val = 0;
+	static int s_aIds[NUM_PROPS] = {0};
+	int NewVal = 0;
 	
 	// cut the properties that isn't needed
-	if(pEditor->get_selected_group()->game_group)
-		props[PROP_POS_X].name = 0;
+	if(pEditor->GetSelectedGroup()->m_GameGroup)
+		aProps[PROP_POS_X].m_pName = 0;
 		
-	int prop = pEditor->do_properties(&view, props, ids, &new_val);
-	if(prop == PROP_ORDER)
-		pEditor->selected_group = pEditor->map.swap_groups(pEditor->selected_group, new_val);
+	int Prop = pEditor->DoProperties(&View, aProps, s_aIds, &NewVal);
+	if(Prop == PROP_ORDER)
+		pEditor->m_SelectedGroup = pEditor->m_Map.SwapGroups(pEditor->m_SelectedGroup, NewVal);
 		
 	// these can not be changed on the game group
-	if(!pEditor->get_selected_group()->game_group)
+	if(!pEditor->GetSelectedGroup()->m_GameGroup)
 	{
-		if(prop == PROP_PARA_X) pEditor->map.groups[pEditor->selected_group]->parallax_x = new_val;
-		else if(prop == PROP_PARA_Y) pEditor->map.groups[pEditor->selected_group]->parallax_y = new_val;
-		else if(prop == PROP_POS_X) pEditor->map.groups[pEditor->selected_group]->offset_x = -new_val;
-		else if(prop == PROP_POS_Y) pEditor->map.groups[pEditor->selected_group]->offset_y = -new_val;
-		else if(prop == PROP_USE_CLIPPING) pEditor->map.groups[pEditor->selected_group]->use_clipping = new_val;
-		else if(prop == PROP_CLIP_X) pEditor->map.groups[pEditor->selected_group]->clip_x = new_val;
-		else if(prop == PROP_CLIP_Y) pEditor->map.groups[pEditor->selected_group]->clip_y = new_val;
-		else if(prop == PROP_CLIP_W) pEditor->map.groups[pEditor->selected_group]->clip_w = new_val;
-		else if(prop == PROP_CLIP_H) pEditor->map.groups[pEditor->selected_group]->clip_h = new_val;
+		if(Prop == PROP_PARA_X) pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ParallaxX = NewVal;
+		else if(Prop == PROP_PARA_Y) pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ParallaxY = NewVal;
+		else if(Prop == PROP_POS_X) pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_OffsetX = -NewVal;
+		else if(Prop == PROP_POS_Y) pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_OffsetY = -NewVal;
+		else if(Prop == PROP_USE_CLIPPING) pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_UseClipping = NewVal;
+		else if(Prop == PROP_CLIP_X) pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ClipX = NewVal;
+		else if(Prop == PROP_CLIP_Y) pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ClipY = NewVal;
+		else if(Prop == PROP_CLIP_W) pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ClipW = NewVal;
+		else if(Prop == PROP_CLIP_H) pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ClipH = NewVal;
 	}
 	
 	return 0;
 }
 
-int EDITOR::popup_layer(EDITOR *pEditor, CUIRect view)
+int CEditor::PopupLayer(CEditor *pEditor, CUIRect View)
 {
 	// remove layer button
-	CUIRect button;
-	view.HSplitBottom(12.0f, &view, &button);
-	static int delete_button = 0;
+	CUIRect Button;
+	View.HSplitBottom(12.0f, &View, &Button);
+	static int s_DeleteButton = 0;
 	
 	// don't allow deletion of game layer
-	if(pEditor->map.game_layer != pEditor->get_selected_layer(0) &&
-		pEditor->DoButton_Editor(&delete_button, "Delete Layer", 0, &button, 0, "Deletes the layer"))
+	if(pEditor->m_Map.m_pGameLayer != pEditor->GetSelectedLayer(0) &&
+		pEditor->DoButton_Editor(&s_DeleteButton, "Delete Layer", 0, &Button, 0, "Deletes the layer"))
 	{
-		pEditor->map.groups[pEditor->selected_group]->delete_layer(pEditor->selected_layer);
+		pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->DeleteLayer(pEditor->m_SelectedLayer);
 		return 1;
 	}
 
-	view.HSplitBottom(10.0f, &view, 0);
+	View.HSplitBottom(10.0f, &View, 0);
 	
-	LAYERGROUP *current_group = pEditor->map.groups[pEditor->selected_group];
-	LAYER *current_layer = pEditor->get_selected_layer(0);
+	CLayerGroup *pCurrentGroup = pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup];
+	CLayer *pCurrentLayer = pEditor->GetSelectedLayer(0);
 	
 	enum
 	{
@@ -195,82 +198,88 @@ int EDITOR::popup_layer(EDITOR *pEditor, CUIRect view)
 		NUM_PROPS,
 	};
 	
-	PROPERTY props[] = {
-		{"Group", pEditor->selected_group, PROPTYPE_INT_STEP, 0, pEditor->map.groups.len()-1},
-		{"Order", pEditor->selected_layer, PROPTYPE_INT_STEP, 0, current_group->layers.len()},
-		{"Detail", current_layer->flags&LAYERFLAG_DETAIL, PROPTYPE_BOOL, 0, 1},
+	CProperty aProps[] = {
+		{"Group", pEditor->m_SelectedGroup, PROPTYPE_INT_STEP, 0, pEditor->m_Map.m_lGroups.size()-1},
+		{"Order", pEditor->m_SelectedLayer, PROPTYPE_INT_STEP, 0, pCurrentGroup->m_lLayers.size()},
+		{"Detail", pCurrentLayer->m_Flags&LAYERFLAG_DETAIL, PROPTYPE_BOOL, 0, 1},
 		{0},
 	};
+
+	if(pEditor->m_Map.m_pGameLayer == pEditor->GetSelectedLayer(0)) // dont use Group and Detail from the selection if this is the game layer
+	{
+		aProps[0].m_Type = PROPTYPE_NULL;
+		aProps[2].m_Type = PROPTYPE_NULL;
+	}
 	
-	static int ids[NUM_PROPS] = {0};
-	int new_val = 0;
-	int prop = pEditor->do_properties(&view, props, ids, &new_val);		
+	static int s_aIds[NUM_PROPS] = {0};
+	int NewVal = 0;
+	int Prop = pEditor->DoProperties(&View, aProps, s_aIds, &NewVal);		
 	
-	if(prop == PROP_ORDER)
-		pEditor->selected_layer = current_group->swap_layers(pEditor->selected_layer, new_val);
-	else if(prop == PROP_GROUP && current_layer->type != LAYERTYPE_GAME)
+	if(Prop == PROP_ORDER)
+		pEditor->m_SelectedLayer = pCurrentGroup->SwapLayers(pEditor->m_SelectedLayer, NewVal);
+	else if(Prop == PROP_GROUP && pCurrentLayer->m_Type != LAYERTYPE_GAME)
 	{
-		if(new_val >= 0 && new_val < pEditor->map.groups.len())
+		if(NewVal >= 0 && NewVal < pEditor->m_Map.m_lGroups.size())
 		{
-			current_group->layers.remove(current_layer);
-			pEditor->map.groups[new_val]->layers.add(current_layer);
-			pEditor->selected_group = new_val;
-			pEditor->selected_layer = pEditor->map.groups[new_val]->layers.len()-1;
+			pCurrentGroup->m_lLayers.remove(pCurrentLayer);
+			pEditor->m_Map.m_lGroups[NewVal]->m_lLayers.add(pCurrentLayer);
+			pEditor->m_SelectedGroup = NewVal;
+			pEditor->m_SelectedLayer = pEditor->m_Map.m_lGroups[NewVal]->m_lLayers.size()-1;
 		}
 	}
-	else if(prop == PROP_HQ)
+	else if(Prop == PROP_HQ)
 	{
-		current_layer->flags &= ~LAYERFLAG_DETAIL;
-		if(new_val)
-			current_layer->flags |= LAYERFLAG_DETAIL;
+		pCurrentLayer->m_Flags &= ~LAYERFLAG_DETAIL;
+		if(NewVal)
+			pCurrentLayer->m_Flags |= LAYERFLAG_DETAIL;
 	}
 		
-	return current_layer->render_properties(&view);
+	return pCurrentLayer->RenderProperties(&View);
 }
 
-int EDITOR::popup_quad(EDITOR *pEditor, CUIRect view)
+int CEditor::PopupQuad(CEditor *pEditor, CUIRect View)
 {
-	QUAD *quad = pEditor->get_selected_quad();
+	CQuad *pQuad = pEditor->GetSelectedQuad();
 
-	CUIRect button;
+	CUIRect Button;
 	
 	// delete button
-	view.HSplitBottom(12.0f, &view, &button);
-	static int delete_button = 0;
-	if(pEditor->DoButton_Editor(&delete_button, "Delete", 0, &button, 0, "Deletes the current quad"))
+	View.HSplitBottom(12.0f, &View, &Button);
+	static int s_DeleteButton = 0;
+	if(pEditor->DoButton_Editor(&s_DeleteButton, "Delete", 0, &Button, 0, "Deletes the current quad"))
 	{
-		LAYER_QUADS *layer = (LAYER_QUADS *)pEditor->get_selected_layer_type(0, LAYERTYPE_QUADS);
-		if(layer)
+		CLayerQuads *pLayer = (CLayerQuads *)pEditor->GetSelectedLayerType(0, LAYERTYPE_QUADS);
+		if(pLayer)
 		{
-			layer->quads.removebyindex(pEditor->selected_quad);
-			pEditor->selected_quad--;
+			pLayer->m_lQuads.remove_index(pEditor->m_SelectedQuad);
+			pEditor->m_SelectedQuad--;
 		}
 		return 1;
 	}
 
 	// square button
-	view.HSplitBottom(10.0f, &view, &button);
-	view.HSplitBottom(12.0f, &view, &button);
-	static int sq_button = 0;
-	if(pEditor->DoButton_Editor(&sq_button, "Square", 0, &button, 0, "Squares the current quad"))
+	View.HSplitBottom(10.0f, &View, &Button);
+	View.HSplitBottom(12.0f, &View, &Button);
+	static int s_Button = 0;
+	if(pEditor->DoButton_Editor(&s_Button, "Square", 0, &Button, 0, "Squares the current quad"))
 	{
-		int top = quad->points[0].y;
-		int left = quad->points[0].x;
-		int bottom = quad->points[0].y;
-		int right = quad->points[0].x;
+		int Top = pQuad->m_aPoints[0].y;
+		int Left = pQuad->m_aPoints[0].x;
+		int Bottom = pQuad->m_aPoints[0].y;
+		int Right = pQuad->m_aPoints[0].x;
 		
 		for(int k = 1; k < 4; k++)
 		{
-			if(quad->points[k].y < top) top = quad->points[k].y;
-			if(quad->points[k].x < left) left = quad->points[k].x;
-			if(quad->points[k].y > bottom) bottom = quad->points[k].y;
-			if(quad->points[k].x > right) right = quad->points[k].x;
+			if(pQuad->m_aPoints[k].y < Top) Top = pQuad->m_aPoints[k].y;
+			if(pQuad->m_aPoints[k].x < Left) Left = pQuad->m_aPoints[k].x;
+			if(pQuad->m_aPoints[k].y > Bottom) Bottom = pQuad->m_aPoints[k].y;
+			if(pQuad->m_aPoints[k].x > Right) Right = pQuad->m_aPoints[k].x;
 		}
 		
-		quad->points[0].x = left; quad->points[0].y = top;
-		quad->points[1].x = right; quad->points[1].y = top;
-		quad->points[2].x = left; quad->points[2].y = bottom;
-		quad->points[3].x = right; quad->points[3].y = bottom;
+		pQuad->m_aPoints[0].x = Left; pQuad->m_aPoints[0].y = Top;
+		pQuad->m_aPoints[1].x = Right; pQuad->m_aPoints[1].y = Top;
+		pQuad->m_aPoints[2].x = Left; pQuad->m_aPoints[2].y = Bottom;
+		pQuad->m_aPoints[3].x = Right; pQuad->m_aPoints[3].y = Bottom;
 		return 1;
 	}
 
@@ -284,30 +293,30 @@ int EDITOR::popup_quad(EDITOR *pEditor, CUIRect view)
 		NUM_PROPS,
 	};
 	
-	PROPERTY props[] = {
-		{"Pos. Env", quad->pos_env, PROPTYPE_INT_STEP, -1, pEditor->map.envelopes.len()},
-		{"Pos. TO", quad->pos_env_offset, PROPTYPE_INT_SCROLL, -1000000, 1000000},
-		{"Color Env", quad->color_env, PROPTYPE_INT_STEP, -1, pEditor->map.envelopes.len()},
-		{"Color TO", quad->color_env_offset, PROPTYPE_INT_SCROLL, -1000000, 1000000},
+	CProperty aProps[] = {
+		{"Pos. Env", pQuad->m_PosEnv, PROPTYPE_INT_STEP, -1, pEditor->m_Map.m_lEnvelopes.size()},
+		{"Pos. TO", pQuad->m_PosEnvOffset, PROPTYPE_INT_SCROLL, -1000000, 1000000},
+		{"Color Env", pQuad->m_ColorEnv, PROPTYPE_INT_STEP, -1, pEditor->m_Map.m_lEnvelopes.size()},
+		{"Color TO", pQuad->m_ColorEnvOffset, PROPTYPE_INT_SCROLL, -1000000, 1000000},
 		
 		{0},
 	};
 	
-	static int ids[NUM_PROPS] = {0};
-	int new_val = 0;
-	int prop = pEditor->do_properties(&view, props, ids, &new_val);		
+	static int s_aIds[NUM_PROPS] = {0};
+	int NewVal = 0;
+	int Prop = pEditor->DoProperties(&View, aProps, s_aIds, &NewVal);		
 	
-	if(prop == PROP_POS_ENV) quad->pos_env = clamp(new_val, -1, pEditor->map.envelopes.len()-1);
-	if(prop == PROP_POS_ENV_OFFSET) quad->pos_env_offset = new_val;
-	if(prop == PROP_COLOR_ENV) quad->color_env = clamp(new_val, -1, pEditor->map.envelopes.len()-1);
-	if(prop == PROP_COLOR_ENV_OFFSET) quad->color_env_offset = new_val;
+	if(Prop == PROP_POS_ENV) pQuad->m_PosEnv = clamp(NewVal, -1, pEditor->m_Map.m_lEnvelopes.size()-1);
+	if(Prop == PROP_POS_ENV_OFFSET) pQuad->m_PosEnvOffset = NewVal;
+	if(Prop == PROP_COLOR_ENV) pQuad->m_ColorEnv = clamp(NewVal, -1, pEditor->m_Map.m_lEnvelopes.size()-1);
+	if(Prop == PROP_COLOR_ENV_OFFSET) pQuad->m_ColorEnvOffset = NewVal;
 	
 	return 0;
 }
 
-int EDITOR::popup_point(EDITOR *pEditor, CUIRect view)
+int CEditor::PopupPoint(CEditor *pEditor, CUIRect View)
 {
-	QUAD *quad = pEditor->get_selected_quad();
+	CQuad *pQuad = pEditor->GetSelectedQuad();
 	
 	enum
 	{
@@ -315,40 +324,40 @@ int EDITOR::popup_point(EDITOR *pEditor, CUIRect view)
 		NUM_PROPS,
 	};
 	
-	int color = 0;
+	int Color = 0;
 
 	for(int v = 0; v < 4; v++)
 	{
-		if(pEditor->selected_points&(1<<v))
+		if(pEditor->m_SelectedPoints&(1<<v))
 		{
-			color = 0;
-			color |= quad->colors[v].r<<24;
-			color |= quad->colors[v].g<<16;
-			color |= quad->colors[v].b<<8;
-			color |= quad->colors[v].a;
+			Color = 0;
+			Color |= pQuad->m_aColors[v].r<<24;
+			Color |= pQuad->m_aColors[v].g<<16;
+			Color |= pQuad->m_aColors[v].b<<8;
+			Color |= pQuad->m_aColors[v].a;
 		}
 	}
 	
 	
-	PROPERTY props[] = {
-		{"Color", color, PROPTYPE_COLOR, -1, pEditor->map.envelopes.len()},
+	CProperty aProps[] = {
+		{"Color", Color, PROPTYPE_COLOR, -1, pEditor->m_Map.m_lEnvelopes.size()},
 		{0},
 	};
 	
-	static int ids[NUM_PROPS] = {0};
-	int new_val = 0;
-	int prop = pEditor->do_properties(&view, props, ids, &new_val);		
-	if(prop == PROP_COLOR)
+	static int s_aIds[NUM_PROPS] = {0};
+	int NewVal = 0;
+	int Prop = pEditor->DoProperties(&View, aProps, s_aIds, &NewVal);		
+	if(Prop == PROP_COLOR)
 	{
 		for(int v = 0; v < 4; v++)
 		{
-			if(pEditor->selected_points&(1<<v))
+			if(pEditor->m_SelectedPoints&(1<<v))
 			{
-				color = 0;
-				quad->colors[v].r = (new_val>>24)&0xff;
-				quad->colors[v].g = (new_val>>16)&0xff;
-				quad->colors[v].b = (new_val>>8)&0xff;
-				quad->colors[v].a = new_val&0xff;
+				Color = 0;
+				pQuad->m_aColors[v].r = (NewVal>>24)&0xff;
+				pQuad->m_aColors[v].g = (NewVal>>16)&0xff;
+				pQuad->m_aColors[v].b = (NewVal>>8)&0xff;
+				pQuad->m_aColors[v].a = NewVal&0xff;
 			}
 		}
 	}
@@ -358,65 +367,66 @@ int EDITOR::popup_point(EDITOR *pEditor, CUIRect view)
 
 
 
-static int select_image_selected = -100;
-static int select_image_current = -100;
+static int g_SelectImageSelected = -100;
+static int g_SelectImageCurrent = -100;
 
-int EDITOR::popup_select_image(EDITOR *pEditor, CUIRect view)
+int CEditor::PopupSelectImage(CEditor *pEditor, CUIRect View)
 {
-	CUIRect buttonbar, imageview;
-	view.VSplitLeft(80.0f, &buttonbar, &view);
-	view.Margin(10.0f, &imageview);
+	CUIRect ButtonBar, ImageView;
+	View.VSplitLeft(80.0f, &ButtonBar, &View);
+	View.Margin(10.0f, &ImageView);
 	
-	int show_image = select_image_current;
+	int ShowImage = g_SelectImageCurrent;
 	
-	for(int i = -1; i < pEditor->map.images.len(); i++)
+	for(int i = -1; i < pEditor->m_Map.m_lImages.size(); i++)
 	{
-		CUIRect button;
-		buttonbar.HSplitTop(12.0f, &button, &buttonbar);
-		buttonbar.HSplitTop(2.0f, 0, &buttonbar);
+		CUIRect Button;
+		ButtonBar.HSplitTop(12.0f, &Button, &ButtonBar);
+		ButtonBar.HSplitTop(2.0f, 0, &ButtonBar);
 		
-		if(pEditor->UI()->MouseInside(&button))
-			show_image = i;
+		if(pEditor->UI()->MouseInside(&Button))
+			ShowImage = i;
 			
 		if(i == -1)
 		{
-			if(pEditor->DoButton_MenuItem(&pEditor->map.images[i], "None", i==select_image_current, &button))
-				select_image_selected = -1;
+			if(pEditor->DoButton_MenuItem(&pEditor->m_Map.m_lImages[i], "None", i==g_SelectImageCurrent, &Button))
+				g_SelectImageSelected = -1;
 		}
 		else
 		{
-			if(pEditor->DoButton_MenuItem(&pEditor->map.images[i], pEditor->map.images[i]->name, i==select_image_current, &button))
-				select_image_selected = i;
+			if(pEditor->DoButton_MenuItem(&pEditor->m_Map.m_lImages[i], pEditor->m_Map.m_lImages[i]->m_aName, i==g_SelectImageCurrent, &Button))
+				g_SelectImageSelected = i;
 		}
 	}
 	
-	if(show_image >= 0 && show_image < pEditor->map.images.len())
-		pEditor->Graphics()->TextureSet(pEditor->map.images[show_image]->tex_id);
+	if(ShowImage >= 0 && ShowImage < pEditor->m_Map.m_lImages.size())
+		pEditor->Graphics()->TextureSet(pEditor->m_Map.m_lImages[ShowImage]->m_TexId);
 	else
 		pEditor->Graphics()->TextureSet(-1);
 	pEditor->Graphics()->QuadsBegin();
-	pEditor->Graphics()->QuadsDrawTL(imageview.x, imageview.y, imageview.w, imageview.h);
+	IGraphics::CQuadItem QuadItem(ImageView.x, ImageView.y, ImageView.w, ImageView.h);
+	pEditor->Graphics()->QuadsDrawTL(&QuadItem, 1);
 	pEditor->Graphics()->QuadsEnd();
 
 	return 0;
 }
 
-void EDITOR::popup_select_image_invoke(int current, float x, float y)
+void CEditor::PopupSelectImageInvoke(int Current, float x, float y)
 {
-	static int select_image_popup_id = 0;
-	select_image_selected = -100;
-	select_image_current = current;
-	ui_invoke_popup_menu(&select_image_popup_id, 0, x, y, 400, 300, popup_select_image);
+	static int s_SelectImagePopupId = 0;
+	g_SelectImageSelected = -100;
+	g_SelectImageCurrent = Current;
+	UiInvokePopupMenu(&s_SelectImagePopupId, 0, x, y, 400, 300, PopupSelectImage);
 }
 
-int EDITOR::popup_select_image_result()
+int CEditor::PopupSelectImageResult()
 {
-	if(select_image_selected == -100)
+	if(g_SelectImageSelected == -100)
 		return -100;
 		
-	select_image_current = select_image_selected;
-	select_image_selected = -100;
-	return select_image_current;
+	g_SelectImageCurrent = g_SelectImageSelected;
+	g_SelectImageSelected = -100;
+	return g_SelectImageCurrent;
 }
 
 
diff --git a/src/game/gamecore.cpp b/src/game/gamecore.cpp
index ceb63be3..f5aa18cf 100644
--- a/src/game/gamecore.cpp
+++ b/src/game/gamecore.cpp
@@ -1,417 +1,311 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <string.h>
-#include "gamecore.hpp"
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+#include "gamecore.h"
 
-const char *TUNING_PARAMS::names[] =
+const char *CTuningParams::m_apNames[] =
 {
-	#define MACRO_TUNING_PARAM(name,value) #name,
-	#include "tuning.hpp"
+	#define MACRO_TUNING_PARAM(Name,ScriptName,Value) #ScriptName,
+	#include "tuning.h"
 	#undef MACRO_TUNING_PARAM
 };
 
 
-bool TUNING_PARAMS::set(int index, float value)
+bool CTuningParams::Set(int Index, float Value)
 {
-	if(index < 0 || index >= num())
+	if(Index < 0 || Index >= Num())
 		return false;
-	((tune_param *)this)[index] = value;
+	((CTuneParam *)this)[Index] = Value;
 	return true;
 }
 
-bool TUNING_PARAMS::get(int index, float *value)
+bool CTuningParams::Get(int Index, float *pValue)
 {
-	if(index < 0 || index >= num())
+	if(Index < 0 || Index >= Num())
 		return false;
-	*value = (float)((tune_param *)this)[index];
+	*pValue = (float)((CTuneParam *)this)[Index];
 	return true;
 }
 
-bool TUNING_PARAMS::set(const char *name, float value)
+bool CTuningParams::Set(const char *pName, float Value)
 {
-	for(int i = 0; i < num(); i++)
-		if(strcmp(name, names[i]) == 0)
-			return set(i, value);
+	for(int i = 0; i < Num(); i++)
+		if(str_comp_nocase(pName, m_apNames[i]) == 0)
+			return Set(i, Value);
 	return false;
 }
 
-bool TUNING_PARAMS::get(const char *name, float *value)
+bool CTuningParams::Get(const char *pName, float *pValue)
 {
-	for(int i = 0; i < num(); i++)
-		if(strcmp(name, names[i]) == 0)
-			return get(i, value);
+	for(int i = 0; i < Num(); i++)
+		if(str_comp_nocase(pName, m_apNames[i]) == 0)
+			return Get(i, pValue);
 	
 	return false;
 }
 
-// TODO: OPT: rewrite this smarter!
-void move_point(vec2 *inout_pos, vec2 *inout_vel, float elasticity, int *bounces)
+float HermiteBasis1(float v)
 {
-	if(bounces)
-		*bounces = 0;
-	
-	vec2 pos = *inout_pos;
-	vec2 vel = *inout_vel;
-	if(col_check_point(pos + vel))
-	{
-		int affected = 0;
-		if(col_check_point(pos.x + vel.x, pos.y))
-		{
-			inout_vel->x *= -elasticity;
-			if(bounces)
-				(*bounces)++;			
-			affected++;
-		}
-
-		if(col_check_point(pos.x, pos.y + vel.y))
-		{
-			inout_vel->y *= -elasticity;
-			if(bounces)
-				(*bounces)++;			
-			affected++;
-		}
-		
-		if(affected == 0)
-		{
-			inout_vel->x *= -elasticity;
-			inout_vel->y *= -elasticity;
-		}
-	}
-	else
-	{
-		*inout_pos = pos + vel;
-	}
-}
-
-bool test_box(vec2 pos, vec2 size)
-{
-	size *= 0.5f;
-	if(col_check_point(pos.x-size.x, pos.y-size.y))
-		return true;
-	if(col_check_point(pos.x+size.x, pos.y-size.y))
-		return true;
-	if(col_check_point(pos.x-size.x, pos.y+size.y))
-		return true;
-	if(col_check_point(pos.x+size.x, pos.y+size.y))
-		return true;
-	return false;
-}
-
-void move_box(vec2 *inout_pos, vec2 *inout_vel, vec2 size, float elasticity)
-{
-	// do the move
-	vec2 pos = *inout_pos;
-	vec2 vel = *inout_vel;
-	
-	float distance = length(vel);
-	int max = (int)distance;
-	
-	if(distance > 0.00001f)
-	{
-		//vec2 old_pos = pos;
-		float fraction = 1.0f/(float)(max+1);
-		for(int i = 0; i <= max; i++)
-		{
-			//float amount = i/(float)max;
-			//if(max == 0)
-				//amount = 0;
-			
-			vec2 new_pos = pos + vel*fraction; // TODO: this row is not nice
-			
-			if(test_box(vec2(new_pos.x, new_pos.y), size))
-			{
-				int hits = 0;
-				
-				if(test_box(vec2(pos.x, new_pos.y), size))
-				{
-					new_pos.y = pos.y;
-					vel.y *= -elasticity;
-					hits++;
-				}
-				
-				if(test_box(vec2(new_pos.x, pos.y), size))
-				{
-					new_pos.x = pos.x;
-					vel.x *= -elasticity;
-					hits++;
-				}
-				
-				// neither of the tests got a collision.
-				// this is a real _corner case_!
-				if(hits == 0)
-				{
-					new_pos.y = pos.y;
-					vel.y *= -elasticity;
-					new_pos.x = pos.x;
-					vel.x *= -elasticity;
-				}
-			}
-			
-			pos = new_pos;
-		}
-	}
-	
-	*inout_pos = pos;
-	*inout_vel = vel;
+	return 2*v*v*v - 3*v*v+1;
 }
 
-float hermite_basis1(float v)
+float VelocityRamp(float Value, float Start, float Range, float Curvature)
 {
-	return 2*v*v*v - 3*v*v+1;
+	if(Value < Start)
+		return 1.0f;
+	return 1.0f/powf(Curvature, (Value-Start)/Range);
 }
 
-float velocity_ramp(float value, float start, float range, float curvature)
+void CCharacterCore::Init(CWorldCore *pWorld, CCollision *pCollision)
 {
-	if(value < start)
-		return 1.0f;
-	return 1.0f/pow(curvature, (value-start)/range);
+	m_pWorld = pWorld;
+	m_pCollision = pCollision;
 }
 
-void CHARACTER_CORE::reset()
+void CCharacterCore::Reset()
 {
-	pos = vec2(0,0);
-	vel = vec2(0,0);
-	hook_pos = vec2(0,0);
-	hook_dir = vec2(0,0);
-	hook_tick = 0;
-	hook_state = HOOK_IDLE;
-	hooked_player = -1;
-	jumped = 0;
-	triggered_events = 0;
+	m_Pos = vec2(0,0);
+	m_Vel = vec2(0,0);
+	m_HookPos = vec2(0,0);
+	m_HookDir = vec2(0,0);
+	m_HookTick = 0;
+	m_HookState = HOOK_IDLE;
+	m_HookedPlayer = -1;
+	m_Jumped = 0;
+	m_TriggeredEvents = 0;
 }
 
-void CHARACTER_CORE::tick(bool use_input)
+void CCharacterCore::Tick(bool UseInput)
 {
-	float phys_size = 28.0f;
-	triggered_events = 0;
+	float PhysSize = 28.0f;
+	m_TriggeredEvents = 0;
 	
 	// get ground state
-	bool grounded = false;
-	if(col_check_point(pos.x+phys_size/2, pos.y+phys_size/2+5))
-		grounded = true;
-	if(col_check_point(pos.x-phys_size/2, pos.y+phys_size/2+5))
-		grounded = true;
+	bool Grounded = false;
+	if(m_pCollision->CheckPoint(m_Pos.x+PhysSize/2, m_Pos.y+PhysSize/2+5))
+		Grounded = true;
+	if(m_pCollision->CheckPoint(m_Pos.x-PhysSize/2, m_Pos.y+PhysSize/2+5))
+		Grounded = true;
 	
-	vec2 target_direction = normalize(vec2(input.target_x, input.target_y));
+	vec2 TargetDirection = normalize(vec2(m_Input.m_TargetX, m_Input.m_TargetY));
 
-	vel.y += world->tuning.gravity;
+	m_Vel.y += m_pWorld->m_Tuning.m_Gravity;
 	
-	float max_speed = grounded ? world->tuning.ground_control_speed : world->tuning.air_control_speed;
-	float accel = grounded ? world->tuning.ground_control_accel : world->tuning.air_control_accel;
-	float friction = grounded ? world->tuning.ground_friction : world->tuning.air_friction;
+	float MaxSpeed = Grounded ? m_pWorld->m_Tuning.m_GroundControlSpeed : m_pWorld->m_Tuning.m_AirControlSpeed;
+	float Accel = Grounded ? m_pWorld->m_Tuning.m_GroundControlAccel : m_pWorld->m_Tuning.m_AirControlAccel;
+	float Friction = Grounded ? m_pWorld->m_Tuning.m_GroundFriction : m_pWorld->m_Tuning.m_AirFriction;
 	
 	// handle input
-	if(use_input)
+	if(UseInput)
 	{
-		direction = input.direction;
+		m_Direction = m_Input.m_Direction;
 
 		// setup angle
 		float a = 0;
-		if(input.target_x == 0)
-			a = atan((float)input.target_y);
+		if(m_Input.m_TargetX == 0)
+			a = atanf((float)m_Input.m_TargetY);
 		else
-			a = atan((float)input.target_y/(float)input.target_x);
+			a = atanf((float)m_Input.m_TargetY/(float)m_Input.m_TargetX);
 			
-		if(input.target_x < 0)
+		if(m_Input.m_TargetX < 0)
 			a = a+pi;
 			
-		angle = (int)(a*256.0f);
+		m_Angle = (int)(a*256.0f);
 
 		// handle jump
-		if(input.jump)
+		if(m_Input.m_Jump)
 		{
-			if(!(jumped&1))
+			if(!(m_Jumped&1))
 			{
-				if(grounded)
+				if(Grounded)
 				{
-					triggered_events |= COREEVENT_GROUND_JUMP;
-					vel.y = -world->tuning.ground_jump_impulse;
-					jumped |= 1;
+					m_TriggeredEvents |= COREEVENT_GROUND_JUMP;
+					m_Vel.y = -m_pWorld->m_Tuning.m_GroundJumpImpulse;
+					m_Jumped |= 1;
 				}
-				else if(!(jumped&2))
+				else if(!(m_Jumped&2))
 				{
-					triggered_events |= COREEVENT_AIR_JUMP;
-					vel.y = -world->tuning.air_jump_impulse;
-					jumped |= 3;
+					m_TriggeredEvents |= COREEVENT_AIR_JUMP;
+					m_Vel.y = -m_pWorld->m_Tuning.m_AirJumpImpulse;
+					m_Jumped |= 3;
 				}
 			}
 		}
 		else
-			jumped &= ~1;
+			m_Jumped &= ~1;
 
 		// handle hook
-		if(input.hook)
+		if(m_Input.m_Hook)
 		{
-			if(hook_state == HOOK_IDLE)
+			if(m_HookState == HOOK_IDLE)
 			{
-				hook_state = HOOK_FLYING;
-				hook_pos = pos+target_direction*phys_size*1.5f;
-				hook_dir = target_direction;
-				hooked_player = -1;
-				hook_tick = 0;
-				triggered_events |= COREEVENT_HOOK_LAUNCH;
+				m_HookState = HOOK_FLYING;
+				m_HookPos = m_Pos+TargetDirection*PhysSize*1.5f;
+				m_HookDir = TargetDirection;
+				m_HookedPlayer = -1;
+				m_HookTick = 0;
+				m_TriggeredEvents |= COREEVENT_HOOK_LAUNCH;
 			}		
 		}
 		else
 		{
-			hooked_player = -1;
-			hook_state = HOOK_IDLE;
-			hook_pos = pos;			
+			m_HookedPlayer = -1;
+			m_HookState = HOOK_IDLE;
+			m_HookPos = m_Pos;			
 		}		
 	}
 	
 	// add the speed modification according to players wanted direction
-	if(direction < 0)
-		vel.x = saturated_add(-max_speed, max_speed, vel.x, -accel);
-	if(direction > 0)
-		vel.x = saturated_add(-max_speed, max_speed, vel.x, accel);
-	if(direction == 0)
-		vel.x *= friction;
+	if(m_Direction < 0)
+		m_Vel.x = SaturatedAdd(-MaxSpeed, MaxSpeed, m_Vel.x, -Accel);
+	if(m_Direction > 0)
+		m_Vel.x = SaturatedAdd(-MaxSpeed, MaxSpeed, m_Vel.x, Accel);
+	if(m_Direction == 0)
+		m_Vel.x *= Friction;
 	
 	// handle jumping
 	// 1 bit = to keep track if a jump has been made on this input
 	// 2 bit = to keep track if a air-jump has been made
-	if(grounded)
-		jumped &= ~2;
+	if(Grounded)
+		m_Jumped &= ~2;
 	
 	// do hook
-	if(hook_state == HOOK_IDLE)
+	if(m_HookState == HOOK_IDLE)
 	{
-		hooked_player = -1;
-		hook_state = HOOK_IDLE;
-		hook_pos = pos;
+		m_HookedPlayer = -1;
+		m_HookState = HOOK_IDLE;
+		m_HookPos = m_Pos;
 	}
-	else if(hook_state >= HOOK_RETRACT_START && hook_state < HOOK_RETRACT_END)
+	else if(m_HookState >= HOOK_RETRACT_START && m_HookState < HOOK_RETRACT_END)
 	{
-		hook_state++;
+		m_HookState++;
 	}
-	else if(hook_state == HOOK_RETRACT_END)
+	else if(m_HookState == HOOK_RETRACT_END)
 	{
-		hook_state = HOOK_RETRACTED;
-		triggered_events |= COREEVENT_HOOK_RETRACT;
-		hook_state = HOOK_RETRACTED;
+		m_HookState = HOOK_RETRACTED;
+		m_TriggeredEvents |= COREEVENT_HOOK_RETRACT;
+		m_HookState = HOOK_RETRACTED;
 	}
-	else if(hook_state == HOOK_FLYING)
+	else if(m_HookState == HOOK_FLYING)
 	{
-		vec2 new_pos = hook_pos+hook_dir*world->tuning.hook_fire_speed;
-		if(distance(pos, new_pos) > world->tuning.hook_length)
+		vec2 NewPos = m_HookPos+m_HookDir*m_pWorld->m_Tuning.m_HookFireSpeed;
+		if(distance(m_Pos, NewPos) > m_pWorld->m_Tuning.m_HookLength)
 		{
-			hook_state = HOOK_RETRACT_START;
-			new_pos = pos + normalize(new_pos-pos) * world->tuning.hook_length;
+			m_HookState = HOOK_RETRACT_START;
+			NewPos = m_Pos + normalize(NewPos-m_Pos) * m_pWorld->m_Tuning.m_HookLength;
 		}
 		
 		// make sure that the hook doesn't go though the ground
-		bool going_to_hit_ground = false;
-		bool going_to_retract = false;
-		int hit = col_intersect_line(hook_pos, new_pos, &new_pos, 0);
-		if(hit)
+		bool GoingToHitGround = false;
+		bool GoingToRetract = false;
+		int Hit = m_pCollision->IntersectLine(m_HookPos, NewPos, &NewPos, 0);
+		if(Hit)
 		{
-			if(hit&COLFLAG_NOHOOK)
-				going_to_retract = true;
+			if(Hit&CCollision::COLFLAG_NOHOOK)
+				GoingToRetract = true;
 			else
-				going_to_hit_ground = true;
+				GoingToHitGround = true;
 		}
 
 		// Check against other players first
-		if(world && world->tuning.player_hooking)
+		if(m_pWorld && m_pWorld->m_Tuning.m_PlayerHooking)
 		{
-			float dist = 0.0f;
+			float Dist = 0.0f;
 			for(int i = 0; i < MAX_CLIENTS; i++)
 			{
-				CHARACTER_CORE *p = world->characters[i];
+				CCharacterCore *p = m_pWorld->m_apCharacters[i];
 				if(!p || p == this)
 					continue;
 
-				vec2 closest_point = closest_point_on_line(hook_pos, new_pos, p->pos);
-				if(distance(p->pos, closest_point) < phys_size+2.0f)
+				vec2 ClosestPoint = closest_point_on_line(m_HookPos, NewPos, p->m_Pos);
+				if(distance(p->m_Pos, ClosestPoint) < PhysSize+2.0f)
 				{
-					if (hooked_player == -1 || distance (hook_pos, p->pos) < dist)
+					if (m_HookedPlayer == -1 || distance(m_HookPos, p->m_Pos) < Dist)
 					{
-						triggered_events |= COREEVENT_HOOK_ATTACH_PLAYER;
-						hook_state = HOOK_GRABBED;
-						hooked_player = i;
-						dist = distance (hook_pos, p->pos);
+						m_TriggeredEvents |= COREEVENT_HOOK_ATTACH_PLAYER;
+						m_HookState = HOOK_GRABBED;
+						m_HookedPlayer = i;
+						Dist = distance(m_HookPos, p->m_Pos);
 					}
 				}
 			}
 		}
 		
-		if(hook_state == HOOK_FLYING)
+		if(m_HookState == HOOK_FLYING)
 		{
 			// check against ground
-			if(going_to_hit_ground)
+			if(GoingToHitGround)
 			{
-				triggered_events |= COREEVENT_HOOK_ATTACH_GROUND;
-				hook_state = HOOK_GRABBED;
+				m_TriggeredEvents |= COREEVENT_HOOK_ATTACH_GROUND;
+				m_HookState = HOOK_GRABBED;
 			}
-			else if(going_to_retract)
+			else if(GoingToRetract)
 			{
-				triggered_events |= COREEVENT_HOOK_HIT_NOHOOK;
-				hook_state = HOOK_RETRACT_START;
+				m_TriggeredEvents |= COREEVENT_HOOK_HIT_NOHOOK;
+				m_HookState = HOOK_RETRACT_START;
 			}
 			
-			hook_pos = new_pos;
+			m_HookPos = NewPos;
 		}
 	}
 	
-	if(hook_state == HOOK_GRABBED)
+	if(m_HookState == HOOK_GRABBED)
 	{
-		if(hooked_player != -1)
+		if(m_HookedPlayer != -1)
 		{
-			CHARACTER_CORE *p = world->characters[hooked_player];
+			CCharacterCore *p = m_pWorld->m_apCharacters[m_HookedPlayer];
 			if(p)
-				hook_pos = p->pos;
+				m_HookPos = p->m_Pos;
 			else
 			{
 				// release hook
-				hooked_player = -1;
-				hook_state = HOOK_RETRACTED;
-				hook_pos = pos;					
+				m_HookedPlayer = -1;
+				m_HookState = HOOK_RETRACTED;
+				m_HookPos = m_Pos;					
 			}
 			
 			// keep players hooked for a max of 1.5sec
-			//if(server_tick() > hook_tick+(server_tickspeed()*3)/2)
+			//if(Server()->Tick() > hook_tick+(Server()->TickSpeed()*3)/2)
 				//release_hooked();
 		}
 		
 		// don't do this hook rutine when we are hook to a player
-		if(hooked_player == -1 && distance(hook_pos, pos) > 46.0f)
+		if(m_HookedPlayer == -1 && distance(m_HookPos, m_Pos) > 46.0f)
 		{
-			vec2 hookvel = normalize(hook_pos-pos)*world->tuning.hook_drag_accel;
+			vec2 HookVel = normalize(m_HookPos-m_Pos)*m_pWorld->m_Tuning.m_HookDragAccel;
 			// the hook as more power to drag you up then down.
 			// this makes it easier to get on top of an platform
-			if(hookvel.y > 0)
-				hookvel.y *= 0.3f;
+			if(HookVel.y > 0)
+				HookVel.y *= 0.3f;
 			
 			// the hook will boost it's power if the player wants to move
 			// in that direction. otherwise it will dampen everything abit
-			if((hookvel.x < 0 && direction < 0) || (hookvel.x > 0 && direction > 0)) 
-				hookvel.x *= 0.95f;
+			if((HookVel.x < 0 && m_Direction < 0) || (HookVel.x > 0 && m_Direction > 0)) 
+				HookVel.x *= 0.95f;
 			else
-				hookvel.x *= 0.75f;
+				HookVel.x *= 0.75f;
 			
-			vec2 new_vel = vel+hookvel;
+			vec2 NewVel = m_Vel+HookVel;
 
 			// check if we are under the legal limit for the hook
-			if(length(new_vel) < world->tuning.hook_drag_speed || length(new_vel) < length(vel))
-				vel = new_vel; // no problem. apply
+			if(length(NewVel) < m_pWorld->m_Tuning.m_HookDragSpeed || length(NewVel) < length(m_Vel))
+				m_Vel = NewVel; // no problem. apply
 				
 		}
 
 		// release hook (max hook time is 1.25
-		hook_tick++;
-		if(hooked_player != -1 && (hook_tick > SERVER_TICK_SPEED+SERVER_TICK_SPEED/5 || !world->characters[hooked_player]))
+		m_HookTick++;
+		if(m_HookedPlayer != -1 && (m_HookTick > SERVER_TICK_SPEED+SERVER_TICK_SPEED/5 || !m_pWorld->m_apCharacters[m_HookedPlayer]))
 		{
-			hooked_player = -1;
-			hook_state = HOOK_RETRACTED;
-			hook_pos = pos;			
+			m_HookedPlayer = -1;
+			m_HookState = HOOK_RETRACTED;
+			m_HookPos = m_Pos;			
 		}
 	}
 	
-	if(world && world->tuning.player_collision)
+	if(m_pWorld && m_pWorld->m_Tuning.m_PlayerCollision)
 	{
 		for(int i = 0; i < MAX_CLIENTS; i++)
 		{
-			CHARACTER_CORE *p = world->characters[i];
+			CCharacterCore *p = m_pWorld->m_apCharacters[i];
 			if(!p)
 				continue;
 			
@@ -420,95 +314,95 @@ void CHARACTER_CORE::tick(bool use_input)
 				continue; // make sure that we don't nudge our self
 			
 			// handle player <-> player collision
-			float d = distance(pos, p->pos);
-			vec2 dir = normalize(pos - p->pos);
-			if(d < phys_size*1.25f && d > 1.0f)
+			float d = distance(m_Pos, p->m_Pos);
+			vec2 Dir = normalize(m_Pos - p->m_Pos);
+			if(d < PhysSize*1.25f && d > 1.0f)
 			{
-				float a = (phys_size*1.45f - d);
+				float a = (PhysSize*1.45f - d);
 				
 				// make sure that we don't add excess force by checking the
 				// direction against the current velocity
-				vec2 veldir = normalize(vel);
-				float v = 1-(dot(veldir, dir)+1)/2;
-				vel = vel + dir*a*(v*0.75f);
-				vel = vel * 0.85f;
+				vec2 VelDir = normalize(m_Vel);
+				float v = 1-(dot(VelDir, Dir)+1)/2;
+				m_Vel = m_Vel + Dir*a*(v*0.75f);
+				m_Vel = m_Vel * 0.85f;
 			}
 			
 			// handle hook influence
-			if(hooked_player == i)
+			if(m_HookedPlayer == i)
 			{
-				if(d > phys_size*1.50f) // TODO: fix tweakable variable
+				if(d > PhysSize*1.50f) // TODO: fix tweakable variable
 				{
-					float accel = world->tuning.hook_drag_accel * (d/world->tuning.hook_length);
-					float drag_speed = world->tuning.hook_drag_speed;
+					float Accel = m_pWorld->m_Tuning.m_HookDragAccel * (d/m_pWorld->m_Tuning.m_HookLength);
+					float DragSpeed = m_pWorld->m_Tuning.m_HookDragSpeed;
 					
 					// add force to the hooked player
-					p->vel.x = saturated_add(-drag_speed, drag_speed, p->vel.x, accel*dir.x*1.5f);
-					p->vel.y = saturated_add(-drag_speed, drag_speed, p->vel.y, accel*dir.y*1.5f);
+					p->m_Vel.x = SaturatedAdd(-DragSpeed, DragSpeed, p->m_Vel.x, Accel*Dir.x*1.5f);
+					p->m_Vel.y = SaturatedAdd(-DragSpeed, DragSpeed, p->m_Vel.y, Accel*Dir.y*1.5f);
 
 					// add a little bit force to the guy who has the grip
-					vel.x = saturated_add(-drag_speed, drag_speed, vel.x, -accel*dir.x*0.25f);
-					vel.y = saturated_add(-drag_speed, drag_speed, vel.y, -accel*dir.y*0.25f);
+					m_Vel.x = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.x, -Accel*Dir.x*0.25f);
+					m_Vel.y = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.y, -Accel*Dir.y*0.25f);
 				}
 			}
 		}
 	}	
 
 	// clamp the velocity to something sane
-	if(length(vel) > 6000)
-		vel = normalize(vel) * 6000;
+	if(length(m_Vel) > 6000)
+		m_Vel = normalize(m_Vel) * 6000;
 }
 
-void CHARACTER_CORE::move()
+void CCharacterCore::Move()
 {
-	float rampvalue = velocity_ramp(length(vel)*50, world->tuning.velramp_start, world->tuning.velramp_range, world->tuning.velramp_curvature);
+	float RampValue = VelocityRamp(length(m_Vel)*50, m_pWorld->m_Tuning.m_VelrampStart, m_pWorld->m_Tuning.m_VelrampRange, m_pWorld->m_Tuning.m_VelrampCurvature);
 	
-	vel.x = vel.x*rampvalue;
-	move_box(&pos, &vel, vec2(28.0f, 28.0f), 0);
-	vel.x = vel.x*(1.0f/rampvalue);
+	m_Vel.x = m_Vel.x*RampValue;
+	m_pCollision->MoveBox(&m_Pos, &m_Vel, vec2(28.0f, 28.0f), 0);
+	m_Vel.x = m_Vel.x*(1.0f/RampValue);
 }
 
-void CHARACTER_CORE::write(NETOBJ_CHARACTER_CORE *obj_core)
+void CCharacterCore::Write(CNetObj_CharacterCore *pObjCore)
 {
-	obj_core->x = round(pos.x);
-	obj_core->y = round(pos.y);
+	pObjCore->m_X = round(m_Pos.x);
+	pObjCore->m_Y = round(m_Pos.y);
 	
-	obj_core->vx = round(vel.x*256.0f);
-	obj_core->vy = round(vel.y*256.0f);
-	obj_core->hook_state = hook_state;
-	obj_core->hook_tick = hook_tick;
-	obj_core->hook_x = round(hook_pos.x);
-	obj_core->hook_y = round(hook_pos.y);
-	obj_core->hook_dx = round(hook_dir.x*256.0f);
-	obj_core->hook_dy = round(hook_dir.y*256.0f);
-	obj_core->hooked_player = hooked_player;
-	obj_core->jumped = jumped;
-	obj_core->direction = direction;
-	obj_core->angle = angle;
+	pObjCore->m_VelX = round(m_Vel.x*256.0f);
+	pObjCore->m_VelY = round(m_Vel.y*256.0f);
+	pObjCore->m_HookState = m_HookState;
+	pObjCore->m_HookTick = m_HookTick;
+	pObjCore->m_HookX = round(m_HookPos.x);
+	pObjCore->m_HookY = round(m_HookPos.y);
+	pObjCore->m_HookDx = round(m_HookDir.x*256.0f);
+	pObjCore->m_HookDy = round(m_HookDir.y*256.0f);
+	pObjCore->m_HookedPlayer = m_HookedPlayer;
+	pObjCore->m_Jumped = m_Jumped;
+	pObjCore->m_Direction = m_Direction;
+	pObjCore->m_Angle = m_Angle;
 }
 
-void CHARACTER_CORE::read(const NETOBJ_CHARACTER_CORE *obj_core)
+void CCharacterCore::Read(const CNetObj_CharacterCore *pObjCore)
 {
-	pos.x = obj_core->x;
-	pos.y = obj_core->y;
-	vel.x = obj_core->vx/256.0f;
-	vel.y = obj_core->vy/256.0f;
-	hook_state = obj_core->hook_state;
-	hook_tick = obj_core->hook_tick;
-	hook_pos.x = obj_core->hook_x;
-	hook_pos.y = obj_core->hook_y;
-	hook_dir.x = obj_core->hook_dx/256.0f;
-	hook_dir.y = obj_core->hook_dy/256.0f;
-	hooked_player = obj_core->hooked_player;
-	jumped = obj_core->jumped;
-	direction = obj_core->direction;
-	angle = obj_core->angle;
+	m_Pos.x = pObjCore->m_X;
+	m_Pos.y = pObjCore->m_Y;
+	m_Vel.x = pObjCore->m_VelX/256.0f;
+	m_Vel.y = pObjCore->m_VelY/256.0f;
+	m_HookState = pObjCore->m_HookState;
+	m_HookTick = pObjCore->m_HookTick;
+	m_HookPos.x = pObjCore->m_HookX;
+	m_HookPos.y = pObjCore->m_HookY;
+	m_HookDir.x = pObjCore->m_HookDx/256.0f;
+	m_HookDir.y = pObjCore->m_HookDy/256.0f;
+	m_HookedPlayer = pObjCore->m_HookedPlayer;
+	m_Jumped = pObjCore->m_Jumped;
+	m_Direction = pObjCore->m_Direction;
+	m_Angle = pObjCore->m_Angle;
 }
 
-void CHARACTER_CORE::quantize()
+void CCharacterCore::Quantize()
 {
-	NETOBJ_CHARACTER_CORE c;
-	write(&c);
-	read(&c);
+	CNetObj_CharacterCore Core;
+	Write(&Core);
+	Read(&Core);
 }
 
diff --git a/src/game/gamecore.h b/src/game/gamecore.h
new file mode 100644
index 00000000..816e1771
--- /dev/null
+++ b/src/game/gamecore.h
@@ -0,0 +1,205 @@
+#ifndef GAME_GAMECORE_H
+#define GAME_GAMECORE_H
+
+#include <base/system.h>
+#include <base/math.h>
+
+#include <math.h>
+#include "collision.h"
+#include <engine/shared/protocol.h>
+#include <game/generated/protocol.h>
+
+
+class CTuneParam
+{
+	int m_Value;
+public:
+	void Set(int v) { m_Value = v; }
+	int Get() const { return m_Value; }
+	CTuneParam &operator = (int v) { m_Value = (int)(v*100.0f); return *this; }
+	CTuneParam &operator = (float v) { m_Value = (int)(v*100.0f); return *this; }
+	operator float() const { return m_Value/100.0f; }
+};
+
+class CTuningParams
+{
+public:
+	CTuningParams()
+	{
+		const float TicksPerSecond = 50.0f;
+		#define MACRO_TUNING_PARAM(Name,ScriptName,Value) m_##Name.Set((int)(Value*100.0f));
+		#include "tuning.h"
+		#undef MACRO_TUNING_PARAM
+	}
+
+	static const char *m_apNames[];
+	
+	#define MACRO_TUNING_PARAM(Name,ScriptName,Value) CTuneParam m_##Name;
+	#include "tuning.h"
+	#undef MACRO_TUNING_PARAM
+	
+	static int Num() { return sizeof(CTuningParams)/sizeof(int); }
+	bool Set(int Index, float Value);
+	bool Set(const char *pName, float Value);
+	bool Get(int Index, float *pValue);
+	bool Get(const char *pName, float *pValue);
+};
+
+
+inline vec2 GetDirection(int Angle)
+{
+	float a = Angle/256.0f;
+	return vec2(cosf(a), sinf(a));
+}
+
+inline vec2 GetDir(float a)
+{
+	return vec2(cosf(a), sinf(a));
+}
+
+inline float GetAngle(vec2 Dir)
+{
+	if(Dir.x == 0 && Dir.y == 0)
+		return 0.0f;
+	float a = atanf(Dir.y/Dir.x);
+	if(Dir.x < 0)
+		a = a+pi;
+	return a;
+}
+
+inline void StrToInts(int *pInts, int Num, const char *pStr)
+{
+	int Index = 0;
+	while(Num)
+	{
+		char aBuf[4] = {0,0,0,0};
+		for(int c = 0; c < 4 && pStr[Index]; c++, Index++)
+			aBuf[c] = pStr[Index];
+		*pInts = ((aBuf[0]+128)<<24)|((aBuf[1]+128)<<16)|((aBuf[2]+128)<<8)|(aBuf[3]+128);
+		pInts++;
+		Num--;
+	}
+	
+	// null terminate
+	pInts[-1] &= 0xffffff00;
+}
+
+inline void IntsToStr(const int *pInts, int Num, char *pStr)
+{
+	while(Num)
+	{
+		pStr[0] = (((*pInts)>>24)&0xff)-128;
+		pStr[1] = (((*pInts)>>16)&0xff)-128;
+		pStr[2] = (((*pInts)>>8)&0xff)-128;
+		pStr[3] = ((*pInts)&0xff)-128;
+		pStr += 4;
+		pInts++;
+		Num--;
+	}
+	
+	// null terminate
+	pStr[-1] = 0;
+}
+
+
+
+inline vec2 CalcPos(vec2 p, vec2 v, float Curvature, float Speed, float t)
+{
+	vec2 n;
+	t *= Speed;
+	n.x = p.x + v.x*t;
+	n.y = p.y + v.y*t + Curvature/10000*(t*t);
+	return n;
+}
+
+
+template<typename T>
+inline T SaturatedAdd(T Min, T Max, T Current, T Modifier)
+{
+	if(Modifier < 0)
+	{
+		if(Current < Min)
+			return Current;
+		Current += Modifier;
+		if(Current < Min)
+			Current = Min;
+		return Current;
+	}
+	else
+	{
+		if(Current > Max)
+			return Current;
+		Current += Modifier;
+		if(Current > Max)
+			Current = Max;
+		return Current;
+	}
+}
+
+
+float VelocityRamp(float Value, float Start, float Range, float Curvature);
+
+// hooking stuff
+enum
+{
+	HOOK_RETRACTED=-1,
+	HOOK_IDLE=0,
+	HOOK_RETRACT_START=1,
+	HOOK_RETRACT_END=3,
+	HOOK_FLYING,
+	HOOK_GRABBED,
+	
+	COREEVENT_GROUND_JUMP=0x01,
+	COREEVENT_AIR_JUMP=0x02,
+	COREEVENT_HOOK_LAUNCH=0x04,
+	COREEVENT_HOOK_ATTACH_PLAYER=0x08,
+	COREEVENT_HOOK_ATTACH_GROUND=0x10,
+	COREEVENT_HOOK_HIT_NOHOOK=0x20,
+	COREEVENT_HOOK_RETRACT=0x40,
+};
+
+class CWorldCore
+{
+public:
+	CWorldCore()
+	{
+		mem_zero(m_apCharacters, sizeof(m_apCharacters));
+	}
+	
+	CTuningParams m_Tuning;
+	class CCharacterCore *m_apCharacters[MAX_CLIENTS];
+};
+
+class CCharacterCore
+{
+	CWorldCore *m_pWorld;
+	CCollision *m_pCollision;
+public:
+	vec2 m_Pos;
+	vec2 m_Vel;
+	
+	vec2 m_HookPos;
+	vec2 m_HookDir;
+	int m_HookTick;
+	int m_HookState;
+	int m_HookedPlayer;
+	
+	int m_Jumped;
+	
+	int m_Direction;
+	int m_Angle;
+	CNetObj_PlayerInput m_Input;
+	
+	int m_TriggeredEvents;
+	
+	void Init(CWorldCore *pWorld, CCollision *pCollision);
+	void Reset();
+	void Tick(bool UseInput);
+	void Move();
+	
+	void Read(const CNetObj_CharacterCore *pObjCore);
+	void Write(CNetObj_CharacterCore *pObjCore);
+	void Quantize();
+};
+
+#endif
diff --git a/src/game/gamecore.hpp b/src/game/gamecore.hpp
deleted file mode 100644
index 2734820c..00000000
--- a/src/game/gamecore.hpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef GAME_GAME_H
-#define GAME_GAME_H
-
-#include <base/system.h>
-#include <base/math.hpp>
-
-#include <engine/e_common_interface.h>
-#include <math.h>
-#include "collision.hpp"
-#include <game/generated/g_protocol.hpp>
-
-struct TUNING_PARAMS
-{
-	TUNING_PARAMS()
-	{
-		const float ticks_per_second = 50.0f;
-		#define MACRO_TUNING_PARAM(name,value) name.set((int)(value*100.0f));
-		#include "tuning.hpp"
-		#undef MACRO_TUNING_PARAM
-	}
-
-	static const char *names[];
-	
-	#define MACRO_TUNING_PARAM(name,value) tune_param name;
-	#include "tuning.hpp"
-	#undef MACRO_TUNING_PARAM
-	
-	static int num() { return sizeof(TUNING_PARAMS)/sizeof(int); }
-	bool set(int index, float value);
-	bool set(const char *name, float value);
-	bool get(int index, float *value);
-	bool get(const char *name, float *value);
-};
-
-
-inline vec2 get_direction(int angle)
-{
-	float a = angle/256.0f;
-	return vec2(cosf(a), sinf(a));
-}
-
-inline vec2 get_dir(float a)
-{
-	return vec2(cosf(a), sinf(a));
-}
-
-inline float get_angle(vec2 dir)
-{
-	float a = atan(dir.y/dir.x);
-	if(dir.x < 0)
-		a = a+pi;
-	return a;
-}
-
-inline void str_to_ints(int *ints, int num, const char *str)
-{
-	int index = 0;
-	while(num)
-	{
-		char buf[4] = {0,0,0,0};
-		for(int c = 0; c < 4 && str[index]; c++, index++)
-			buf[c] = str[index];
-		*ints = ((buf[0]+128)<<24)|((buf[1]+128)<<16)|((buf[2]+128)<<8)|(buf[3]+128);
-		ints++;
-		num--;
-	}
-	
-	// null terminate
-	ints[-1] &= 0xffffff00;
-}
-
-inline void ints_to_str(const int *ints, int num, char *str)
-{
-	while(num)
-	{
-		str[0] = (((*ints)>>24)&0xff)-128;
-		str[1] = (((*ints)>>16)&0xff)-128;
-		str[2] = (((*ints)>>8)&0xff)-128;
-		str[3] = ((*ints)&0xff)-128;
-		str += 4;
-		ints++;
-		num--;
-	}
-	
-	// null terminate
-	str[-1] = 0;
-}
-
-
-
-inline vec2 calc_pos(vec2 p, vec2 v, float curvature, float speed, float t)
-{
-	vec2 n;
-	t *= speed;
-	n.x = p.x + v.x*t;
-	n.y = p.y + v.y*t + curvature/10000*(t*t);
-	return n;
-}
-
-
-template<typename T>
-inline T saturated_add(T min, T max, T current, T modifier)
-{
-	if(modifier < 0)
-	{
-		if(current < min)
-			return current;
-		current += modifier;
-		if(current < min)
-			current = min;
-		return current;
-	}
-	else
-	{
-		if(current > max)
-			return current;
-		current += modifier;
-		if(current > max)
-			current = max;
-		return current;
-	}
-}
-
-void move_point(vec2 *inout_pos, vec2 *inout_vel, float elasticity, int *bounces);
-void move_box(vec2 *inout_pos, vec2 *inout_vel, vec2 size, float elasticity);
-bool test_box(vec2 pos, vec2 size);
-float velocity_ramp(float value, float start, float range, float curvature);
-
-// hooking stuff
-enum
-{
-	HOOK_RETRACTED=-1,
-	HOOK_IDLE=0,
-	HOOK_RETRACT_START=1,
-	HOOK_RETRACT_END=3,
-	HOOK_FLYING,
-	HOOK_GRABBED,
-	
-	COREEVENT_GROUND_JUMP=0x01,
-	COREEVENT_AIR_JUMP=0x02,
-	COREEVENT_HOOK_LAUNCH=0x04,
-	COREEVENT_HOOK_ATTACH_PLAYER=0x08,
-	COREEVENT_HOOK_ATTACH_GROUND=0x10,
-	COREEVENT_HOOK_HIT_NOHOOK=0x20,
-	COREEVENT_HOOK_RETRACT=0x40,
-};
-
-class WORLD_CORE
-{
-public:
-	WORLD_CORE()
-	{
-		mem_zero(characters, sizeof(characters));
-	}
-	
-	TUNING_PARAMS tuning;
-	class CHARACTER_CORE *characters[MAX_CLIENTS];
-};
-
-class CHARACTER_CORE
-{
-public:
-	WORLD_CORE *world;
-	
-	vec2 pos;
-	vec2 vel;
-	
-	vec2 hook_pos;
-	vec2 hook_dir;
-	int hook_tick;
-	int hook_state;
-	int hooked_player;
-	
-	int jumped;
-	
-	int direction;
-	int angle;
-	NETOBJ_PLAYER_INPUT input;
-	
-	int triggered_events;
-	
-	void reset();
-	void tick(bool use_input);
-	void move();
-	
-	void read(const NETOBJ_CHARACTER_CORE *obj_core);
-	void write(NETOBJ_CHARACTER_CORE *obj_core);
-	void quantize();
-};
-
-
-#define LERP(a,b,t) (a + (b-a) * t)
-#define min(a, b) ( a > b ? b : a)
-#define max(a, b) ( a > b ? a : b)
-
-inline bool col_check_point(float x, float y) { return col_is_solid(round(x), round(y)) != 0; }
-inline bool col_check_point(vec2 p) { return col_check_point(p.x, p.y); }
-
-#endif
diff --git a/src/game/layers.cpp b/src/game/layers.cpp
index 832dc766..e99befd2 100644
--- a/src/game/layers.cpp
+++ b/src/game/layers.cpp
@@ -1,57 +1,61 @@
-#include <engine/e_common_interface.h>
-#include "layers.hpp"
+#include "layers.h"
 
-static MAPITEM_LAYER_TILEMAP *game_layer = 0;
-static MAPITEM_GROUP *game_group = 0;
-
-static int groups_start = 0;
-static int groups_num = 0;
-static int layers_start = 0;
-static int layers_num = 0;
+CLayers::CLayers()
+{
+	m_GroupsNum = 0;
+	m_GroupsStart = 0;
+	m_LayersNum = 0;
+	m_LayersStart = 0;
+	m_pGameGroup = 0;
+	m_pGameLayer = 0;
+	m_pMap = 0;
+}
 
-void layers_init()
+void CLayers::Init(class IKernel *pKernel)
 {
-	map_get_type(MAPITEMTYPE_GROUP, &groups_start, &groups_num);
-	map_get_type(MAPITEMTYPE_LAYER, &layers_start, &layers_num);
+	m_pMap = pKernel->RequestInterface<IMap>();
+	m_pMap->GetType(MAPITEMTYPE_GROUP, &m_GroupsStart, &m_GroupsNum);
+	m_pMap->GetType(MAPITEMTYPE_LAYER, &m_LayersStart, &m_LayersNum);
 	
-	for(int g = 0; g < layers_num_groups(); g++)
+	for(int g = 0; g < NumGroups(); g++)
 	{
-		MAPITEM_GROUP *group = layers_get_group(g);
-		for(int l = 0; l < group->num_layers; l++)
+		CMapItemGroup *pGroup = GetGroup(g);
+		for(int l = 0; l < pGroup->m_NumLayers; l++)
 		{
-			MAPITEM_LAYER *layer = layers_get_layer(group->start_layer+l);
+			CMapItemLayer *pLayer = GetLayer(pGroup->m_StartLayer+l);
 			
-			if(layer->type == LAYERTYPE_TILES)
+			if(pLayer->m_Type == LAYERTYPE_TILES)
 			{
-				MAPITEM_LAYER_TILEMAP *tilemap = (MAPITEM_LAYER_TILEMAP *)layer;
-				if(tilemap->flags&1)
+				CMapItemLayerTilemap *pTilemap = reinterpret_cast<CMapItemLayerTilemap *>(pLayer);
+				if(pTilemap->m_Flags&1)
 				{
-					game_layer = tilemap;
-					game_group = group;
+					m_pGameLayer = pTilemap;
+					m_pGameGroup = pGroup;
+
+					// make sure the game group has standard settings
+					m_pGameGroup->m_OffsetX = 0;
+					m_pGameGroup->m_OffsetY = 0;
+					m_pGameGroup->m_ParallaxX = 100;
+					m_pGameGroup->m_ParallaxY = 100;
+					m_pGameGroup->m_UseClipping = 0;
+					m_pGameGroup->m_ClipX = 0;
+					m_pGameGroup->m_ClipY = 0;
+					m_pGameGroup->m_ClipW = 0;
+					m_pGameGroup->m_ClipH = 0;
+
+					break;
 				}
 			}			
 		}
 	}
 }
 
-int layers_num_groups() { return groups_num; }
-MAPITEM_GROUP *layers_get_group(int index)
-{
-	return (MAPITEM_GROUP *)map_get_item(groups_start+index, 0, 0);
-}
-
-MAPITEM_LAYER *layers_get_layer(int index)
+CMapItemGroup *CLayers::GetGroup(int Index) const
 {
-	return (MAPITEM_LAYER *)map_get_item(layers_start+index, 0, 0);
+	return static_cast<CMapItemGroup *>(m_pMap->GetItem(m_GroupsStart+Index, 0, 0));
 }
 
-MAPITEM_LAYER_TILEMAP *layers_game_layer()
+CMapItemLayer *CLayers::GetLayer(int Index) const
 {
-	return game_layer;
+	return static_cast<CMapItemLayer *>(m_pMap->GetItem(m_LayersStart+Index, 0, 0));
 }
-
-MAPITEM_GROUP *layers_game_group()
-{
-	return game_group;
-}
-
diff --git a/src/game/layers.h b/src/game/layers.h
new file mode 100644
index 00000000..198fe695
--- /dev/null
+++ b/src/game/layers.h
@@ -0,0 +1,28 @@
+#ifndef GAME_LAYERS_H
+#define GAME_LAYERS_H
+
+#include <engine/map.h>
+#include <game/mapitems.h>
+
+class CLayers
+{
+	int m_GroupsNum;
+	int m_GroupsStart;
+	int m_LayersNum;
+	int m_LayersStart;
+	CMapItemGroup *m_pGameGroup;
+	CMapItemLayerTilemap *m_pGameLayer;
+	class IMap *m_pMap;
+
+public:
+	CLayers();
+	void Init(class IKernel *pKernel);
+	int NumGroups() const { return m_GroupsNum; };
+	class IMap *Map() const { return m_pMap; };
+	CMapItemGroup *GameGroup() const { return m_pGameGroup; };
+	CMapItemLayerTilemap *GameLayer() const { return m_pGameLayer; };
+	CMapItemGroup *GetGroup(int Index) const;
+	CMapItemLayer *GetLayer(int Index) const;	
+};
+
+#endif
diff --git a/src/game/layers.hpp b/src/game/layers.hpp
deleted file mode 100644
index cb18419b..00000000
--- a/src/game/layers.hpp
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "mapitems.hpp"
-
-void layers_init();
-
-MAPITEM_LAYER_TILEMAP *layers_game_layer();
-MAPITEM_GROUP *layers_game_group();
-
-int layers_num_groups();
-MAPITEM_GROUP *layers_get_group(int index);
-MAPITEM_LAYER *layers_get_layer(int index);
-
-
diff --git a/src/game/localization.cpp b/src/game/localization.cpp
index 3a1b0411..02065e36 100644
--- a/src/game/localization.cpp
+++ b/src/game/localization.cpp
@@ -1,100 +1,101 @@
 
-#include "localization.hpp"
-#include <base/tl/algorithm.hpp>
+#include "localization.h"
+#include <base/tl/algorithm.h>
 
-#include <engine/e_linereader.h>
+#include <engine/shared/linereader.h>
 
-const char *localize(const char *str)
+const char *Localize(const char *pStr)
 {
-	const char *new_str = localization.find_string(str_quickhash(str));
-	return new_str ? new_str : str;
+	const char *pNewStr = g_Localization.FindString(str_quickhash(pStr));
+	return pNewStr ? pNewStr : pStr;
 }
 
-LOC_CONSTSTRING::LOC_CONSTSTRING(const char *str)
+CLocConstString::CLocConstString(const char *pStr)
 {
-	default_str = str;
-	hash = str_quickhash(default_str);
-	version = -1;
+	m_pDefaultStr = pStr;
+	m_Hash = str_quickhash(m_pDefaultStr);
+	m_Version = -1;
 }
 
-void LOC_CONSTSTRING::reload()
+void CLocConstString::Reload()
 {
-	version = localization.version();
-	const char *new_str = localization.find_string(hash);
-	current_str = new_str;
-	if(!current_str)
-		current_str = default_str;
+	m_Version = g_Localization.Version();
+	const char *pNewStr = g_Localization.FindString(m_Hash);
+	m_pCurrentStr = pNewStr;
+	if(!m_pCurrentStr)
+		m_pCurrentStr = m_pDefaultStr;
 }
 
-LOCALIZATIONDATABASE::LOCALIZATIONDATABASE()
+CLocalizationDatabase::CLocalizationDatabase()
 {
-	current_version = 0;
+	m_CurrentVersion = 0;
 }
 
-void LOCALIZATIONDATABASE::add_string(const char *org_str, const char *new_str)
+void CLocalizationDatabase::AddString(const char *pOrgStr, const char *pNewStr)
 {
-	STRING s;
-	s.hash = str_quickhash(org_str);
-	s.replacement = new_str;
-	strings.add(s);
+	CString s;
+	s.m_Hash = str_quickhash(pOrgStr);
+	s.m_Replacement = pNewStr;
+	m_Strings.add(s);
 }
 
-bool LOCALIZATIONDATABASE::load(const char *filename)
+bool CLocalizationDatabase::Load(const char *pFilename)
 {
 	// empty string means unload
-	if(filename[0] == 0)
+	if(pFilename[0] == 0)
 	{
-		strings.clear();
+		m_Strings.clear();
+		m_CurrentVersion = 0;
 		return true;
 	}
 	
-	LINEREADER lr;
-	IOHANDLE io = io_open(filename, IOFLAG_READ);
-	if(!io)
+	IOHANDLE IoHandle = io_open(pFilename, IOFLAG_READ);
+	if(!IoHandle)
 		return false;
 	
-	dbg_msg("localization", "loaded '%s'", filename);
-	strings.clear();
+	dbg_msg("localization", "loaded '%s'", pFilename);
+	m_Strings.clear();
 	
-	linereader_init(&lr, io);
-	char *line;
-	while((line = linereader_get(&lr)))
+	CLineReader LineReader;
+	LineReader.Init(IoHandle);
+	char *pLine;
+	while((pLine = LineReader.Get()))
 	{
-		if(!str_length(line))
+		if(!str_length(pLine))
 			continue;
 			
-		if(line[0] == '#') // skip comments
+		if(pLine[0] == '#') // skip comments
 			continue;
 			
-		char *replacement = linereader_get(&lr);
-		if(!replacement)
+		char *pReplacement = LineReader.Get();
+		if(!pReplacement)
 		{
 			dbg_msg("", "unexpected end of file");
 			break;
 		}
 		
-		if(replacement[0] != '=' || replacement[1] != '=' || replacement[2] != ' ')
+		if(pReplacement[0] != '=' || pReplacement[1] != '=' || pReplacement[2] != ' ')
 		{
-			dbg_msg("", "malform replacement line for '%s'", line);
+			dbg_msg("", "malform replacement line for '%s'", pLine);
 			continue;
 		}
 
-		replacement += 3;
-		localization.add_string(line, replacement);
+		pReplacement += 3;
+		AddString(pLine, pReplacement);
 	}
 	
-	current_version++;
+	m_CurrentVersion++;
 	return true;
 }
 
-const char *LOCALIZATIONDATABASE::find_string(unsigned hash)
+const char *CLocalizationDatabase::FindString(unsigned Hash)
 {
-	STRING s;
-	s.hash = hash;
-	sorted_array<STRING>::range r = ::find_binary(strings.all(), s);
+	CString String;
+	String.m_Hash = Hash;
+	sorted_array<CString>::range r = ::find_binary(m_Strings.all(), String);
 	if(r.empty())
 		return 0;
-	return r.front().replacement;
+	return r.front().m_Replacement;
 }
 
-LOCALIZATIONDATABASE localization;
+CLocalizationDatabase g_Localization;
diff --git a/src/game/localization.h b/src/game/localization.h
new file mode 100644
index 00000000..2e96ef04
--- /dev/null
+++ b/src/game/localization.h
@@ -0,0 +1,57 @@
+#ifndef GAME_LOCALIZATION_H
+#define GAME_LOCALIZATION_H
+#include <base/tl/string.h>
+#include <base/tl/sorted_array.h>
+
+class CLocalizationDatabase
+{
+	class CString
+	{
+	public:
+		unsigned m_Hash;
+		
+		// TODO: do this as an const char * and put everything on a incremental heap
+		string m_Replacement;
+
+		bool operator <(const CString &Other) const { return m_Hash < Other.m_Hash; }
+		bool operator <=(const CString &Other) const { return m_Hash <= Other.m_Hash; }
+		bool operator ==(const CString &Other) const { return m_Hash == Other.m_Hash; }
+	};
+
+	sorted_array<CString> m_Strings;
+	int m_CurrentVersion;
+	
+public:
+	CLocalizationDatabase();
+
+	bool Load(const char *pFilename);
+
+	int Version() { return m_CurrentVersion; }
+	
+	void AddString(const char *pOrgStr, const char *pNewStr);
+	const char *FindString(unsigned Hash);
+};
+
+extern CLocalizationDatabase g_Localization;
+
+class CLocConstString
+{
+	const char *m_pDefaultStr;
+	const char *m_pCurrentStr;
+	unsigned m_Hash;
+	int m_Version;
+public:
+	CLocConstString(const char *pStr);
+	void Reload();
+	
+	inline operator const char *()
+	{
+		if(m_Version != g_Localization.Version())
+			Reload();
+		return m_pCurrentStr;
+	}
+};
+
+
+extern const char *Localize(const char *pStr);
+#endif
diff --git a/src/game/localization.hpp b/src/game/localization.hpp
deleted file mode 100644
index 3f79d687..00000000
--- a/src/game/localization.hpp
+++ /dev/null
@@ -1,54 +0,0 @@
-#include <base/tl/string.hpp>
-#include <base/tl/sorted_array.hpp>
-
-class LOCALIZATIONDATABASE
-{
-	class STRING
-	{
-	public:
-		unsigned hash;
-		
-		// TODO: do this as an const char * and put everything on a incremental heap
-		string replacement;
-
-		bool operator <(const STRING &other) const { return hash < other.hash; }
-		bool operator <=(const STRING &other) const { return hash <= other.hash; }
-		bool operator ==(const STRING &other) const { return hash == other.hash; }
-	};
-
-	sorted_array<STRING> strings;
-	int current_version;
-	
-public:
-	LOCALIZATIONDATABASE();
-
-	bool load(const char *filename);
-
-	int version() { return current_version; }
-	
-	void add_string(const char *org_str, const char *new_str);
-	const char *find_string(unsigned hash);
-};
-
-extern LOCALIZATIONDATABASE localization;
-
-class LOC_CONSTSTRING
-{
-	const char *default_str;
-	const char *current_str;
-	unsigned hash;
-	int version;
-public:
-	LOC_CONSTSTRING(const char *str);
-	void reload();
-	
-	inline operator const char *()
-	{
-		if(version != localization.version())
-			reload();
-		return current_str;
-	}
-};
-
-
-extern const char *localize(const char *str);
diff --git a/src/game/mapitems.h b/src/game/mapitems.h
new file mode 100644
index 00000000..efbd96f2
--- /dev/null
+++ b/src/game/mapitems.h
@@ -0,0 +1,179 @@
+#ifndef GAME_MAPITEMS_H
+#define GAME_MAPITEMS_H
+
+// layer types
+enum
+{
+	LAYERTYPE_INVALID=0,
+	LAYERTYPE_GAME, // not used
+	LAYERTYPE_TILES,
+	LAYERTYPE_QUADS,
+	
+	MAPITEMTYPE_VERSION=0,
+	MAPITEMTYPE_INFO,
+	MAPITEMTYPE_IMAGE,
+	MAPITEMTYPE_ENVELOPE,
+	MAPITEMTYPE_GROUP,
+	MAPITEMTYPE_LAYER,
+	MAPITEMTYPE_ENVPOINTS,
+	
+
+	CURVETYPE_STEP=0,
+	CURVETYPE_LINEAR,
+	CURVETYPE_SLOW,
+	CURVETYPE_FAST,
+	CURVETYPE_SMOOTH,
+	NUM_CURVETYPES,
+	
+	// game layer tiles
+	ENTITY_NULL=0,
+	ENTITY_SPAWN,
+	ENTITY_SPAWN_RED,
+	ENTITY_SPAWN_BLUE,
+	ENTITY_FLAGSTAND_RED,
+	ENTITY_FLAGSTAND_BLUE,
+	ENTITY_ARMOR_1,
+	ENTITY_HEALTH_1,
+	ENTITY_WEAPON_SHOTGUN,
+	ENTITY_WEAPON_GRENADE,
+	ENTITY_POWERUP_NINJA,
+	ENTITY_WEAPON_RIFLE,
+	NUM_ENTITIES,
+	
+	TILE_AIR=0,
+	TILE_SOLID,
+	TILE_DEATH,
+	TILE_NOHOOK,
+	
+	TILEFLAG_VFLIP=1,
+	TILEFLAG_HFLIP=2,
+	TILEFLAG_OPAQUE=4,
+	
+	LAYERFLAG_DETAIL=1,
+	
+	ENTITY_OFFSET=255-16*4,
+};
+
+struct CPoint
+{
+	int x, y; // 22.10 fixed point
+};
+
+struct CColor
+{
+	int r, g, b, a;
+};
+
+struct CQuad
+{
+	CPoint m_aPoints[5];
+	CColor m_aColors[4];
+	CPoint m_aTexcoords[4];
+	
+	int m_PosEnv;
+	int m_PosEnvOffset;
+	
+	int m_ColorEnv;
+	int m_ColorEnvOffset;
+};
+
+struct CTile
+{
+	unsigned char m_Index;
+	unsigned char m_Flags;
+	unsigned char m_Skip;
+	unsigned char m_Reserved;
+};
+
+struct CMapItemImage
+{
+	int m_Version;
+	int m_Width;
+	int m_Height;
+	int m_External;
+	int m_ImageName;
+	int m_ImageData;
+} ;
+
+struct CMapItemGroup_v1
+{
+	int m_Version;
+	int m_OffsetX;
+	int m_OffsetY;
+	int m_ParallaxX;
+	int m_ParallaxY;
+
+	int m_StartLayer;
+	int m_NumLayers;
+} ;
+
+
+struct CMapItemGroup : public CMapItemGroup_v1
+{
+	enum { CURRENT_VERSION=2 };
+	
+	int m_UseClipping;
+	int m_ClipX;
+	int m_ClipY;
+	int m_ClipW;
+	int m_ClipH;
+} ;
+
+struct CMapItemLayer
+{
+	int m_Version;
+	int m_Type;
+	int m_Flags;
+} ;
+
+struct CMapItemLayerTilemap
+{
+	CMapItemLayer m_Layer;
+	int m_Version;
+	
+	int m_Width;
+	int m_Height;
+	int m_Flags;
+	
+	CColor m_Color;
+	int m_ColorEnv;
+	int m_ColorEnvOffset;
+	
+	int m_Image;
+	int m_Data;
+} ;
+
+struct CMapItemLayerQuads
+{
+	CMapItemLayer m_Layer;
+	int m_Version;
+	
+	int m_NumQuads;
+	int m_Data;
+	int m_Image;
+} ;
+
+struct CMapItemVersion
+{
+	int m_Version;
+} ;
+
+struct CEnvPoint
+{
+	int m_Time; // in ms
+	int m_Curvetype;
+	int m_aValues[4]; // 1-4 depending on envelope (22.10 fixed point)
+	
+	bool operator<(const CEnvPoint &Other) { return m_Time < Other.m_Time; }
+} ;
+
+struct CMapItemEnvelope
+{
+	int m_Version;
+	int m_Channels;
+	int m_StartPoint;
+	int m_NumPoints;
+	int m_Name;
+} ;
+
+#endif
diff --git a/src/game/mapitems.hpp b/src/game/mapitems.hpp
deleted file mode 100644
index 9c9936d2..00000000
--- a/src/game/mapitems.hpp
+++ /dev/null
@@ -1,178 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#ifndef GAME_MAPITEMS_H
-#define GAME_MAPITEMS_H
-
-// layer types
-enum
-{
-	LAYERTYPE_INVALID=0,
-	LAYERTYPE_GAME, // not used
-	LAYERTYPE_TILES,
-	LAYERTYPE_QUADS,
-	
-	MAPITEMTYPE_VERSION=0,
-	MAPITEMTYPE_INFO,
-	MAPITEMTYPE_IMAGE,
-	MAPITEMTYPE_ENVELOPE,
-	MAPITEMTYPE_GROUP,
-	MAPITEMTYPE_LAYER,
-	MAPITEMTYPE_ENVPOINTS,
-	
-
-	CURVETYPE_STEP=0,
-	CURVETYPE_LINEAR,
-	CURVETYPE_SLOW,
-	CURVETYPE_FAST,
-	CURVETYPE_SMOOTH,
-	NUM_CURVETYPES,
-	
-	// game layer tiles
-	ENTITY_NULL=0,
-	ENTITY_SPAWN,
-	ENTITY_SPAWN_RED,
-	ENTITY_SPAWN_BLUE,
-	ENTITY_FLAGSTAND_RED,
-	ENTITY_FLAGSTAND_BLUE,
-	ENTITY_ARMOR_1,
-	ENTITY_HEALTH_1,
-	ENTITY_WEAPON_SHOTGUN,
-	ENTITY_WEAPON_GRENADE,
-	ENTITY_POWERUP_NINJA,
-	ENTITY_WEAPON_RIFLE,
-	NUM_ENTITIES,
-	
-	TILE_AIR=0,
-	TILE_SOLID,
-	TILE_DEATH,
-	TILE_NOHOOK,
-	
-	TILEFLAG_VFLIP=1,
-	TILEFLAG_HFLIP=2,
-	TILEFLAG_OPAQUE=4,
-	
-	LAYERFLAG_DETAIL=1,
-	
-	ENTITY_OFFSET=255-16*4,
-};
-
-typedef struct
-{
-	int x, y; // 22.10 fixed point
-} POINT;
-
-typedef struct
-{
-	int r, g, b, a;
-} COLOR;
-
-typedef struct
-{
-	POINT points[5];
-	COLOR colors[4];
-	POINT texcoords[4];
-	
-	int pos_env;
-	int pos_env_offset;
-	
-	int color_env;
-	int color_env_offset;
-} QUAD;
-
-typedef struct
-{
-	unsigned char index;
-	unsigned char flags;
-	unsigned char skip;
-	unsigned char reserved;
-} TILE;
-
-typedef struct 
-{
-	int version;
-	int width;
-	int height;
-	int external;
-	int image_name;
-	int image_data;
-} MAPITEM_IMAGE;
-
-struct MAPITEM_GROUP_v1
-{
-	int version;
-	int offset_x;
-	int offset_y;
-	int parallax_x;
-	int parallax_y;
-
-	int start_layer;
-	int num_layers;
-} ;
-
-
-struct MAPITEM_GROUP : public MAPITEM_GROUP_v1
-{
-	enum { CURRENT_VERSION=2 };
-	
-	int use_clipping;
-	int clip_x;
-	int clip_y;
-	int clip_w;
-	int clip_h;
-} ;
-
-typedef struct
-{
-	int version;
-	int type;
-	int flags;
-} MAPITEM_LAYER;
-
-typedef struct
-{
-	MAPITEM_LAYER layer;
-	int version;
-	
-	int width;
-	int height;
-	int flags;
-	
-	COLOR color;
-	int color_env;
-	int color_env_offset;
-	
-	int image;
-	int data;
-} MAPITEM_LAYER_TILEMAP;
-
-typedef struct
-{
-	MAPITEM_LAYER layer;
-	int version;
-	
-	int num_quads;
-	int data;
-	int image;
-} MAPITEM_LAYER_QUADS;
-
-typedef struct
-{
-	int version;
-} MAPITEM_VERSION;
-
-typedef struct
-{
-	int time; // in ms
-	int curvetype;
-	int values[4]; // 1-4 depending on envelope (22.10 fixed point)
-} ENVPOINT;
-
-typedef struct
-{
-	int version;
-	int channels;
-	int start_point;
-	int num_points;
-	int name;
-} MAPITEM_ENVELOPE;
-
-#endif
diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp
index 8ba91a80..839088dd 100644
--- a/src/game/server/entities/character.cpp
+++ b/src/game/server/entities/character.cpp
@@ -1,838 +1,820 @@
 #include <new>
-#include <engine/e_server_interface.h>
-#include <engine/e_config.h>
-#include <game/server/gamecontext.hpp>
-#include <game/mapitems.hpp>
+#include <engine/shared/config.h>
+#include <game/server/gamecontext.h>
+#include <game/mapitems.h>
 
-#include "character.hpp"
-#include "laser.hpp"
-#include "projectile.hpp"
+#include "character.h"
+#include "laser.h"
+#include "projectile.h"
 
-struct INPUT_COUNT
+//input count
+struct CInputCount
 {
-	int presses;
-	int releases;
+	int m_Presses;
+	int m_Releases;
 };
 
-static INPUT_COUNT count_input(int prev, int cur)
+CInputCount CountInput(int Prev, int Cur)
 {
-	INPUT_COUNT c = {0,0};
-	prev &= INPUT_STATE_MASK;
-	cur &= INPUT_STATE_MASK;
-	int i = prev;
-	while(i != cur)
+	CInputCount c = {0, 0};
+	Prev &= INPUT_STATE_MASK;
+	Cur &= INPUT_STATE_MASK;
+	int i = Prev;
+	
+	while(i != Cur)
 	{
 		i = (i+1)&INPUT_STATE_MASK;
 		if(i&1)
-			c.presses++;
+			c.m_Presses++;
 		else
-			c.releases++;
+			c.m_Releases++;
 	}
 
 	return c;
 }
 
 
-MACRO_ALLOC_POOL_ID_IMPL(CHARACTER, MAX_CLIENTS)
+MACRO_ALLOC_POOL_ID_IMPL(CCharacter, MAX_CLIENTS)
 
-// player
-CHARACTER::CHARACTER()
-: ENTITY(NETOBJTYPE_CHARACTER)
+// Character, "physical" player's part
+CCharacter::CCharacter(CGameWorld *pWorld)
+: CEntity(pWorld, NETOBJTYPE_CHARACTER)
 {
-	proximity_radius = phys_size;
+	m_ProximityRadius = g_CharPhysSize;
+	m_Health = 0;
+	m_Armor = 0;
 }
 
-void CHARACTER::reset()
+void CCharacter::Reset()
 {
-	destroy();
+	Destroy();
 }
 
-bool CHARACTER::spawn(PLAYER *player, vec2 pos, int team)
+bool CCharacter::Spawn(CPlayer *pPlayer, vec2 Pos)
 {
-	player_state = PLAYERSTATE_UNKNOWN;
-	emote_stop = -1;
-	last_action = -1;
-	active_weapon = WEAPON_GUN;
-	last_weapon = WEAPON_HAMMER;
-	queued_weapon = -1;
+	m_PlayerState = PLAYERSTATE_UNKNOWN;
+	m_EmoteStop = -1;
+	m_LastAction = -1;
+	m_ActiveWeapon = WEAPON_GUN;
+	m_LastWeapon = WEAPON_HAMMER;
+	m_QueuedWeapon = -1;
 	
-	//clear();
-	this->player = player;
-	this->pos = pos;
-	this->team = team;
+	m_pPlayer = pPlayer;
+	m_Pos = Pos;
 	
-	core.reset();
-	core.world = &game.world.core;
-	core.pos = pos;
-	game.world.core.characters[player->client_id] = &core;
-
-	reckoning_tick = 0;
-	mem_zero(&sendcore, sizeof(sendcore));
-	mem_zero(&reckoningcore, sizeof(reckoningcore));
+	m_Core.Reset();
+	m_Core.Init(&GameServer()->m_World.m_Core, GameServer()->Collision());
+	m_Core.m_Pos = m_Pos;
+	GameServer()->m_World.m_Core.m_apCharacters[m_pPlayer->GetCID()] = &m_Core;
+
+	m_ReckoningTick = 0;
+	mem_zero(&m_SendCore, sizeof(m_SendCore));
+	mem_zero(&m_ReckoningCore, sizeof(m_ReckoningCore));
 	
-	game.world.insert_entity(this);
-	alive = true;
-	player->force_balanced = false;
+	GameServer()->m_World.InsertEntity(this);
+	m_Alive = true;
 
-	game.controller->on_character_spawn(this);
+	GameServer()->m_pController->OnCharacterSpawn(this);
 
 	return true;
 }
 
-void CHARACTER::destroy()
+void CCharacter::Destroy()
 {
-	game.world.core.characters[player->client_id] = 0;
-	alive = false;
+	GameServer()->m_World.m_Core.m_apCharacters[m_pPlayer->GetCID()] = 0;
+	m_Alive = false;
 }
 
-void CHARACTER::set_weapon(int w)
+void CCharacter::SetWeapon(int W)
 {
-	if(w == active_weapon)
+	if(W == m_ActiveWeapon)
 		return;
 		
-	last_weapon = active_weapon;
-	queued_weapon = -1;
-	active_weapon = w;
-	if(active_weapon < 0 || active_weapon >= NUM_WEAPONS)
-		active_weapon = 0;
+	m_LastWeapon = m_ActiveWeapon;
+	m_QueuedWeapon = -1;
+	m_ActiveWeapon = W;
+	GameServer()->CreateSound(m_Pos, SOUND_WEAPON_SWITCH);
 	
-	game.create_sound(pos, SOUND_WEAPON_SWITCH);
+	if(m_ActiveWeapon < 0 || m_ActiveWeapon >= NUM_WEAPONS)
+		m_ActiveWeapon = 0;
 }
 
-bool CHARACTER::is_grounded()
+bool CCharacter::IsGrounded()
 {
-	if(col_check_point((int)(pos.x+phys_size/2), (int)(pos.y+phys_size/2+5)))
+	if(GameServer()->Collision()->CheckPoint(m_Pos.x+g_CharPhysSize/2, m_Pos.y+g_CharPhysSize/2+5))
 		return true;
-	if(col_check_point((int)(pos.x-phys_size/2), (int)(pos.y+phys_size/2+5)))
+	if(GameServer()->Collision()->CheckPoint(m_Pos.x-g_CharPhysSize/2, m_Pos.y+g_CharPhysSize/2+5))
 		return true;
 	return false;
 }
 
 
-int CHARACTER::handle_ninja()
+void CCharacter::HandleNinja()
 {
-	if(active_weapon != WEAPON_NINJA)
-		return 0;
+	if(m_ActiveWeapon != WEAPON_NINJA)
+		return;
 	
-	vec2 direction = normalize(vec2(latest_input.target_x, latest_input.target_y));
+	vec2 Direction = normalize(vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY));
 
-	if ((server_tick() - ninja.activationtick) > (data->weapons.ninja.duration * server_tickspeed() / 1000))
+	if ((Server()->Tick() - m_Ninja.m_ActivationTick) > (g_pData->m_Weapons.m_Ninja.m_Duration * Server()->TickSpeed() / 1000))
 	{
 		// time's up, return
-		weapons[WEAPON_NINJA].got = false;
-		active_weapon = last_weapon;
-		if(active_weapon == WEAPON_NINJA)
-			active_weapon = WEAPON_GUN;
-		set_weapon(active_weapon);
-		return 0;
+		m_aWeapons[WEAPON_NINJA].m_Got = false;
+		m_ActiveWeapon = m_LastWeapon;
+		if(m_ActiveWeapon == WEAPON_NINJA)
+			m_ActiveWeapon = WEAPON_GUN;
+			
+		SetWeapon(m_ActiveWeapon);
+		return;
 	}
 	
-	// force ninja weapon
-	set_weapon(WEAPON_NINJA);
+	// force ninja Weapon
+	SetWeapon(WEAPON_NINJA);
 
-	ninja.currentmovetime--;
+	m_Ninja.m_CurrentMoveTime--;
 
-	if (ninja.currentmovetime == 0)
+	if (m_Ninja.m_CurrentMoveTime == 0)
 	{
-		// reset player velocity
-		core.vel *= 0.2f;
-		//return MODIFIER_RETURNFLAGS_OVERRIDEWEAPON;
+		// reset velocity
+		m_Core.m_Vel *= 0.2f;
 	}
 
-	if (ninja.currentmovetime > 0)
+	if (m_Ninja.m_CurrentMoveTime > 0)
 	{
-		// Set player velocity
-		core.vel = ninja.activationdir * data->weapons.ninja.velocity;
-		vec2 oldpos = pos;
-		move_box(&core.pos, &core.vel, vec2(phys_size, phys_size), 0.0f);
+		// Set velocity
+		m_Core.m_Vel = m_Ninja.m_ActivationDir * g_pData->m_Weapons.m_Ninja.m_Velocity;
+		vec2 OldPos = m_Pos;
+		GameServer()->Collision()->MoveBox(&m_Core.m_Pos, &m_Core.m_Vel, vec2(g_CharPhysSize, g_CharPhysSize), 0.f);
+		
 		// reset velocity so the client doesn't predict stuff
-		core.vel = vec2(0.0f,0.0f);
-		if ((ninja.currentmovetime % 2) == 0)
-		{
-			//create_smoke(pos);
-		}
+		m_Core.m_Vel = vec2(0.f, 0.f);
 
-		// check if we hit anything along the way
+		// check if we Hit anything along the way
 		{
-			CHARACTER *ents[64];
-			vec2 dir = pos - oldpos;
-			float radius = phys_size * 2.0f; //length(dir * 0.5f);
-			vec2 center = oldpos + dir * 0.5f;
-			int num = game.world.find_entities(center, radius, (ENTITY**)ents, 64, NETOBJTYPE_CHARACTER);
+			CCharacter *aEnts[64];
+			vec2 Dir = m_Pos - OldPos;
+			float Radius = g_CharPhysSize * 2.0f;
+			vec2 Center = OldPos + Dir * 0.5f;
+			int Num = GameServer()->m_World.FindEntities(Center, Radius, (CEntity**)aEnts, 64, NETOBJTYPE_CHARACTER);
 
-			for (int i = 0; i < num; i++)
+			for (int i = 0; i < Num; ++i)
 			{
-				// Check if entity is a player
-				if (ents[i] == this)
+				if (aEnts[i] == this)
 					continue;
-				// make sure we haven't hit this object before
-				bool balreadyhit = false;
-				for (int j = 0; j < numobjectshit; j++)
+					
+				// make sure we haven't Hit this object before
+				bool bAlreadyHit = false;
+				for (int j = 0; j < m_NumObjectsHit; j++)
 				{
-					if (hitobjects[j] == ents[i])
-						balreadyhit = true;
+					if (m_apHitObjects[j] == aEnts[i])
+						bAlreadyHit = true;
 				}
-				if (balreadyhit)
+				if (bAlreadyHit)
 					continue;
 
 				// check so we are sufficiently close
-				if (distance(ents[i]->pos, pos) > (phys_size * 2.0f))
+				if (distance(aEnts[i]->m_Pos, m_Pos) > (g_CharPhysSize * 2.0f))
 					continue;
 
-				// hit a player, give him damage and stuffs...
-				game.create_sound(ents[i]->pos, SOUND_NINJA_HIT);
+				// Hit a player, give him damage and stuffs...
+				GameServer()->CreateSound(aEnts[i]->m_Pos, SOUND_NINJA_HIT);
 				// set his velocity to fast upward (for now)
-				if(numobjectshit < 10)
-					hitobjects[numobjectshit++] = ents[i];
+				if(m_NumObjectsHit < 10)
+					m_apHitObjects[m_NumObjectsHit++] = aEnts[i];
 					
-				ents[i]->take_damage(vec2(0,10.0f), data->weapons.ninja.base->damage, player->client_id,WEAPON_NINJA);
+				aEnts[i]->TakeDamage(vec2(0, 10.0f), g_pData->m_Weapons.m_Ninja.m_pBase->m_Damage, m_pPlayer->GetCID(), WEAPON_NINJA);
 			}
 		}
-		return 0;
+		
+		return;
 	}
 
-	return 0;
+	return;
 }
 
 
-void CHARACTER::do_weaponswitch()
+void CCharacter::DoWeaponSwitch()
 {
-	if(reload_timer != 0) // make sure we have reloaded
-		return;
-		
-	if(queued_weapon == -1) // check for a queued weapon
+	// make sure we can switch
+	if(m_ReloadTimer != 0 || m_QueuedWeapon == -1 || m_aWeapons[WEAPON_NINJA].m_Got)
 		return;
 
-	if(weapons[WEAPON_NINJA].got) // if we have ninja, no weapon selection is possible
-		return;
-
-	// switch weapon
-	set_weapon(queued_weapon);
+	// switch Weapon
+	SetWeapon(m_QueuedWeapon);
 }
 
-void CHARACTER::handle_weaponswitch()
+void CCharacter::HandleWeaponSwitch()
 {
-	int wanted_weapon = active_weapon;
-	if(queued_weapon != -1)
-		wanted_weapon = queued_weapon;
+	int WantedWeapon = m_ActiveWeapon;
+	if(m_QueuedWeapon != -1)
+		WantedWeapon = m_QueuedWeapon;
 	
-	// select weapon
-	int next = count_input(latest_previnput.next_weapon, latest_input.next_weapon).presses;
-	int prev = count_input(latest_previnput.prev_weapon, latest_input.prev_weapon).presses;
+	// select Weapon
+	int Next = CountInput(m_LatestPrevInput.m_NextWeapon, m_LatestInput.m_NextWeapon).m_Presses;
+	int Prev = CountInput(m_LatestPrevInput.m_PrevWeapon, m_LatestInput.m_PrevWeapon).m_Presses;
 
-	if(next < 128) // make sure we only try sane stuff
+	if(Next < 128) // make sure we only try sane stuff
 	{
-		while(next) // next weapon selection
+		while(Next) // Next Weapon selection
 		{
-			wanted_weapon = (wanted_weapon+1)%NUM_WEAPONS;
-			if(weapons[wanted_weapon].got)
-				next--;
+			WantedWeapon = (WantedWeapon+1)%NUM_WEAPONS;
+			if(m_aWeapons[WantedWeapon].m_Got)
+				Next--;
 		}
 	}
 
-	if(prev < 128) // make sure we only try sane stuff
+	if(Prev < 128) // make sure we only try sane stuff
 	{
-		while(prev) // prev weapon selection
+		while(Prev) // Prev Weapon selection
 		{
-			wanted_weapon = (wanted_weapon-1)<0?NUM_WEAPONS-1:wanted_weapon-1;
-			if(weapons[wanted_weapon].got)
-				prev--;
+			WantedWeapon = (WantedWeapon-1)<0?NUM_WEAPONS-1:WantedWeapon-1;
+			if(m_aWeapons[WantedWeapon].m_Got)
+				Prev--;
 		}
 	}
 
-	// direct weapon selection
-	if(latest_input.wanted_weapon)
-		wanted_weapon = input.wanted_weapon-1;
+	// Direct Weapon selection
+	if(m_LatestInput.m_WantedWeapon)
+		WantedWeapon = m_Input.m_WantedWeapon-1;
 
 	// check for insane values
-	if(wanted_weapon >= 0 && wanted_weapon < NUM_WEAPONS && wanted_weapon != active_weapon && weapons[wanted_weapon].got)
-		queued_weapon = wanted_weapon;
+	if(WantedWeapon >= 0 && WantedWeapon < NUM_WEAPONS && WantedWeapon != m_ActiveWeapon && m_aWeapons[WantedWeapon].m_Got)
+		m_QueuedWeapon = WantedWeapon;
 	
-	do_weaponswitch();
+	DoWeaponSwitch();
 }
 
-void CHARACTER::fire_weapon()
+void CCharacter::FireWeapon()
 {
-	if(reload_timer != 0)
+	if(m_ReloadTimer != 0)
 		return;
 		
-	do_weaponswitch();
+	DoWeaponSwitch();
+	vec2 Direction = normalize(vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY));
 	
-	vec2 direction = normalize(vec2(latest_input.target_x, latest_input.target_y));
-	
-	bool fullauto = false;
-	if(active_weapon == WEAPON_GRENADE || active_weapon == WEAPON_SHOTGUN || active_weapon == WEAPON_RIFLE)
-		fullauto = true;
+	bool FullAuto = false;
+	if(m_ActiveWeapon == WEAPON_GRENADE || m_ActiveWeapon == WEAPON_SHOTGUN || m_ActiveWeapon == WEAPON_RIFLE)
+		FullAuto = true;
 
 
 	// check if we gonna fire
-	bool will_fire = false;
-	if(count_input(latest_previnput.fire, latest_input.fire).presses) will_fire = true;
-	if(fullauto && (latest_input.fire&1) && weapons[active_weapon].ammo) will_fire = true;
-	if(!will_fire)
+	bool WillFire = false;
+	if(CountInput(m_LatestPrevInput.m_Fire, m_LatestInput.m_Fire).m_Presses)
+		WillFire = true;
+		
+	if(FullAuto && (m_LatestInput.m_Fire&1) && m_aWeapons[m_ActiveWeapon].m_Ammo)
+		WillFire = true;
+		
+	if(!WillFire)
 		return;
 		
 	// check for ammo
-	if(!weapons[active_weapon].ammo)
+	if(!m_aWeapons[m_ActiveWeapon].m_Ammo)
 	{
 		// 125ms is a magical limit of how fast a human can click
-		reload_timer = 125 * server_tickspeed() / 1000;;
-		game.create_sound(pos, SOUND_WEAPON_NOAMMO);
+		m_ReloadTimer = 125 * Server()->TickSpeed() / 1000;
+		GameServer()->CreateSound(m_Pos, SOUND_WEAPON_NOAMMO);
 		return;
 	}
 	
-	vec2 projectile_startpos = pos+direction*phys_size*0.75f;
+	vec2 ProjStartPos = m_Pos+Direction*g_CharPhysSize*0.75f;
 	
-	switch(active_weapon)
+	switch(m_ActiveWeapon)
 	{
 		case WEAPON_HAMMER:
 		{
-			// reset objects hit
-			numobjectshit = 0;
-			game.create_sound(pos, SOUND_HAMMER_FIRE);
+			// reset objects Hit
+			m_NumObjectsHit = 0;
+			GameServer()->CreateSound(m_Pos, SOUND_HAMMER_FIRE);
 			
-			CHARACTER *ents[64];
-			int hits = 0;
-			int num = game.world.find_entities(pos+direction*phys_size*0.75f, phys_size*0.5f, (ENTITY**)ents, 64, NETOBJTYPE_CHARACTER);
+			CCharacter *aEnts[64];
+			int Hits = 0;
+			int Num = GameServer()->m_World.FindEntities(ProjStartPos, g_CharPhysSize*0.5f, (CEntity**)aEnts, 
+			64, NETOBJTYPE_CHARACTER);
 
-			for (int i = 0; i < num; i++)
+			for (int i = 0; i < Num; ++i)
 			{
-				CHARACTER *target = ents[i];
-				if (target == this)
+				CCharacter *Target = aEnts[i];
+				
+				//for race mod or any other mod, which needs hammer hits through the wall remove second condition
+				if ((Target == this) || GameServer()->Collision()->IntersectLine(ProjStartPos, Target->m_Pos, NULL, NULL))
 					continue;
-					
-				// hit a player, give him damage and stuffs...
-				vec2 fdir = normalize(ents[i]->pos - pos);
 
 				// set his velocity to fast upward (for now)
-				game.create_hammerhit(pos);
-				ents[i]->take_damage(vec2(0,-1.0f), data->weapons.hammer.base->damage, player->client_id, active_weapon);
-				vec2 dir;
-				if (length(target->pos - pos) > 0.0f)
-					dir = normalize(target->pos - pos);
+				GameServer()->CreateHammerHit(m_Pos);
+				aEnts[i]->TakeDamage(vec2(0.f, -1.f), g_pData->m_Weapons.m_Hammer.m_pBase->m_Damage, m_pPlayer->GetCID(), m_ActiveWeapon);
+				
+				vec2 Dir;
+				if (length(Target->m_Pos - m_Pos) > 0.0f)
+					Dir = normalize(Target->m_Pos - m_Pos);
 				else
-					dir = vec2(0,-1);
+					Dir = vec2(0.f, -1.f);
 					
-				target->core.vel += normalize(dir + vec2(0,-1.1f)) * 10.0f;
-				hits++;
+				Target->m_Core.m_Vel += normalize(Dir + vec2(0.f, -1.1f)) * 10.0f;
+				Hits++;
 			}
 			
-			// if we hit anything, we have to wait for the reload
-			if(hits)
-				reload_timer = server_tickspeed()/3;
+			// if we Hit anything, we have to wait for the reload
+			if(Hits)
+				m_ReloadTimer = Server()->TickSpeed()/3;
 			
 		} break;
 
 		case WEAPON_GUN:
 		{
-			PROJECTILE *proj = new PROJECTILE(WEAPON_GUN,
-				player->client_id,
-				projectile_startpos,
-				direction,
-				(int)(server_tickspeed()*tuning.gun_lifetime),
+			CProjectile *Proj = new CProjectile(GameWorld(), WEAPON_GUN,
+				m_pPlayer->GetCID(),
+				ProjStartPos,
+				Direction,
+				(int)(Server()->TickSpeed()*GameServer()->Tuning()->m_GunLifetime),
 				1, 0, 0, -1, WEAPON_GUN);
 				
-			// pack the projectile and send it to the client directly
-			NETOBJ_PROJECTILE p;
-			proj->fill_info(&p);
+			// pack the Projectile and send it to the client Directly
+			CNetObj_Projectile p;
+			Proj->FillInfo(&p);
 			
-			msg_pack_start(NETMSGTYPE_SV_EXTRAPROJECTILE, 0);
-			msg_pack_int(1);
-			for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++)
-				msg_pack_int(((int *)&p)[i]);
-			msg_pack_end();
-			server_send_msg(player->client_id);
-							
-			game.create_sound(pos, SOUND_GUN_FIRE);
+			CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE);
+			Msg.AddInt(1);
+			for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++)
+				Msg.AddInt(((int *)&p)[i]);
+				
+			Server()->SendMsg(&Msg, 0, m_pPlayer->GetCID());
+	
+			GameServer()->CreateSound(m_Pos, SOUND_GUN_FIRE);
 		} break;
 		
 		case WEAPON_SHOTGUN:
 		{
-			int shotspread = 2;
+			int ShotSpread = 2;
 
-			msg_pack_start(NETMSGTYPE_SV_EXTRAPROJECTILE, 0);
-			msg_pack_int(shotspread*2+1);
+			CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE);
+			Msg.AddInt(ShotSpread*2+1);
 			
-			for(int i = -shotspread; i <= shotspread; i++)
+			for(int i = -ShotSpread; i <= ShotSpread; ++i)
 			{
-				float spreading[] = {-0.185f, -0.070f, 0, 0.070f, 0.185f};
-				float a = get_angle(direction);
-				a += spreading[i+2];
-				float v = 1-(abs(i)/(float)shotspread);
-				float speed = mix((float)tuning.shotgun_speeddiff, 1.0f, v);
-				PROJECTILE *proj = new PROJECTILE(WEAPON_SHOTGUN,
-					player->client_id,
-					projectile_startpos,
-					vec2(cosf(a), sinf(a))*speed,
-					(int)(server_tickspeed()*tuning.shotgun_lifetime),
+				float Spreading[] = {-0.185f, -0.070f, 0, 0.070f, 0.185f};
+				float a = GetAngle(Direction);
+				a += Spreading[i+2];
+				float v = 1-(absolute(i)/(float)ShotSpread);
+				float Speed = mix((float)GameServer()->Tuning()->m_ShotgunSpeeddiff, 1.0f, v);
+				CProjectile *Proj = new CProjectile(GameWorld(), WEAPON_SHOTGUN,
+					m_pPlayer->GetCID(),
+					ProjStartPos,
+					vec2(cosf(a), sinf(a))*Speed,
+					(int)(Server()->TickSpeed()*GameServer()->Tuning()->m_ShotgunLifetime),
 					1, 0, 0, -1, WEAPON_SHOTGUN);
 					
-				// pack the projectile and send it to the client directly
-				NETOBJ_PROJECTILE p;
-				proj->fill_info(&p);
+				// pack the Projectile and send it to the client Directly
+				CNetObj_Projectile p;
+				Proj->FillInfo(&p);
 				
-				for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++)
-					msg_pack_int(((int *)&p)[i]);
+				for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++)
+					Msg.AddInt(((int *)&p)[i]);
 			}
 
-			msg_pack_end();
-			server_send_msg(player->client_id);					
+			Server()->SendMsg(&Msg, 0,m_pPlayer->GetCID());					
 			
-			game.create_sound(pos, SOUND_SHOTGUN_FIRE);
+			GameServer()->CreateSound(m_Pos, SOUND_SHOTGUN_FIRE);
 		} break;
 
 		case WEAPON_GRENADE:
 		{
-			PROJECTILE *proj = new PROJECTILE(WEAPON_GRENADE,
-				player->client_id,
-				projectile_startpos,
-				direction,
-				(int)(server_tickspeed()*tuning.grenade_lifetime),
-				1, PROJECTILE::PROJECTILE_FLAGS_EXPLODE, 0, SOUND_GRENADE_EXPLODE, WEAPON_GRENADE);
-
-			// pack the projectile and send it to the client directly
-			NETOBJ_PROJECTILE p;
-			proj->fill_info(&p);
+			CProjectile *Proj = new CProjectile(GameWorld(), WEAPON_GRENADE,
+				m_pPlayer->GetCID(),
+				ProjStartPos,
+				Direction,
+				(int)(Server()->TickSpeed()*GameServer()->Tuning()->m_GrenadeLifetime),
+				1, true, 0, SOUND_GRENADE_EXPLODE, WEAPON_GRENADE);
+
+			// pack the Projectile and send it to the client Directly
+			CNetObj_Projectile p;
+			Proj->FillInfo(&p);
+			
+			CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE);
+			Msg.AddInt(1);
+			for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++)
+				Msg.AddInt(((int *)&p)[i]);
+			Server()->SendMsg(&Msg, 0, m_pPlayer->GetCID());
 			
-			msg_pack_start(NETMSGTYPE_SV_EXTRAPROJECTILE, 0);
-			msg_pack_int(1);
-			for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++)
-				msg_pack_int(((int *)&p)[i]);
-			msg_pack_end();
-			server_send_msg(player->client_id);
-
-			game.create_sound(pos, SOUND_GRENADE_FIRE);
+			GameServer()->CreateSound(m_Pos, SOUND_GRENADE_FIRE);
 		} break;
 		
 		case WEAPON_RIFLE:
 		{
-			new LASER(pos, direction, tuning.laser_reach, player->client_id);
-			game.create_sound(pos, SOUND_RIFLE_FIRE);
+			new CLaser(GameWorld(), m_Pos, Direction, GameServer()->Tuning()->m_LaserReach, m_pPlayer->GetCID());
+			GameServer()->CreateSound(m_Pos, SOUND_RIFLE_FIRE);
 		} break;
 		
 		case WEAPON_NINJA:
 		{
-			attack_tick = server_tick();
-			ninja.activationdir = direction;
-			ninja.currentmovetime = data->weapons.ninja.movetime * server_tickspeed() / 1000;
-
-			//reload_timer = data->weapons.ninja.base->firedelay * server_tickspeed() / 1000 + server_tick();
+			// reset Hit objects
+			m_NumObjectsHit = 0;
 			
-			// reset hit objects
-			numobjectshit = 0;
+			m_AttackTick = Server()->Tick();
+			m_Ninja.m_ActivationDir = Direction;
+			m_Ninja.m_CurrentMoveTime = g_pData->m_Weapons.m_Ninja.m_Movetime * Server()->TickSpeed() / 1000;
 
-			game.create_sound(pos, SOUND_NINJA_FIRE);
-			
+			GameServer()->CreateSound(m_Pos, SOUND_NINJA_FIRE);
 		} break;
 		
 	}
-
-	if(weapons[active_weapon].ammo > 0) // -1 == unlimited
-		weapons[active_weapon].ammo--;
-	attack_tick = server_tick();
-	if(!reload_timer)
-		reload_timer = data->weapons.id[active_weapon].firedelay * server_tickspeed() / 1000;
+	
+	m_AttackTick = Server()->Tick();
+	
+	if(m_aWeapons[m_ActiveWeapon].m_Ammo > 0) // -1 == unlimited
+		m_aWeapons[m_ActiveWeapon].m_Ammo--;
+	
+	if(!m_ReloadTimer)
+		m_ReloadTimer = g_pData->m_Weapons.m_aId[m_ActiveWeapon].m_Firedelay * Server()->TickSpeed() / 1000;
 }
 
-int CHARACTER::handle_weapons()
+void CCharacter::HandleWeapons()
 {
-	vec2 direction = normalize(vec2(latest_input.target_x, latest_input.target_y));
-
-	/*
-	if(config.dbg_stress)
-	{
-		for(int i = 0; i < NUM_WEAPONS; i++)
-		{
-			weapons[i].got = true;
-			weapons[i].ammo = 10;
-		}
-
-		if(reload_timer) // twice as fast reload
-			reload_timer--;
-	} */
-
-	//if(active_weapon == WEAPON_NINJA)
-	handle_ninja();
-
+	//ninja
+	HandleNinja();
+	
+	vec2 Direction = normalize(vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY));
 
 	// check reload timer
-	if(reload_timer)
+	if(m_ReloadTimer)
 	{
-		reload_timer--;
-		return 0;
+		m_ReloadTimer--;
+		return;
 	}
-	
-	/*
-	if (active_weapon == WEAPON_NINJA)
-	{
-		// don't update other weapons while ninja is active
-		return handle_ninja();
-	}*/
 
-	// fire weapon, if wanted
-	fire_weapon();
+	// fire Weapon, if wanted
+	FireWeapon();
 
 	// ammo regen
-	int ammoregentime = data->weapons.id[active_weapon].ammoregentime;
-	if(ammoregentime)
+	int AmmoRegenTime = g_pData->m_Weapons.m_aId[m_ActiveWeapon].m_Ammoregentime;
+	if(AmmoRegenTime)
 	{
 		// If equipped and not active, regen ammo?
-		if (reload_timer <= 0)
+		if (m_ReloadTimer <= 0)
 		{
-			if (weapons[active_weapon].ammoregenstart < 0)
-				weapons[active_weapon].ammoregenstart = server_tick();
+			if (m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart < 0)
+				m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = Server()->Tick();
 
-			if ((server_tick() - weapons[active_weapon].ammoregenstart) >= ammoregentime * server_tickspeed() / 1000)
+			if ((Server()->Tick() - m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart) >= AmmoRegenTime * Server()->TickSpeed() / 1000)
 			{
 				// Add some ammo
-				weapons[active_weapon].ammo = min(weapons[active_weapon].ammo + 1, 10);
-				weapons[active_weapon].ammoregenstart = -1;
+				m_aWeapons[m_ActiveWeapon].m_Ammo = min(m_aWeapons[m_ActiveWeapon].m_Ammo + 1, 10);
+				m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = -1;
 			}
 		}
 		else
 		{
-			weapons[active_weapon].ammoregenstart = -1;
+			m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = -1;
 		}
 	}
 	
-	return 0;
+	return;
+}
+
+bool CCharacter::GiveWeapon(int Weapon, int Ammo)
+{
+	if(m_aWeapons[Weapon].m_Ammo < g_pData->m_Weapons.m_aId[Weapon].m_Maxammo || !m_aWeapons[Weapon].m_Got)
+	{	
+		m_aWeapons[Weapon].m_Got = true;
+		m_aWeapons[Weapon].m_Ammo = min(g_pData->m_Weapons.m_aId[Weapon].m_Maxammo, Ammo);
+		return true;
+	}
+	return false;
+}
+
+void CCharacter::GiveNinja()
+{
+	m_Ninja.m_ActivationTick = Server()->Tick();
+	m_aWeapons[WEAPON_NINJA].m_Got = true;
+	m_aWeapons[WEAPON_NINJA].m_Ammo = -1;
+	m_LastWeapon = m_ActiveWeapon;
+	m_ActiveWeapon = WEAPON_NINJA;
+	
+	GameServer()->CreateSound(m_Pos, SOUND_PICKUP_NINJA);
 }
 
-void CHARACTER::on_predicted_input(NETOBJ_PLAYER_INPUT *new_input)
+void CCharacter::SetEmote(int Emote, int Tick)
+{
+	m_EmoteType = Emote;
+	m_EmoteStop = Tick;
+}
+
+void CCharacter::OnPredictedInput(CNetObj_PlayerInput *pNewInput)
 {
 	// check for changes
-	if(mem_comp(&input, new_input, sizeof(NETOBJ_PLAYER_INPUT)) != 0)
-		last_action = server_tick();
+	if(mem_comp(&m_Input, pNewInput, sizeof(CNetObj_PlayerInput)) != 0)
+		m_LastAction = Server()->Tick();
 		
 	// copy new input
-	mem_copy(&input, new_input, sizeof(input));
-	num_inputs++;
+	mem_copy(&m_Input, pNewInput, sizeof(m_Input));
+	m_NumInputs++;
 	
 	// or are not allowed to aim in the center
-	if(input.target_x == 0 && input.target_y == 0)
-		input.target_y = -1;	
+	if(m_Input.m_TargetX == 0 && m_Input.m_TargetY == 0)
+		m_Input.m_TargetY = -1;	
 }
 
-void CHARACTER::on_direct_input(NETOBJ_PLAYER_INPUT *new_input)
+void CCharacter::OnDirectInput(CNetObj_PlayerInput *pNewInput)
 {
-	mem_copy(&latest_previnput, &latest_input, sizeof(latest_input));
-	mem_copy(&latest_input, new_input, sizeof(latest_input));
+	mem_copy(&m_LatestPrevInput, &m_LatestInput, sizeof(m_LatestInput));
+	mem_copy(&m_LatestInput, pNewInput, sizeof(m_LatestInput));
 	
-	if(num_inputs > 2 && team != -1)
+	if(m_NumInputs > 2 && m_pPlayer->GetTeam() != -1)
 	{
-		handle_weaponswitch();
-		fire_weapon();
+		HandleWeaponSwitch();
+		FireWeapon();
 	}
 	
-	mem_copy(&latest_previnput, &latest_input, sizeof(latest_input));
+	mem_copy(&m_LatestPrevInput, &m_LatestInput, sizeof(m_LatestInput));
 }
 
-void CHARACTER::tick()
+void CCharacter::Tick()
 {
-	if(player->force_balanced)
+	if(m_pPlayer->m_ForceBalanced)
 	{
-		char buf[128];
-		str_format(buf, sizeof(buf), "You were moved to %s due to team balancing", game.controller->get_team_name(team));
-		game.send_broadcast(buf, player->client_id);
+		char Buf[128];
+		str_format(Buf, sizeof(Buf), "You were moved to %s due to team balancing", GameServer()->m_pController->GetTeamName(m_pPlayer->GetTeam()));
+		GameServer()->SendBroadcast(Buf, m_pPlayer->GetCID());
 		
-		player->force_balanced = false;
+		m_pPlayer->m_ForceBalanced = false;
 	}
 
-	//player_core core;
-	//core.pos = pos;
-	//core.jumped = jumped;
-	core.input = input;
-	core.tick(true);
+	m_Core.m_Input = m_Input;
+	m_Core.Tick(true);
 	
-	float phys_size = 28.0f;
 	// handle death-tiles
-	if(col_get((int)(pos.x+phys_size/3), (int)(pos.y-phys_size/3))&COLFLAG_DEATH ||
-			col_get((int)(pos.x+phys_size/3), (int)(pos.y+phys_size/3))&COLFLAG_DEATH ||
-			col_get((int)(pos.x-phys_size/3), (int)(pos.y-phys_size/3))&COLFLAG_DEATH ||
-			col_get((int)(pos.x-phys_size/3), (int)(pos.y+phys_size/3))&COLFLAG_DEATH)
+	if(GameServer()->Collision()->GetCollisionAt(m_Pos.x+g_CharPhysSize/3.f, m_Pos.y-g_CharPhysSize/3.f)&CCollision::COLFLAG_DEATH ||
+		GameServer()->Collision()->GetCollisionAt(m_Pos.x+g_CharPhysSize/3.f, m_Pos.y+g_CharPhysSize/3.f)&CCollision::COLFLAG_DEATH ||
+		GameServer()->Collision()->GetCollisionAt(m_Pos.x-g_CharPhysSize/3.f, m_Pos.y-g_CharPhysSize/3.f)&CCollision::COLFLAG_DEATH ||
+		GameServer()->Collision()->GetCollisionAt(m_Pos.x-g_CharPhysSize/3.f, m_Pos.y+g_CharPhysSize/3.f)&CCollision::COLFLAG_DEATH)
 	{
-		die(player->client_id, WEAPON_WORLD);
+		Die(m_pPlayer->GetCID(), WEAPON_WORLD);
 	}
 
-	// handle weapons
-	handle_weapons();
+	// handle Weapons
+	HandleWeapons();
 
-	player_state = input.player_state;
+	m_PlayerState = m_Input.m_PlayerState;
 
 	// Previnput
-	previnput = input;
+	m_PrevInput = m_Input;
 	return;
 }
 
-void CHARACTER::tick_defered()
+void CCharacter::TickDefered()
 {
 	// advance the dummy
 	{
-		WORLD_CORE tempworld;
-		reckoningcore.world = &tempworld;
-		reckoningcore.tick(false);
-		reckoningcore.move();
-		reckoningcore.quantize();
+		CWorldCore TempWorld;
+		m_ReckoningCore.Init(&TempWorld, GameServer()->Collision());
+		m_ReckoningCore.Tick(false);
+		m_ReckoningCore.Move();
+		m_ReckoningCore.Quantize();
 	}
 	
-	//lastsentcore;
-	/*if(!dead)
-	{*/
-		vec2 start_pos = core.pos;
-		vec2 start_vel = core.vel;
-		bool stuck_before = test_box(core.pos, vec2(28.0f, 28.0f));
-		
-		core.move();
-		bool stuck_after_move = test_box(core.pos, vec2(28.0f, 28.0f));
-		core.quantize();
-		bool stuck_after_quant = test_box(core.pos, vec2(28.0f, 28.0f));
-		pos = core.pos;
-		
-		if(!stuck_before && (stuck_after_move || stuck_after_quant))
-		{
-			dbg_msg("player", "STUCK!!! %d %d %d %f %f %f %f %x %x %x %x", 
-				stuck_before,
-				stuck_after_move,
-				stuck_after_quant,
-				start_pos.x, start_pos.y,
-				start_vel.x, start_vel.y,
-				*((unsigned *)&start_pos.x), *((unsigned *)&start_pos.y),
-				*((unsigned *)&start_vel.x), *((unsigned *)&start_vel.y));
-		}
+	//lastsentcore
+	vec2 StartPos = m_Core.m_Pos;
+	vec2 StartVel = m_Core.m_Vel;
+	bool StuckBefore = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f));
+	
+	m_Core.Move();
+	bool StuckAfterMove = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f));
+	m_Core.Quantize();
+	bool StuckAfterQuant = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f));
+	m_Pos = m_Core.m_Pos;
+	
+	if(!StuckBefore && (StuckAfterMove || StuckAfterQuant))
+	{
+		dbg_msg("char_core", "STUCK!!! %d %d %d %f %f %f %f %x %x %x %x", 
+			StuckBefore,
+			StuckAfterMove,
+			StuckAfterQuant,
+			StartPos.x, StartPos.y,
+			StartVel.x, StartVel.y,
+			*((unsigned *)&StartPos.x), *((unsigned *)&StartPos.y),
+			*((unsigned *)&StartVel.x), *((unsigned *)&StartVel.y));
+	}
 
-		int events = core.triggered_events;
-		int mask = cmask_all_except_one(player->client_id);
-		
-		if(events&COREEVENT_GROUND_JUMP) game.create_sound(pos, SOUND_PLAYER_JUMP, mask);
-		
-		//if(events&COREEVENT_HOOK_LAUNCH) snd_play_random(CHN_WORLD, SOUND_HOOK_LOOP, 1.0f, pos);
-		if(events&COREEVENT_HOOK_ATTACH_PLAYER) game.create_sound(pos, SOUND_HOOK_ATTACH_PLAYER, cmask_all());
-		if(events&COREEVENT_HOOK_ATTACH_GROUND) game.create_sound(pos, SOUND_HOOK_ATTACH_GROUND, mask);
-		if(events&COREEVENT_HOOK_HIT_NOHOOK) game.create_sound(pos, SOUND_HOOK_NOATTACH, mask);
-		//if(events&COREEVENT_HOOK_RETRACT) snd_play_random(CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, pos);
-	//}
-	
-	if(team == -1)
+	int Events = m_Core.m_TriggeredEvents;
+	int Mask = CmaskAllExceptOne(m_pPlayer->GetCID());
+	
+	if(Events&COREEVENT_GROUND_JUMP) GameServer()->CreateSound(m_Pos, SOUND_PLAYER_JUMP, Mask);
+	
+	if(Events&COREEVENT_HOOK_ATTACH_PLAYER) GameServer()->CreateSound(m_Pos, SOUND_HOOK_ATTACH_PLAYER, CmaskAll());
+	if(Events&COREEVENT_HOOK_ATTACH_GROUND) GameServer()->CreateSound(m_Pos, SOUND_HOOK_ATTACH_GROUND, Mask);
+	if(Events&COREEVENT_HOOK_HIT_NOHOOK) GameServer()->CreateSound(m_Pos, SOUND_HOOK_NOATTACH, Mask);
+
+	
+	if(m_pPlayer->GetTeam() == -1)
 	{
-		pos.x = input.target_x;
-		pos.y = input.target_y;
+		m_Pos.x = m_Input.m_TargetX;
+		m_Pos.y = m_Input.m_TargetY;
 	}
 	
-	// update the sendcore if needed
+	// update the m_SendCore if needed
 	{
-		NETOBJ_CHARACTER predicted;
-		NETOBJ_CHARACTER current;
-		mem_zero(&predicted, sizeof(predicted));
-		mem_zero(&current, sizeof(current));
-		reckoningcore.write(&predicted);
-		core.write(&current);
+		CNetObj_Character Predicted;
+		CNetObj_Character Current;
+		mem_zero(&Predicted, sizeof(Predicted));
+		mem_zero(&Current, sizeof(Current));
+		m_ReckoningCore.Write(&Predicted);
+		m_Core.Write(&Current);
 
 		// only allow dead reackoning for a top of 3 seconds
-		if(reckoning_tick+server_tickspeed()*3 < server_tick() || mem_comp(&predicted, &current, sizeof(NETOBJ_CHARACTER)) != 0)
+		if(m_ReckoningTick+Server()->TickSpeed()*3 < Server()->Tick() || mem_comp(&Predicted, &Current, sizeof(CNetObj_Character)) != 0)
 		{
-			reckoning_tick = server_tick();
-			sendcore = core;
-			reckoningcore = core;
+			m_ReckoningTick = Server()->Tick();
+			m_SendCore = m_Core;
+			m_ReckoningCore = m_Core;
 		}
 	}
 }
 
-bool CHARACTER::increase_health(int amount)
+bool CCharacter::IncreaseHealth(int Amount)
 {
-	if(health >= 10)
+	if(m_Health >= 10)
 		return false;
-	health = clamp(health+amount, 0, 10);
+	m_Health = clamp(m_Health+Amount, 0, 10);
 	return true;
 }
 
-bool CHARACTER::increase_armor(int amount)
+bool CCharacter::IncreaseArmor(int Amount)
 {
-	if(armor >= 10)
+	if(m_Armor >= 10)
 		return false;
-	armor = clamp(armor+amount, 0, 10);
+	m_Armor = clamp(m_Armor+Amount, 0, 10);
 	return true;
 }
 
-void CHARACTER::die(int killer, int weapon)
+void CCharacter::Die(int Killer, int Weapon)
 {
-	/*if (dead || team == -1)
-		return;*/
-	int mode_special = game.controller->on_character_death(this, game.players[killer], weapon);
+	int ModeSpecial = GameServer()->m_pController->OnCharacterDeath(this, GameServer()->m_apPlayers[Killer], Weapon);
 
 	dbg_msg("game", "kill killer='%d:%s' victim='%d:%s' weapon=%d special=%d",
-		killer, server_clientname(killer),
-		player->client_id, server_clientname(player->client_id), weapon, mode_special);
+		Killer, Server()->ClientName(Killer),
+		m_pPlayer->GetCID(), Server()->ClientName(m_pPlayer->GetCID()), Weapon, ModeSpecial);
 
 	// send the kill message
-	NETMSG_SV_KILLMSG msg;
-	msg.killer = killer;
-	msg.victim = player->client_id;
-	msg.weapon = weapon;
-	msg.mode_special = mode_special;
-	msg.pack(MSGFLAG_VITAL);
-	server_send_msg(-1);
+	CNetMsg_Sv_KillMsg Msg;
+	Msg.m_Killer = Killer;
+	Msg.m_Victim = m_pPlayer->GetCID();
+	Msg.m_Weapon = Weapon;
+	Msg.m_ModeSpecial = ModeSpecial;
+	Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, -1);
 
 	// a nice sound
-	game.create_sound(pos, SOUND_PLAYER_DIE);
-
-	// set dead state
-	// TODO: do stuff here
-	/*
-	die_pos = pos;
-	dead = true;
-	*/
+	GameServer()->CreateSound(m_Pos, SOUND_PLAYER_DIE);
 	
 	// this is for auto respawn after 3 secs
-	player->die_tick = server_tick();
+	m_pPlayer->m_DieTick = Server()->Tick();
 	
-	alive = false;
-	game.world.remove_entity(this);
-	game.world.core.characters[player->client_id] = 0;
-	game.create_death(pos, player->client_id);
+	m_Alive = false;
+	GameServer()->m_World.RemoveEntity(this);
+	GameServer()->m_World.m_Core.m_apCharacters[m_pPlayer->GetCID()] = 0;
+	GameServer()->CreateDeath(m_Pos, m_pPlayer->GetCID());
 	
 	// we got to wait 0.5 secs before respawning
-	player->respawn_tick = server_tick()+server_tickspeed()/2;
+	m_pPlayer->m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2;
 }
 
-bool CHARACTER::take_damage(vec2 force, int dmg, int from, int weapon)
+bool CCharacter::TakeDamage(vec2 Force, int Dmg, int From, int Weapon)
 {
-	core.vel += force;
+	m_Core.m_Vel += Force;
 	
-	if(game.controller->is_friendly_fire(player->client_id, from) && !config.sv_teamdamage)
+	if(GameServer()->m_pController->IsFriendlyFire(m_pPlayer->GetCID(), From) && !g_Config.m_SvTeamdamage)
 		return false;
 
-	// player only inflicts half damage on self
-	if(from == player->client_id)
-		dmg = max(1, dmg/2);
+	// m_pPlayer only inflicts half damage on self
+	if(From == m_pPlayer->GetCID())
+		Dmg = max(1, Dmg/2);
 
-	damage_taken++;
+	m_DamageTaken++;
 
 	// create healthmod indicator
-	if(server_tick() < damage_taken_tick+25)
+	if(Server()->Tick() < m_DamageTakenTick+25)
 	{
 		// make sure that the damage indicators doesn't group together
-		game.create_damageind(pos, damage_taken*0.25f, dmg);
+		GameServer()->CreateDamageInd(m_Pos, m_DamageTaken*0.25f, Dmg);
 	}
 	else
 	{
-		damage_taken = 0;
-		game.create_damageind(pos, 0, dmg);
+		m_DamageTaken = 0;
+		GameServer()->CreateDamageInd(m_Pos, 0, Dmg);
 	}
 
-	if(dmg)
+	if(Dmg)
 	{
-		if(armor)
+		if(m_Armor)
 		{
-			if(dmg > 1)
+			if(Dmg > 1)
 			{
-				health--;
-				dmg--;
+				m_Health--;
+				Dmg--;
 			}
 			
-			if(dmg > armor)
+			if(Dmg > m_Armor)
 			{
-				dmg -= armor;
-				armor = 0;
+				Dmg -= m_Armor;
+				m_Armor = 0;
 			}
 			else
 			{
-				armor -= dmg;
-				dmg = 0;
+				m_Armor -= Dmg;
+				Dmg = 0;
 			}
 		}
 		
-		health -= dmg;
+		m_Health -= Dmg;
 	}
 
-	damage_taken_tick = server_tick();
+	m_DamageTakenTick = Server()->Tick();
 
-	// do damage hit sound
-	if(from >= 0 && from != player->client_id && game.players[from])
-		game.create_sound(game.players[from]->view_pos, SOUND_HIT, cmask_one(from));
+	// do damage Hit sound
+	if(From >= 0 && From != m_pPlayer->GetCID() && GameServer()->m_apPlayers[From])
+		GameServer()->CreateSound(GameServer()->m_apPlayers[From]->m_ViewPos, SOUND_HIT, CmaskOne(From));
 
 	// check for death
-	if(health <= 0)
+	if(m_Health <= 0)
 	{
-		die(from, weapon);
+		Die(From, Weapon);
 		
 		// set attacker's face to happy (taunt!)
-		if (from >= 0 && from != player->client_id && game.players[from])
+		if (From >= 0 && From != m_pPlayer->GetCID() && GameServer()->m_apPlayers[From])
 		{
-			CHARACTER *chr = game.players[from]->get_character();
-			if (chr)
+			CCharacter *pChr = GameServer()->m_apPlayers[From]->GetCharacter();
+			if (pChr)
 			{
-				chr->emote_type = EMOTE_HAPPY;
-				chr->emote_stop = server_tick() + server_tickspeed();
+				pChr->m_EmoteType = EMOTE_HAPPY;
+				pChr->m_EmoteStop = Server()->Tick() + Server()->TickSpeed();
 			}
 		}
 	
 		return false;
 	}
 
-	if (dmg > 2)
-		game.create_sound(pos, SOUND_PLAYER_PAIN_LONG);
+	if (Dmg > 2)
+		GameServer()->CreateSound(m_Pos, SOUND_PLAYER_PAIN_LONG);
 	else
-		game.create_sound(pos, SOUND_PLAYER_PAIN_SHORT);
+		GameServer()->CreateSound(m_Pos, SOUND_PLAYER_PAIN_SHORT);
 
-	emote_type = EMOTE_PAIN;
-	emote_stop = server_tick() + 500 * server_tickspeed() / 1000;
+	m_EmoteType = EMOTE_PAIN;
+	m_EmoteStop = Server()->Tick() + 500 * Server()->TickSpeed() / 1000;
 
-	// spawn blood?
 	return true;
 }
 
-void CHARACTER::snap(int snapping_client)
+void CCharacter::Snap(int SnappingClient)
 {
-	if(networkclipped(snapping_client))
+	if(NetworkClipped(SnappingClient))
 		return;
 	
-	NETOBJ_CHARACTER *character = (NETOBJ_CHARACTER *)snap_new_item(NETOBJTYPE_CHARACTER, player->client_id, sizeof(NETOBJ_CHARACTER));
+	CNetObj_Character *Character = static_cast<CNetObj_Character *>(Server()->SnapNewItem(NETOBJTYPE_CHARACTER, m_pPlayer->GetCID(), sizeof(CNetObj_Character)));
 	
-	// write down the core
-	if(game.world.paused)
+	// write down the m_Core
+	if(GameServer()->m_World.m_Paused)
 	{
 		// no dead reckoning when paused because the client doesn't know
 		// how far to perform the reckoning
-		character->tick = 0;
-		core.write(character);
+		Character->m_Tick = 0;
+		m_Core.Write(Character);
 	}
 	else
 	{
-		character->tick = reckoning_tick;
-		sendcore.write(character);
+		Character->m_Tick = m_ReckoningTick;
+		m_SendCore.Write(Character);
 	}
 	
 	// set emote
-	if (emote_stop < server_tick())
+	if (m_EmoteStop < Server()->Tick())
 	{
-		emote_type = EMOTE_NORMAL;
-		emote_stop = -1;
+		m_EmoteType = EMOTE_NORMAL;
+		m_EmoteStop = -1;
 	}
 
-	character->emote = emote_type;
+	Character->m_Emote = m_EmoteType;
 
-	character->ammocount = 0;
-	character->health = 0;
-	character->armor = 0;
+	Character->m_AmmoCount = 0;
+	Character->m_Health = 0;
+	Character->m_Armor = 0;
 	
-	character->weapon = active_weapon;
-	character->attacktick = attack_tick;
+	Character->m_Weapon = m_ActiveWeapon;
+	Character->m_AttackTick = m_AttackTick;
 
-	character->direction = input.direction;
+	Character->m_Direction = m_Input.m_Direction;
 
-	if(player->client_id == snapping_client)
+	if(m_pPlayer->GetCID() == SnappingClient)
 	{
-		character->health = health;
-		character->armor = armor;
-		if(weapons[active_weapon].ammo > 0)
-			character->ammocount = weapons[active_weapon].ammo;
+		Character->m_Health = m_Health;
+		Character->m_Armor = m_Armor;
+		if(m_aWeapons[m_ActiveWeapon].m_Ammo > 0)
+			Character->m_AmmoCount = m_aWeapons[m_ActiveWeapon].m_Ammo;
 	}
 
-	if (character->emote == EMOTE_NORMAL)
+	if (Character->m_Emote == EMOTE_NORMAL)
 	{
-		if(250 - ((server_tick() - last_action)%(250)) < 5)
-			character->emote = EMOTE_BLINK;
+		if(250 - ((Server()->Tick() - m_LastAction)%(250)) < 5)
+			Character->m_Emote = EMOTE_BLINK;
 	}
 
-	character->player_state = player_state;
+	Character->m_PlayerState = m_PlayerState;
 }
diff --git a/src/game/server/entities/character.h b/src/game/server/entities/character.h
new file mode 100644
index 00000000..30c6586f
--- /dev/null
+++ b/src/game/server/entities/character.h
@@ -0,0 +1,133 @@
+#ifndef GAME_SERVER_ENTITIES_CHARACTER_H
+#define GAME_SERVER_ENTITIES_CHARACTER_H
+
+#include <game/server/entity.h>
+#include <game/generated/server_data.h>
+#include <game/generated/protocol.h>
+
+#include <game/gamecore.h>
+
+//character's size
+const int g_CharPhysSize = 28;
+
+enum
+{
+	WEAPON_GAME = -3, // team switching etc
+	WEAPON_SELF = -2, // console kill command
+	WEAPON_WORLD = -1, // death tiles etc
+};
+
+class CCharacter : public CEntity
+{
+	MACRO_ALLOC_POOL_ID()
+	
+public:
+	CCharacter(CGameWorld *pWorld);
+	
+	virtual void Reset();
+	virtual void Destroy();
+	virtual void Tick();
+	virtual void TickDefered();
+	virtual void Snap(int SnappingClient);
+		
+	bool IsGrounded();
+	
+	void SetWeapon(int W);
+	void HandleWeaponSwitch();
+	void DoWeaponSwitch();
+	
+	void HandleWeapons();
+	void HandleNinja();
+
+	void OnPredictedInput(CNetObj_PlayerInput *pNewInput);
+	void OnDirectInput(CNetObj_PlayerInput *pNewInput);
+	void FireWeapon();
+
+	void Die(int Killer, int Weapon);
+	bool TakeDamage(vec2 Force, int Dmg, int From, int Weapon);	
+
+	bool Spawn(class CPlayer *pPlayer, vec2 Pos);
+	bool Remove();
+	
+	bool IncreaseHealth(int Amount);
+	bool IncreaseArmor(int Amount);
+	
+	bool GiveWeapon(int Weapon, int Ammo);
+	void GiveNinja();
+	
+	void SetEmote(int Emote, int Tick);
+	
+	const bool IsAlive() { return m_Alive; }
+	class CPlayer *GetPlayer() { return m_pPlayer; }
+	
+private:
+	// player controlling this character
+	class CPlayer *m_pPlayer;
+	
+	bool m_Alive;
+
+	// weapon info
+	CEntity *m_apHitObjects[10];
+	int m_NumObjectsHit;
+	
+	struct WeaponStat
+	{
+		int m_AmmoRegenStart;
+		int m_Ammo;
+		int m_Ammocost;
+		bool m_Got;
+		
+	} m_aWeapons[NUM_WEAPONS];
+	
+	int m_ActiveWeapon;
+	int m_LastWeapon;
+	int m_QueuedWeapon;
+	
+	int m_ReloadTimer;
+	int m_AttackTick;
+	
+	int m_DamageTaken;
+
+	int m_EmoteType;
+	int m_EmoteStop;
+	
+	// last tick that the player took any action ie some input
+	int m_LastAction;
+
+	// these are non-heldback inputs
+	CNetObj_PlayerInput m_LatestPrevInput;
+	CNetObj_PlayerInput m_LatestInput;
+
+	// input	
+	CNetObj_PlayerInput m_PrevInput;
+	CNetObj_PlayerInput m_Input;
+	int m_NumInputs;
+	int m_Jumped;
+	
+	int m_DamageTakenTick;
+
+	int m_Health;
+	int m_Armor;
+
+	// ninja
+	struct
+	{
+		vec2 m_ActivationDir;
+		int m_ActivationTick;
+		int m_CurrentMoveTime;
+		
+	} m_Ninja;
+
+	int m_PlayerState;// if the client is chatting, accessing a menu or so
+
+	// the player core for the physics	
+	CCharacterCore m_Core;
+	
+	// info for dead reckoning
+	int m_ReckoningTick; // tick that we are performing dead reckoning From
+	CCharacterCore m_SendCore; // core that we should send
+	CCharacterCore m_ReckoningCore; // the dead reckoning core
+
+};
+
+#endif
diff --git a/src/game/server/entities/character.hpp b/src/game/server/entities/character.hpp
deleted file mode 100644
index bd2f7afe..00000000
--- a/src/game/server/entities/character.hpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-
-#ifndef GAME_SERVER_ENTITY_CHARACTER_H
-#define GAME_SERVER_ENTITY_CHARACTER_H
-
-#include <game/server/entity.hpp>
-#include <game/generated/gs_data.hpp>
-#include <game/generated/g_protocol.hpp>
-
-#include <game/gamecore.hpp>
-
-enum
-{
-	WEAPON_GAME = -3, // team switching etc
-	WEAPON_SELF = -2, // console kill command
-	WEAPON_WORLD = -1, // death tiles etc
-};
-
-class CHARACTER : public ENTITY
-{
-	MACRO_ALLOC_POOL_ID()
-public:
-	// player controlling this character
-	class PLAYER *player;
-	
-	bool alive;
-
-	// weapon info
-	ENTITY *hitobjects[10];
-	int numobjectshit;
-	struct WEAPONSTAT
-	{
-		int ammoregenstart;
-		int ammo;
-		int ammocost;
-		bool got;
-	} weapons[NUM_WEAPONS];
-	
-	int active_weapon;
-	int last_weapon;
-	int queued_weapon;
-	
-	int reload_timer;
-	int attack_tick;
-	
-	int damage_taken;
-
-	int emote_type;
-	int emote_stop;
-
-	// TODO: clean this up
-	char skin_name[64];
-	int use_custom_color;
-	int color_body;
-	int color_feet;
-	
-	int last_action; // last tick that the player took any action ie some input
-
-	// these are non-heldback inputs
-	NETOBJ_PLAYER_INPUT latest_previnput;
-	NETOBJ_PLAYER_INPUT latest_input;
-
-	// input	
-	NETOBJ_PLAYER_INPUT previnput;
-	NETOBJ_PLAYER_INPUT input;
-	int num_inputs;
-	int jumped;
-	
-	int damage_taken_tick;
-
-	int health;
-	int armor;
-
-	// ninja
-	struct
-	{
-		vec2 activationdir;
-		int activationtick;
-		int currentmovetime;
-	} ninja;
-
-	//
-	//int score;
-	int team;
-	int player_state; // if the client is chatting, accessing a menu or so
-
-	// the player core for the physics	
-	CHARACTER_CORE core;
-	
-	// info for dead reckoning
-	int reckoning_tick; // tick that we are performing dead reckoning from
-	CHARACTER_CORE sendcore; // core that we should send
-	CHARACTER_CORE reckoningcore; // the dead reckoning core
-
-	//
-	CHARACTER();
-	
-	virtual void reset();
-	virtual void destroy();
-		
-	bool is_grounded();
-	
-	void set_weapon(int w);
-	
-	void handle_weaponswitch();
-	void do_weaponswitch();
-	
-	int handle_weapons();
-	int handle_ninja();
-
-	void on_predicted_input(NETOBJ_PLAYER_INPUT *new_input);
-	void on_direct_input(NETOBJ_PLAYER_INPUT *new_input);
-	void fire_weapon();
-
-	void die(int killer, int weapon);
-
-	bool take_damage(vec2 force, int dmg, int from, int weapon);	
-
-	
-	bool spawn(PLAYER *player, vec2 pos, int team);
-	//bool init_tryspawn(int team);
-	bool remove();
-
-	static const int phys_size = 28;
-
-	virtual void tick();
-	virtual void tick_defered();
-	virtual void snap(int snapping_client);
-	
-	bool increase_health(int amount);
-	bool increase_armor(int amount);
-};
-
-#endif
diff --git a/src/game/server/entities/laser.cpp b/src/game/server/entities/laser.cpp
index 2c6fa0ff..6bc26074 100644
--- a/src/game/server/entities/laser.cpp
+++ b/src/game/server/entities/laser.cpp
@@ -1,115 +1,105 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <engine/e_server_interface.h>
-#include <game/generated/g_protocol.hpp>
-#include <game/server/gamecontext.hpp>
-#include "laser.hpp"
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+#include <game/generated/protocol.h>
+#include <game/server/gamecontext.h>
+#include "laser.h"
 
-//////////////////////////////////////////////////
-// laser
-//////////////////////////////////////////////////
-LASER::LASER(vec2 pos, vec2 direction, float start_energy, int owner)
-: ENTITY(NETOBJTYPE_LASER)
+CLaser::CLaser(CGameWorld *pGameWorld, vec2 Pos, vec2 Direction, float StartEnergy, int Owner)
+: CEntity(pGameWorld, NETOBJTYPE_LASER)
 {
-	this->pos = pos;
-	this->owner = owner;
-	energy = start_energy;
-	dir = direction;
-	bounces = 0;
-	do_bounce();
-	
-	game.world.insert_entity(this);
+	m_Pos = Pos;
+	m_Owner = Owner;
+	m_Energy = StartEnergy;
+	m_Dir = Direction;
+	m_Bounces = 0;
+	m_EvalTick = 0;
+	GameWorld()->InsertEntity(this);
+	DoBounce();
 }
 
 
-bool LASER::hit_character(vec2 from, vec2 to)
+bool CLaser::HitCharacter(vec2 From, vec2 To)
 {
-	vec2 at;
-	CHARACTER *owner_char = game.get_player_char(owner);
-	CHARACTER *hit = game.world.intersect_character(pos, to, 0.0f, at, owner_char);
-	if(!hit)
+	vec2 At;
+	CCharacter *OwnerChar = GameServer()->GetPlayerChar(m_Owner);
+	CCharacter *Hit = GameServer()->m_World.IntersectCharacter(m_Pos, To, 0.f, At, OwnerChar);
+	if(!Hit)
 		return false;
 
-	this->from = from;
-	pos = at;
-	energy = -1;		
-	hit->take_damage(vec2(0,0), tuning.laser_damage, owner, WEAPON_RIFLE);
+	m_From = From;
+	m_Pos = At;
+	m_Energy = -1;		
+	Hit->TakeDamage(vec2(0.f, 0.f), GameServer()->Tuning()->m_LaserDamage, m_Owner, WEAPON_RIFLE);
 	return true;
 }
 
-void LASER::do_bounce()
+void CLaser::DoBounce()
 {
-	eval_tick = server_tick();
+	m_EvalTick = Server()->Tick();
 	
-	if(energy < 0)
+	if(m_Energy < 0)
 	{
-		//dbg_msg("laser", "%d removed", server_tick());
-		game.world.destroy_entity(this);
+		GameServer()->m_World.DestroyEntity(this);
 		return;
 	}
 	
-	vec2 to = pos + dir*energy;
-	vec2 org_to = to;
+	vec2 To = m_Pos + m_Dir * m_Energy;
+	vec2 OrgTo = To;
 	
-	if(col_intersect_line(pos, to, 0x0, &to))
+	if(GameServer()->Collision()->IntersectLine(m_Pos, To, 0x0, &To))
 	{
-		if(!hit_character(pos, to))
+		if(!HitCharacter(m_Pos, To))
 		{
 			// intersected
-			from = pos;
-			pos = to;
+			m_From = m_Pos;
+			m_Pos = To;
 
-			vec2 temp_pos = pos;
-			vec2 temp_dir = dir*4.0f;
+			vec2 TempPos = m_Pos;
+			vec2 TempDir = m_Dir * 4.0f;
 			
-			move_point(&temp_pos, &temp_dir, 1.0f, 0);
-			pos = temp_pos;
-			dir = normalize(temp_dir);
+			GameServer()->Collision()->MovePoint(&TempPos, &TempDir, 1.0f, 0);
+			m_Pos = TempPos;
+			m_Dir = normalize(TempDir);
 			
-			energy -= distance(from, pos) + tuning.laser_bounce_cost;
-			bounces++;
+			m_Energy -= distance(m_From, m_Pos) + GameServer()->Tuning()->m_LaserBounceCost;
+			m_Bounces++;
 			
-			if(bounces > tuning.laser_bounce_num)
-				energy = -1;
+			if(m_Bounces > GameServer()->Tuning()->m_LaserBounceNum)
+				m_Energy = -1;
 				
-			game.create_sound(pos, SOUND_RIFLE_BOUNCE);
+			GameServer()->CreateSound(m_Pos, SOUND_RIFLE_BOUNCE);
 		}
 	}
 	else
 	{
-		if(!hit_character(pos, to))
+		if(!HitCharacter(m_Pos, To))
 		{
-			from = pos;
-			pos = to;
-			energy = -1;
+			m_From = m_Pos;
+			m_Pos = To;
+			m_Energy = -1;
 		}
 	}
-		
-	//dbg_msg("laser", "%d done %f %f %f %f", server_tick(), from.x, from.y, pos.x, pos.y);
 }
 	
-void LASER::reset()
+void CLaser::Reset()
 {
-	game.world.destroy_entity(this);
+	GameServer()->m_World.DestroyEntity(this);
 }
 
-void LASER::tick()
+void CLaser::Tick()
 {
-	if(server_tick() > eval_tick+(server_tickspeed()*tuning.laser_bounce_delay)/1000.0f)
-	{
-		do_bounce();
-	}
-
+	if(Server()->Tick() > m_EvalTick+(Server()->TickSpeed()*GameServer()->Tuning()->m_LaserBounceDelay)/1000.0f)
+		DoBounce();
 }
 
-void LASER::snap(int snapping_client)
+void CLaser::Snap(int SnappingClient)
 {
-	if(networkclipped(snapping_client))
+	if(NetworkClipped(SnappingClient))
 		return;
 
-	NETOBJ_LASER *obj = (NETOBJ_LASER *)snap_new_item(NETOBJTYPE_LASER, id, sizeof(NETOBJ_LASER));
-	obj->x = (int)pos.x;
-	obj->y = (int)pos.y;
-	obj->from_x = (int)from.x;
-	obj->from_y = (int)from.y;
-	obj->start_tick = eval_tick;
+	CNetObj_Laser *pObj = static_cast<CNetObj_Laser *>(Server()->SnapNewItem(NETOBJTYPE_LASER, m_Id, sizeof(CNetObj_Laser)));
+	pObj->m_X = (int)m_Pos.x;
+	pObj->m_Y = (int)m_Pos.y;
+	pObj->m_FromX = (int)m_From.x;
+	pObj->m_FromY = (int)m_From.y;
+	pObj->m_StartTick = m_EvalTick;
 }
diff --git a/src/game/server/entities/laser.h b/src/game/server/entities/laser.h
new file mode 100644
index 00000000..040cfb4c
--- /dev/null
+++ b/src/game/server/entities/laser.h
@@ -0,0 +1,28 @@
+#ifndef GAME_SERVER_ENTITIES_LASER_H
+#define GAME_SERVER_ENTITIES_LASER_H
+
+#include <game/server/entity.h>
+
+class CLaser : public CEntity
+{
+public:
+	CLaser(CGameWorld *pGameWorld, vec2 Pos, vec2 Direction, float StartEnergy, int Owner);
+	
+	virtual void Reset();
+	virtual void Tick();
+	virtual void Snap(int SnappingClient);
+	
+protected:
+	bool HitCharacter(vec2 From, vec2 To);
+	void DoBounce();
+	
+private:
+	vec2 m_From;
+	vec2 m_Dir;
+	float m_Energy;
+	int m_Bounces;
+	int m_EvalTick;
+	int m_Owner;
+};
+
+#endif
diff --git a/src/game/server/entities/laser.hpp b/src/game/server/entities/laser.hpp
deleted file mode 100644
index aa4c2284..00000000
--- a/src/game/server/entities/laser.hpp
+++ /dev/null
@@ -1,31 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-
-#ifndef GAME_SERVER_ENTITY_LASER_H
-#define GAME_SERVER_ENTITY_LASER_H
-
-#include <game/server/entity.hpp>
-
-class CHARACTER;
-
-class LASER : public ENTITY
-{
-	vec2 from;
-	vec2 dir;
-	float energy;
-	int bounces;
-	int eval_tick;
-	int owner;
-	
-	bool hit_character(vec2 from, vec2 to);
-	void do_bounce();
-	
-public:
-	
-	LASER(vec2 pos, vec2 direction, float start_energy, int owner);
-	
-	virtual void reset();
-	virtual void tick();
-	virtual void snap(int snapping_client);
-};
-
-#endif
diff --git a/src/game/server/entities/pickup.cpp b/src/game/server/entities/pickup.cpp
index 436282cc..9798e2c3 100644
--- a/src/game/server/entities/pickup.cpp
+++ b/src/game/server/entities/pickup.cpp
@@ -1,143 +1,129 @@
-#include <engine/e_server_interface.h>
-#include <game/generated/g_protocol.hpp>
-#include <game/server/gamecontext.hpp>
-#include "pickup.hpp"
+#include <game/generated/protocol.h>
+#include <game/server/gamecontext.h>
+#include "pickup.h"
 
-//////////////////////////////////////////////////
-// pickup
-//////////////////////////////////////////////////
-PICKUP::PICKUP(int _type, int _subtype)
-: ENTITY(NETOBJTYPE_PICKUP)
+CPickup::CPickup(CGameWorld *pGameWorld, int Type, int SubType)
+: CEntity(pGameWorld, NETOBJTYPE_PICKUP)
 {
-	type = _type;
-	subtype = _subtype;
-	proximity_radius = phys_size;
+	m_Type = Type;
+	m_Subtype = SubType;
+	m_ProximityRadius = PickupPhysSize;
 
-	reset();
-
-	// TODO: should this be done here?
-	game.world.insert_entity(this);
+	Reset();
+	
+	GameWorld()->InsertEntity(this);
 }
 
-void PICKUP::reset()
+void CPickup::Reset()
 {
-	if (data->pickups[type].spawndelay > 0)
-		spawntick = server_tick() + server_tickspeed() * data->pickups[type].spawndelay;
+	if (g_pData->m_aPickups[m_Type].m_Spawndelay > 0)
+		m_SpawnTick = Server()->Tick() + Server()->TickSpeed() * g_pData->m_aPickups[m_Type].m_Spawndelay;
 	else
-		spawntick = -1;
+		m_SpawnTick = -1;
 }
 
-void PICKUP::tick()
+void CPickup::Tick()
 {
 	// wait for respawn
-	if(spawntick > 0)
+	if(m_SpawnTick > 0)
 	{
-		if(server_tick() > spawntick)
+		if(Server()->Tick() > m_SpawnTick)
 		{
 			// respawn
-			spawntick = -1;
+			m_SpawnTick = -1;
 
-			if(type == POWERUP_WEAPON)
-				game.create_sound(pos, SOUND_WEAPON_SPAWN);
+			if(m_Type == POWERUP_WEAPON)
+				GameServer()->CreateSound(m_Pos, SOUND_WEAPON_SPAWN);
 		}
 		else
 			return;
 	}
 	// Check if a player intersected us
-	CHARACTER *chr = game.world.closest_character(pos, 20.0f, 0);
-	if(chr)
+	CCharacter *pChr = GameServer()->m_World.ClosestCharacter(m_Pos, 20.0f, 0);
+	if(pChr && pChr->IsAlive())
 	{
 		// player picked us up, is someone was hooking us, let them go
-		int respawntime = -1;
-		switch (type)
+		int RespawnTime = -1;
+		switch (m_Type)
 		{
-		case POWERUP_HEALTH:
-			if(chr->increase_health(1))
-			{
-				game.create_sound(pos, SOUND_PICKUP_HEALTH);
-				respawntime = data->pickups[type].respawntime;
-			}
-			break;
-		case POWERUP_ARMOR:
-			if(chr->increase_armor(1))
-			{
-				game.create_sound(pos, SOUND_PICKUP_ARMOR);
-				respawntime = data->pickups[type].respawntime;
-			}
-			break;
+			case POWERUP_HEALTH:
+				if(pChr->IncreaseHealth(1))
+				{
+					GameServer()->CreateSound(m_Pos, SOUND_PICKUP_HEALTH);
+					RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime;
+				}
+				break;
+				
+			case POWERUP_ARMOR:
+				if(pChr->IncreaseArmor(1))
+				{
+					GameServer()->CreateSound(m_Pos, SOUND_PICKUP_ARMOR);
+					RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime;
+				}
+				break;
 
-		case POWERUP_WEAPON:
-			if(subtype >= 0 && subtype < NUM_WEAPONS)
-			{
-				if(chr->weapons[subtype].ammo < data->weapons.id[subtype].maxammo || !chr->weapons[subtype].got)
+			case POWERUP_WEAPON:
+				if(m_Subtype >= 0 && m_Subtype < NUM_WEAPONS)
 				{
-					chr->weapons[subtype].got = true;
-					chr->weapons[subtype].ammo = min(data->weapons.id[subtype].maxammo, chr->weapons[subtype].ammo + 10);
-					respawntime = data->pickups[type].respawntime;
+					if(pChr->GiveWeapon(m_Subtype, 10))
+					{
+						RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime;
 
-					// TODO: data compiler should take care of stuff like this
-					if(subtype == WEAPON_GRENADE)
-						game.create_sound(pos, SOUND_PICKUP_GRENADE);
-					else if(subtype == WEAPON_SHOTGUN)
-						game.create_sound(pos, SOUND_PICKUP_SHOTGUN);
-					else if(subtype == WEAPON_RIFLE)
-						game.create_sound(pos, SOUND_PICKUP_SHOTGUN);
+						if(m_Subtype == WEAPON_GRENADE)
+							GameServer()->CreateSound(m_Pos, SOUND_PICKUP_GRENADE);
+						else if(m_Subtype == WEAPON_SHOTGUN)
+							GameServer()->CreateSound(m_Pos, SOUND_PICKUP_SHOTGUN);
+						else if(m_Subtype == WEAPON_RIFLE)
+							GameServer()->CreateSound(m_Pos, SOUND_PICKUP_SHOTGUN);
 
-					if(chr->player)
-                    	game.send_weapon_pickup(chr->player->client_id, subtype);
+						if(pChr->GetPlayer())
+							GameServer()->SendWeaponPickup(pChr->GetPlayer()->GetCID(), m_Subtype);
+					}
 				}
-			}
-			break;
-		case POWERUP_NINJA:
-			{
-				// activate ninja on target player
-				chr->ninja.activationtick = server_tick();
-				chr->weapons[WEAPON_NINJA].got = true;
-				chr->weapons[WEAPON_NINJA].ammo = -1;
-				chr->last_weapon = chr->active_weapon;
-				chr->active_weapon = WEAPON_NINJA;
-				respawntime = data->pickups[type].respawntime;
-				game.create_sound(pos, SOUND_PICKUP_NINJA);
-
-				// loop through all players, setting their emotes
-				ENTITY *ents[64];
-				int num = game.world.find_entities(vec2(0, 0), 1000000, ents, 64, NETOBJTYPE_CHARACTER);
-				for (int i = 0; i < num; i++)
+				break;
+				
+			case POWERUP_NINJA:
 				{
-					CHARACTER *c = (CHARACTER *)ents[i];
-					if (c != chr)
+					// activate ninja on target player
+					pChr->GiveNinja();
+					RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime;
+
+					// loop through all players, setting their emotes
+					CEntity *apEnts[64];
+					int Num = GameServer()->m_World.FindEntities(vec2(0, 0), 1000000, apEnts, 64, NETOBJTYPE_CHARACTER);
+					
+					for (int i = 0; i < Num; ++i)
 					{
-						c->emote_type = EMOTE_SURPRISE;
-						c->emote_stop = server_tick() + server_tickspeed();
+						CCharacter *pC = static_cast<CCharacter *>(apEnts[i]);
+						if (pC != pChr)
+							pC->SetEmote(EMOTE_SURPRISE, Server()->Tick() + Server()->TickSpeed());
 					}
-				}
 
-				chr->emote_type = EMOTE_ANGRY;
-				chr->emote_stop = server_tick() + 1200 * server_tickspeed() / 1000;
+					pChr->SetEmote(EMOTE_ANGRY, Server()->Tick() + 1200 * Server()->TickSpeed() / 1000);
+					break;
+				}
 				
+			default:
 				break;
-			}
-		default:
-			break;
 		};
 
-		if(respawntime >= 0)
+		if(RespawnTime >= 0)
 		{
 			dbg_msg("game", "pickup player='%d:%s' item=%d/%d",
-				chr->player->client_id, server_clientname(chr->player->client_id), type, subtype);
-			spawntick = server_tick() + server_tickspeed() * respawntime;
+				pChr->GetPlayer()->GetCID(), Server()->ClientName(pChr->GetPlayer()->GetCID()), m_Type, m_Subtype);
+			m_SpawnTick = Server()->Tick() + Server()->TickSpeed() * RespawnTime;
 		}
 	}
 }
 
-void PICKUP::snap(int snapping_client)
+void CPickup::Snap(int SnappingClient)
 {
-	if(spawntick != -1)
+	if(m_SpawnTick != -1 || NetworkClipped(SnappingClient))
 		return;
 
-	NETOBJ_PICKUP *up = (NETOBJ_PICKUP *)snap_new_item(NETOBJTYPE_PICKUP, id, sizeof(NETOBJ_PICKUP));
-	up->x = (int)pos.x;
-	up->y = (int)pos.y;
-	up->type = type; // TODO: two diffrent types? what gives?
-	up->subtype = subtype;
+	CNetObj_Pickup *pP = static_cast<CNetObj_Pickup *>(Server()->SnapNewItem(NETOBJTYPE_PICKUP, m_Id, sizeof(CNetObj_Pickup)));
+	pP->m_X = (int)m_Pos.x;
+	pP->m_Y = (int)m_Pos.y;
+	pP->m_Type = m_Type;
+	pP->m_Subtype = m_Subtype;
 }
diff --git a/src/game/server/entities/pickup.h b/src/game/server/entities/pickup.h
new file mode 100644
index 00000000..c076464c
--- /dev/null
+++ b/src/game/server/entities/pickup.h
@@ -0,0 +1,23 @@
+#ifndef GAME_SERVER_ENTITIES_PICKUP_H
+#define GAME_SERVER_ENTITIES_PICKUP_H
+
+#include <game/server/entity.h>
+
+const int PickupPhysSize = 14;
+
+class CPickup : public CEntity
+{
+public:
+	CPickup(CGameWorld *pGameWorld, int Type, int SubType = 0);
+	
+	virtual void Reset();
+	virtual void Tick();
+	virtual void Snap(int SnappingClient);
+	
+private:
+	int m_Type;
+	int m_Subtype;
+	int m_SpawnTick;
+};
+
+#endif
diff --git a/src/game/server/entities/pickup.hpp b/src/game/server/entities/pickup.hpp
deleted file mode 100644
index cd480d92..00000000
--- a/src/game/server/entities/pickup.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-
-#ifndef GAME_SERVER_ENTITY_PICKUP_H
-#define GAME_SERVER_ENTITY_PICKUP_H
-
-#include <game/server/entity.hpp>
-
-// TODO: move to seperate file
-class PICKUP : public ENTITY
-{
-public:
-	static const int phys_size = 14;
-	
-	int type;
-	int subtype; // weapon type for instance?
-	int spawntick;
-	PICKUP(int _type, int _subtype = 0);
-	
-	virtual void reset();
-	virtual void tick();
-	virtual void snap(int snapping_client);
-};
-
-#endif
diff --git a/src/game/server/entities/projectile.cpp b/src/game/server/entities/projectile.cpp
index 2a8de766..18652ba1 100644
--- a/src/game/server/entities/projectile.cpp
+++ b/src/game/server/entities/projectile.cpp
@@ -1,105 +1,102 @@
-#include <engine/e_server_interface.h>
-#include <game/generated/g_protocol.hpp>
-#include <game/server/gamecontext.hpp>
-#include "projectile.hpp"
+#include <game/generated/protocol.h>
+#include <game/server/gamecontext.h>
+#include "projectile.h"
 
-
-//////////////////////////////////////////////////
-// projectile
-//////////////////////////////////////////////////
-PROJECTILE::PROJECTILE(int type, int owner, vec2 pos, vec2 dir, int span,
-	int damage, int flags, float force, int sound_impact, int weapon)
-: ENTITY(NETOBJTYPE_PROJECTILE)
+CProjectile::CProjectile(CGameWorld *pGameWorld, int Type, int Owner, vec2 Pos, vec2 Dir, int Span,
+		int Damage, bool Explosive, float Force, int SoundImpact, int Weapon)
+: CEntity(pGameWorld, NETOBJTYPE_PROJECTILE)
 {
-	this->type = type;
-	this->pos = pos;
-	this->direction = dir;
-	this->lifespan = span;
-	this->owner = owner;
-	this->flags = flags;
-	this->force = force;
-	this->damage = damage;
-	this->sound_impact = sound_impact;
-	this->weapon = weapon;
-	this->bounce = 0;
-	this->start_tick = server_tick();
-	game.world.insert_entity(this);
+	m_Type = Type;
+	m_Pos = Pos;
+	m_Direction = Dir;
+	m_LifeSpan = Span;
+	m_Owner = Owner;
+	m_Force = Force;
+	m_Damage = Damage;
+	m_SoundImpact = SoundImpact;
+	m_Weapon = Weapon;
+	m_StartTick = Server()->Tick();
+	m_Explosive = Explosive;
+
+	GameWorld()->InsertEntity(this);
 }
 
-void PROJECTILE::reset()
+void CProjectile::Reset()
 {
-	game.world.destroy_entity(this);
+	GameServer()->m_World.DestroyEntity(this);
 }
 
-vec2 PROJECTILE::get_pos(float time)
+vec2 CProjectile::GetPos(float Time)
 {
-	float curvature = 0;
-	float speed = 0;
-	if(type == WEAPON_GRENADE)
-	{
-		curvature = tuning.grenade_curvature;
-		speed = tuning.grenade_speed;
-	}
-	else if(type == WEAPON_SHOTGUN)
-	{
-		curvature = tuning.shotgun_curvature;
-		speed = tuning.shotgun_speed;
-	}
-	else if(type == WEAPON_GUN)
+	float Curvature = 0;
+	float Speed = 0;
+	
+	switch(m_Type)
 	{
-		curvature = tuning.gun_curvature;
-		speed = tuning.gun_speed;
+		case WEAPON_GRENADE:
+			Curvature = GameServer()->Tuning()->m_GrenadeCurvature;
+			Speed = GameServer()->Tuning()->m_GrenadeSpeed;
+			break;
+			
+		case WEAPON_SHOTGUN:
+			Curvature = GameServer()->Tuning()->m_ShotgunCurvature;
+			Speed = GameServer()->Tuning()->m_ShotgunSpeed;
+			break;
+			
+		case WEAPON_GUN:
+			Curvature = GameServer()->Tuning()->m_GunCurvature;
+			Speed = GameServer()->Tuning()->m_GunSpeed;
+			break;
 	}
 	
-	return calc_pos(pos, direction, curvature, speed, time);
+	return CalcPos(m_Pos, m_Direction, Curvature, Speed, Time);
 }
 
 
-void PROJECTILE::tick()
+void CProjectile::Tick()
 {
-	
-	float pt = (server_tick()-start_tick-1)/(float)server_tickspeed();
-	float ct = (server_tick()-start_tick)/(float)server_tickspeed();
-	vec2 prevpos = get_pos(pt);
-	vec2 curpos = get_pos(ct);
+	float Pt = (Server()->Tick()-m_StartTick-1)/(float)Server()->TickSpeed();
+	float Ct = (Server()->Tick()-m_StartTick)/(float)Server()->TickSpeed();
+	vec2 PrevPos = GetPos(Pt);
+	vec2 CurPos = GetPos(Ct);
+	int Collide = GameServer()->Collision()->IntersectLine(PrevPos, CurPos, &CurPos, 0);
+	CCharacter *OwnerChar = GameServer()->GetPlayerChar(m_Owner);
+	CCharacter *TargetChr = GameServer()->m_World.IntersectCharacter(PrevPos, CurPos, 6.0f, CurPos, OwnerChar);
 
-	lifespan--;
+	m_LifeSpan--;
 	
-	int collide = col_intersect_line(prevpos, curpos, &curpos, 0);
-	//int collide = col_check_point((int)curpos.x, (int)curpos.y);
-	CHARACTER *ownerchar = game.get_player_char(owner);
-	CHARACTER *targetchr = game.world.intersect_character(prevpos, curpos, 6.0f, curpos, ownerchar);
-	if(targetchr || collide || lifespan < 0)
+	if(TargetChr || Collide || m_LifeSpan < 0)
 	{
-		if(lifespan >= 0 || weapon == WEAPON_GRENADE)
-			game.create_sound(curpos, sound_impact);
+		if(m_LifeSpan >= 0 || m_Weapon == WEAPON_GRENADE)
+			GameServer()->CreateSound(CurPos, m_SoundImpact);
 
-		if(flags & PROJECTILE_FLAGS_EXPLODE)
-			game.create_explosion(curpos, owner, weapon, false);
-		else if(targetchr)
-			targetchr->take_damage(direction * max(0.001f, force), damage, owner, weapon);
+		if(m_Explosive)
+			GameServer()->CreateExplosion(CurPos, m_Owner, m_Weapon, false);
+			
+		else if(TargetChr)
+			TargetChr->TakeDamage(m_Direction * max(0.001f, m_Force), m_Damage, m_Owner, m_Weapon);
 
-		game.world.destroy_entity(this);
+		GameServer()->m_World.DestroyEntity(this);
 	}
 }
 
-void PROJECTILE::fill_info(NETOBJ_PROJECTILE *proj)
+void CProjectile::FillInfo(CNetObj_Projectile *pProj)
 {
-	proj->x = (int)pos.x;
-	proj->y = (int)pos.y;
-	proj->vx = (int)(direction.x*100.0f);
-	proj->vy = (int)(direction.y*100.0f);
-	proj->start_tick = start_tick;
-	proj->type = type;
+	pProj->m_X = (int)m_Pos.x;
+	pProj->m_Y = (int)m_Pos.y;
+	pProj->m_VelX = (int)(m_Direction.x*100.0f);
+	pProj->m_VelY = (int)(m_Direction.y*100.0f);
+	pProj->m_StartTick = m_StartTick;
+	pProj->m_Type = m_Type;
 }
 
-void PROJECTILE::snap(int snapping_client)
+void CProjectile::Snap(int SnappingClient)
 {
-	float ct = (server_tick()-start_tick)/(float)server_tickspeed();
+	float Ct = (Server()->Tick()-m_StartTick)/(float)Server()->TickSpeed();
 	
-	if(networkclipped(snapping_client, get_pos(ct)))
+	if(NetworkClipped(SnappingClient, GetPos(Ct)))
 		return;
 
-	NETOBJ_PROJECTILE *proj = (NETOBJ_PROJECTILE *)snap_new_item(NETOBJTYPE_PROJECTILE, id, sizeof(NETOBJ_PROJECTILE));
-	fill_info(proj);
+	CNetObj_Projectile *pProj = static_cast<CNetObj_Projectile *>(Server()->SnapNewItem(NETOBJTYPE_PROJECTILE, m_Id, sizeof(CNetObj_Projectile)));
+	FillInfo(pProj);
 }
diff --git a/src/game/server/entities/projectile.h b/src/game/server/entities/projectile.h
new file mode 100644
index 00000000..87f4f6c3
--- /dev/null
+++ b/src/game/server/entities/projectile.h
@@ -0,0 +1,30 @@
+#ifndef GAME_SERVER_ENTITIES_PROJECTILE_H
+#define GAME_SERVER_ENTITIES_PROJECTILE_H
+
+class CProjectile : public CEntity
+{
+public:
+	CProjectile(CGameWorld *pGameWorld, int Type, int Owner, vec2 Pos, vec2 Dir, int Span,
+		int Damage, bool Explosive, float Force, int SoundImpact, int Weapon);
+
+	vec2 GetPos(float Time);
+	void FillInfo(CNetObj_Projectile *pProj);
+
+	virtual void Reset();
+	virtual void Tick();
+	virtual void Snap(int SnappingClient);
+	
+private:
+	vec2 m_Direction;
+	int m_LifeSpan;
+	int m_Owner;
+	int m_Type;
+	int m_Damage;
+	int m_SoundImpact;
+	int m_Weapon;
+	float m_Force;
+	int m_StartTick;
+	bool m_Explosive;
+};
+
+#endif
diff --git a/src/game/server/entities/projectile.hpp b/src/game/server/entities/projectile.hpp
deleted file mode 100644
index a5c3b88f..00000000
--- a/src/game/server/entities/projectile.hpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-
-#ifndef GAME_SERVER_ENTITY_PROJECTILE_H
-#define GAME_SERVER_ENTITY_PROJECTILE_H
-
-class PROJECTILE : public ENTITY
-{
-public:
-	enum
-	{
-		PROJECTILE_FLAGS_EXPLODE = 1 << 0,
-	};
-	
-	vec2 direction;
-	int lifespan;
-	int owner;
-	int type;
-	int flags;
-	int damage;
-	int sound_impact;
-	int weapon;
-	int bounce;
-	float force;
-	int start_tick;
-	
-	PROJECTILE(int type, int owner, vec2 pos, vec2 vel, int span,
-		int damage, int flags, float force, int sound_impact, int weapon);
-
-	vec2 get_pos(float time);
-	void fill_info(NETOBJ_PROJECTILE *proj);
-
-	virtual void reset();
-	virtual void tick();
-	virtual void snap(int snapping_client);
-};
-
-#endif
diff --git a/src/game/server/entity.cpp b/src/game/server/entity.cpp
index 8e3345ab..d17c3fab 100644
--- a/src/game/server/entity.cpp
+++ b/src/game/server/entity.cpp
@@ -1,49 +1,50 @@
 
-#include <engine/e_server_interface.h>
-#include "entity.hpp"
-#include "gamecontext.hpp"
+#include "entity.h"
+#include "gamecontext.h"
 
 //////////////////////////////////////////////////
 // Entity
 //////////////////////////////////////////////////
-ENTITY::ENTITY(int objtype)
+CEntity::CEntity(CGameWorld *pGameWorld, int ObjType)
 {
-	this->objtype = objtype;
-	pos = vec2(0,0);
-	proximity_radius = 0;
+	m_pGameWorld = pGameWorld;
+	
+	m_Objtype = ObjType;
+	m_Pos = vec2(0,0);
+	m_ProximityRadius = 0;
 
-	marked_for_destroy = false;	
-	id = snap_new_id();
+	m_MarkedForDestroy = false;	
+	m_Id = Server()->SnapNewID();
 
-	next_entity = 0;
-	prev_entity = 0;
-	prev_type_entity = 0;
-	next_type_entity = 0;
+	m_pNextEntity = 0;
+	m_pPrevEntity = 0;
+	m_pPrevTypeEntity = 0;
+	m_pNextTypeEntity = 0;
 }
 
-ENTITY::~ENTITY()
+CEntity::~CEntity()
 {
-	game.world.remove_entity(this);
-	snap_free_id(id);
+	GameWorld()->RemoveEntity(this);
+	Server()->SnapFreeID(m_Id);
 }
 
-int ENTITY::networkclipped(int snapping_client)
+int CEntity::NetworkClipped(int SnappingClient)
 {
-	return networkclipped(snapping_client, pos);
+	return NetworkClipped(SnappingClient, m_Pos);
 }
 
-int ENTITY::networkclipped(int snapping_client, vec2 check_pos)
+int CEntity::NetworkClipped(int SnappingClient, vec2 CheckPos)
 {
-	if(snapping_client == -1)
+	if(SnappingClient == -1)
 		return 0;
 	
-	float dx = game.players[snapping_client]->view_pos.x-check_pos.x;
-	float dy = game.players[snapping_client]->view_pos.y-check_pos.y;
+	float dx = GameServer()->m_apPlayers[SnappingClient]->m_ViewPos.x-CheckPos.x;
+	float dy = GameServer()->m_apPlayers[SnappingClient]->m_ViewPos.y-CheckPos.y;
 	
-	if(fabs(dx) > 1000.0f || fabs(dy) > 800.0f)
+	if(absolute(dx) > 1000.0f || absolute(dy) > 800.0f)
 		return 1;
 	
-	if(distance(game.players[snapping_client]->view_pos, check_pos) > 1100.0f)
+	if(distance(GameServer()->m_apPlayers[SnappingClient]->m_ViewPos, CheckPos) > 1100.0f)
 		return 1;
 	return 0;
 }
diff --git a/src/game/server/entity.hpp b/src/game/server/entity.h
index debe57b6..b7fd3d94 100644
--- a/src/game/server/entity.hpp
+++ b/src/game/server/entity.h
@@ -2,101 +2,109 @@
 #define GAME_SERVER_ENTITY_H
 
 #include <new>
-#include <base/vmath.hpp>
+#include <base/vmath.h>
+#include <game/server/gameworld.h>
 
 #define MACRO_ALLOC_HEAP() \
 	public: \
-	void *operator new(size_t size) \
+	void *operator new(size_t Size) \
 	{ \
-		void *p = mem_alloc(size, 1); \
+		void *p = mem_alloc(Size, 1); \
 		/*dbg_msg("", "++ %p %d", p, size);*/ \
-		mem_zero(p, size); \
+		mem_zero(p, Size); \
 		return p; \
 	} \
-	void operator delete(void *p) \
+	void operator delete(void *pPtr) \
 	{ \
 		/*dbg_msg("", "-- %p", p);*/ \
-		mem_free(p); \
+		mem_free(pPtr); \
 	} \
 	private:
 
 #define MACRO_ALLOC_POOL_ID() \
 	public: \
-	void *operator new(size_t size, int id); \
+	void *operator new(size_t Size, int id); \
 	void operator delete(void *p); \
 	private:
 	
-#define MACRO_ALLOC_POOL_ID_IMPL(POOLTYPE, poolsize) \
-	static char pool_data_##POOLTYPE[poolsize][sizeof(POOLTYPE)] = {{0}}; \
-	static int pool_used_##POOLTYPE[poolsize] = {0}; \
-	void *POOLTYPE::operator new(size_t size, int id) \
+#define MACRO_ALLOC_POOL_ID_IMPL(POOLTYPE, PoolSize) \
+	static char ms_PoolData##POOLTYPE[PoolSize][sizeof(POOLTYPE)] = {{0}}; \
+	static int ms_PoolUsed##POOLTYPE[PoolSize] = {0}; \
+	void *POOLTYPE::operator new(size_t Size, int id) \
 	{ \
-		dbg_assert(sizeof(POOLTYPE) == size, "size error"); \
-		dbg_assert(!pool_used_##POOLTYPE[id], "already used"); \
+		dbg_assert(sizeof(POOLTYPE) == Size, "size error"); \
+		dbg_assert(!ms_PoolUsed##POOLTYPE[id], "already used"); \
 		/*dbg_msg("pool", "++ %s %d", #POOLTYPE, id);*/ \
-		pool_used_##POOLTYPE[id] = 1; \
-		mem_zero(pool_data_##POOLTYPE[id], size); \
-		return pool_data_##POOLTYPE[id]; \
+		ms_PoolUsed##POOLTYPE[id] = 1; \
+		mem_zero(ms_PoolData##POOLTYPE[id], Size); \
+		return ms_PoolData##POOLTYPE[id]; \
 	} \
 	void POOLTYPE::operator delete(void *p) \
 	{ \
-		int id = (POOLTYPE*)p - (POOLTYPE*)pool_data_##POOLTYPE; \
-		dbg_assert(pool_used_##POOLTYPE[id], "not used"); \
+		int id = (POOLTYPE*)p - (POOLTYPE*)ms_PoolData##POOLTYPE; \
+		dbg_assert(ms_PoolUsed##POOLTYPE[id], "not used"); \
 		/*dbg_msg("pool", "-- %s %d", #POOLTYPE, id);*/ \
-		pool_used_##POOLTYPE[id] = 0; \
-		mem_zero(pool_data_##POOLTYPE[id], sizeof(POOLTYPE)); \
+		ms_PoolUsed##POOLTYPE[id] = 0; \
+		mem_zero(ms_PoolData##POOLTYPE[id], sizeof(POOLTYPE)); \
 	}
 	
 /*
 	Class: Entity
 		Basic entity class.
 */
-class ENTITY
+class CEntity
 {
 	MACRO_ALLOC_HEAP()
 private:
-	friend class GAMEWORLD; // thy these?
-	ENTITY *prev_entity;
-	ENTITY *next_entity;
+	friend class CGameWorld; // thy these?
+	CEntity *m_pPrevEntity;
+	CEntity *m_pNextEntity;
 
-	ENTITY *prev_type_entity;
-	ENTITY *next_type_entity;
+	CEntity *m_pPrevTypeEntity;
+	CEntity *m_pNextTypeEntity;
+	
+	class CGameWorld *m_pGameWorld;
 protected:
-	bool marked_for_destroy;
-	int id;
-	int objtype;
+	bool m_MarkedForDestroy;
+	int m_Id;
+	int m_Objtype;
 public:
-	ENTITY(int objtype);
-	virtual ~ENTITY();
+	CEntity(CGameWorld *pGameWorld, int Objtype);
+	virtual ~CEntity();
+	
+	class CGameWorld *GameWorld() { return m_pGameWorld; }
+	class CGameContext *GameServer() { return GameWorld()->GameServer(); }
+	class IServer *Server() { return GameWorld()->Server(); }
+	
 	
-	ENTITY *typenext() { return next_type_entity; }
-	ENTITY *typeprev() { return prev_type_entity; }
+	CEntity *TypeNext() { return m_pNextTypeEntity; }
+	CEntity *TypePrev() { return m_pPrevTypeEntity; }
 
 	/*
 		Function: destroy
 			Destorys the entity.
 	*/
-	virtual void destroy() { delete this; }
+	virtual void Destroy() { delete this; }
 		
 	/*
 		Function: reset
 			Called when the game resets the map. Puts the entity
 			back to it's starting state or perhaps destroys it.
 	*/
-	virtual void reset() {}
+	virtual void Reset() {}
 	
 	/*
 		Function: tick
 			Called progress the entity to the next tick. Updates
 			and moves the entity to it's new state and position.
 	*/
-	virtual void tick() {}
+	virtual void Tick() {}
 
 	/*
 		Function: tick_defered
 			Called after all entities tick() function has been called.
 	*/
-	virtual void tick_defered() {}
+	virtual void TickDefered() {}
 	
 	/*
 		Function: snap
@@ -109,7 +117,7 @@ public:
 				snapshot of everything in the game for demo
 				recording.
 	*/
-	virtual void snap(int snapping_client) {}
+	virtual void Snap(int SnappingClient) {}
 	
 	/*
 		Function: networkclipped(int snapping_client)
@@ -125,21 +133,21 @@ public:
 		Returns:
 			Non-zero if the entity doesn't have to be in the snapshot.
 	*/
-	int networkclipped(int snapping_client);
-	int networkclipped(int snapping_client, vec2 check_pos);
+	int NetworkClipped(int SnappingClient);
+	int NetworkClipped(int SnappingClient, vec2 CheckPos);
 		
 
 	/*
 		Variable: proximity_radius
 			Contains the physical size of the entity.
 	*/
-	float proximity_radius;
+	float m_ProximityRadius;
 	
 	/*
 		Variable: pos
 			Contains the current posititon of the entity.
 	*/
-	vec2 pos;
+	vec2 m_Pos;
 };
 
 #endif
diff --git a/src/game/server/eventhandler.cpp b/src/game/server/eventhandler.cpp
index 761eaf2c..48b6689e 100644
--- a/src/game/server/eventhandler.cpp
+++ b/src/game/server/eventhandler.cpp
@@ -1,48 +1,54 @@
-#include "eventhandler.hpp"
-#include "gamecontext.hpp"
+#include "eventhandler.h"
+#include "gamecontext.h"
 
 //////////////////////////////////////////////////
 // Event handler
 //////////////////////////////////////////////////
-EVENTHANDLER::EVENTHANDLER()
+CEventHandler::CEventHandler()
 {
-	clear();
+	m_pGameServer = 0;
+	Clear();
 }
 
-void *EVENTHANDLER::create(int type, int size, int mask)
+void CEventHandler::SetGameServer(CGameContext *pGameServer)
 {
-	if(num_events == MAX_EVENTS)
+	m_pGameServer = pGameServer;
+}
+
+void *CEventHandler::Create(int Type, int Size, int Mask)
+{
+	if(m_NumEvents == MAX_EVENTS)
 		return 0;
-	if(current_offset+size >= MAX_DATASIZE)
+	if(m_CurrentOffset+Size >= MAX_DATASIZE)
 		return 0;
 
-	void *p = &data[current_offset];
-	offsets[num_events] = current_offset;
-	types[num_events] = type;
-	sizes[num_events] = size;
-	client_masks[num_events] = mask;
-	current_offset += size;
-	num_events++;
+	void *p = &m_aData[m_CurrentOffset];
+	m_aOffsets[m_NumEvents] = m_CurrentOffset;
+	m_aTypes[m_NumEvents] = Type;
+	m_aSizes[m_NumEvents] = Size;
+	m_aClientMasks[m_NumEvents] = Mask;
+	m_CurrentOffset += Size;
+	m_NumEvents++;
 	return p;
 }
 
-void EVENTHANDLER::clear()
+void CEventHandler::Clear()
 {
-	num_events = 0;
-	current_offset = 0;
+	m_NumEvents = 0;
+	m_CurrentOffset = 0;
 }
 
-void EVENTHANDLER::snap(int snapping_client)
+void CEventHandler::Snap(int SnappingClient)
 {
-	for(int i = 0; i < num_events; i++)
+	for(int i = 0; i < m_NumEvents; i++)
 	{
-		if(snapping_client == -1 || cmask_is_set(client_masks[i], snapping_client))
+		if(SnappingClient == -1 || CmaskIsSet(m_aClientMasks[i], SnappingClient))
 		{
-			NETEVENT_COMMON *ev = (NETEVENT_COMMON *)&data[offsets[i]];
-			if(snapping_client == -1 || distance(game.players[snapping_client]->view_pos, vec2(ev->x, ev->y)) < 1500.0f)
+			NETEVENT_COMMON *ev = (NETEVENT_COMMON *)&m_aData[m_aOffsets[i]];
+			if(SnappingClient == -1 || distance(GameServer()->m_apPlayers[SnappingClient]->m_ViewPos, vec2(ev->m_X, ev->m_Y)) < 1500.0f)
 			{
-				void *d = snap_new_item(types[i], i, sizes[i]);
-				mem_copy(d, &data[offsets[i]], sizes[i]);
+				void *d = GameServer()->Server()->SnapNewItem(m_aTypes[i], i, m_aSizes[i]);
+				mem_copy(d, &m_aData[m_aOffsets[i]], m_aSizes[i]);
 			}
 		}
 	}
diff --git a/src/game/server/eventhandler.h b/src/game/server/eventhandler.h
new file mode 100644
index 00000000..3833efe0
--- /dev/null
+++ b/src/game/server/eventhandler.h
@@ -0,0 +1,30 @@
+#ifndef GAME_SERVER_EVENTHANDLER_H
+#define GAME_SERVER_EVENTHANDLER_H
+
+//
+class CEventHandler
+{
+	static const int MAX_EVENTS = 128;
+	static const int MAX_DATASIZE = 128*64;
+
+	int m_aTypes[MAX_EVENTS];  // TODO: remove some of these arrays
+	int m_aOffsets[MAX_EVENTS];
+	int m_aSizes[MAX_EVENTS];
+	int m_aClientMasks[MAX_EVENTS];
+	char m_aData[MAX_DATASIZE];
+	
+	class CGameContext *m_pGameServer;
+	
+	int m_CurrentOffset;
+	int m_NumEvents;
+public:
+	CGameContext *GameServer() const { return m_pGameServer; }
+	void SetGameServer(CGameContext *pGameServer);
+	
+	CEventHandler();
+	void *Create(int Type, int Size, int Mask = -1);
+	void Clear();
+	void Snap(int SnappingClient);
+};
+
+#endif
diff --git a/src/game/server/eventhandler.hpp b/src/game/server/eventhandler.hpp
deleted file mode 100644
index 4d513154..00000000
--- a/src/game/server/eventhandler.hpp
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef GAME_SERVER_EVENTHANDLER_H
-#define GAME_SERVER_EVENTHANDLER_H
-
-//
-class EVENTHANDLER
-{
-	static const int MAX_EVENTS = 128;
-	static const int MAX_DATASIZE = 128*64;
-
-	int types[MAX_EVENTS];  // TODO: remove some of these arrays
-	int offsets[MAX_EVENTS];
-	int sizes[MAX_EVENTS];
-	int client_masks[MAX_EVENTS];
-	char data[MAX_DATASIZE];
-	
-	int current_offset;
-	int num_events;
-public:
-	EVENTHANDLER();
-	void *create(int type, int size, int mask = -1);
-	void clear();
-	void snap(int snapping_client);
-};
-
-#endif
diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp
index 736d437f..795bb65f 100644
--- a/src/game/server/gamecontext.cpp
+++ b/src/game/server/gamecontext.cpp
@@ -1,99 +1,143 @@
-#include <string.h>
 #include <new>
-#include <engine/e_server_interface.h>
-#include "gamecontext.hpp"
+#include <base/math.h>
+#include <engine/shared/config.h>
+#include <engine/map.h>
+#include <engine/console.h>
+#include "gamecontext.h"
+#include <game/version.h>
+#include <game/collision.h>
+#include <game/gamecore.h>
+#include "gamemodes/dm.h"
+#include "gamemodes/tdm.h"
+#include "gamemodes/ctf.h"
+#include "gamemodes/mod.h"
 
-GAMECONTEXT game;
+enum
+{
+	RESET,
+	NO_RESET
+};
 
-GAMECONTEXT::GAMECONTEXT()
+void CGameContext::Construct(int Resetting)
 {
+	m_Resetting = 0;
+	m_pServer = 0;
+	
 	for(int i = 0; i < MAX_CLIENTS; i++)
-		players[i] = 0;
+		m_apPlayers[i] = 0;
 	
-	controller = 0;
-	vote_closetime = 0;
+	m_pController = 0;
+	m_VoteCloseTime = 0;
+	m_pVoteOptionFirst = 0;
+	m_pVoteOptionLast = 0;
+
+	if(Resetting==NO_RESET)
+		m_pVoteOptionHeap = new CHeap();
+}
+
+CGameContext::CGameContext(int Resetting)
+{
+	Construct(Resetting);
+}
+
+CGameContext::CGameContext()
+{
+	Construct(NO_RESET);
 }
 
-GAMECONTEXT::~GAMECONTEXT()
+CGameContext::~CGameContext()
 {
 	for(int i = 0; i < MAX_CLIENTS; i++)
-		delete players[i];
+		delete m_apPlayers[i];
+	if(!m_Resetting)
+		delete m_pVoteOptionHeap;
 }
 
-void GAMECONTEXT::clear()
+void CGameContext::Clear()
 {
-	this->~GAMECONTEXT();
+	CHeap *pVoteOptionHeap = m_pVoteOptionHeap;
+	CVoteOption *pVoteOptionFirst = m_pVoteOptionFirst;
+	CVoteOption *pVoteOptionLast = m_pVoteOptionLast;
+	CTuningParams Tuning = m_Tuning;
+
+	m_Resetting = true;
+	this->~CGameContext();
 	mem_zero(this, sizeof(*this));
-	new (this) GAMECONTEXT();
+	new (this) CGameContext(RESET);
+
+	m_pVoteOptionHeap = pVoteOptionHeap;
+	m_pVoteOptionFirst = pVoteOptionFirst;
+	m_pVoteOptionLast = pVoteOptionLast;
+	m_Tuning = Tuning;
 }
 
 
-class CHARACTER *GAMECONTEXT::get_player_char(int client_id)
+class CCharacter *CGameContext::GetPlayerChar(int ClientId)
 {
-	if(client_id < 0 || client_id >= MAX_CLIENTS || !players[client_id])
+	if(ClientId < 0 || ClientId >= MAX_CLIENTS || !m_apPlayers[ClientId])
 		return 0;
-	return players[client_id]->get_character();
+	return m_apPlayers[ClientId]->GetCharacter();
 }
 
-void GAMECONTEXT::create_damageind(vec2 p, float angle, int amount)
+void CGameContext::CreateDamageInd(vec2 p, float Angle, int Amount)
 {
-	float a = 3 * 3.14159f / 2 + angle;
+	float a = 3 * 3.14159f / 2 + Angle;
 	//float a = get_angle(dir);
 	float s = a-pi/3;
 	float e = a+pi/3;
-	for(int i = 0; i < amount; i++)
+	for(int i = 0; i < Amount; i++)
 	{
-		float f = mix(s, e, float(i+1)/float(amount+2));
-		NETEVENT_DAMAGEIND *ev = (NETEVENT_DAMAGEIND *)events.create(NETEVENTTYPE_DAMAGEIND, sizeof(NETEVENT_DAMAGEIND));
+		float f = mix(s, e, float(i+1)/float(Amount+2));
+		NETEVENT_DAMAGEIND *ev = (NETEVENT_DAMAGEIND *)m_Events.Create(NETEVENTTYPE_DAMAGEIND, sizeof(NETEVENT_DAMAGEIND));
 		if(ev)
 		{
-			ev->x = (int)p.x;
-			ev->y = (int)p.y;
-			ev->angle = (int)(f*256.0f);
+			ev->m_X = (int)p.x;
+			ev->m_Y = (int)p.y;
+			ev->m_Angle = (int)(f*256.0f);
 		}
 	}
 }
 
-void GAMECONTEXT::create_hammerhit(vec2 p)
+void CGameContext::CreateHammerHit(vec2 p)
 {
 	// create the event
-	NETEVENT_HAMMERHIT *ev = (NETEVENT_HAMMERHIT *)events.create(NETEVENTTYPE_HAMMERHIT, sizeof(NETEVENT_HAMMERHIT));
+	NETEVENT_HAMMERHIT *ev = (NETEVENT_HAMMERHIT *)m_Events.Create(NETEVENTTYPE_HAMMERHIT, sizeof(NETEVENT_HAMMERHIT));
 	if(ev)
 	{
-		ev->x = (int)p.x;
-		ev->y = (int)p.y;
+		ev->m_X = (int)p.x;
+		ev->m_Y = (int)p.y;
 	}
 }
 
 
-void GAMECONTEXT::create_explosion(vec2 p, int owner, int weapon, bool bnodamage)
+void CGameContext::CreateExplosion(vec2 p, int Owner, int Weapon, bool NoDamage)
 {
 	// create the event
-	NETEVENT_EXPLOSION *ev = (NETEVENT_EXPLOSION *)events.create(NETEVENTTYPE_EXPLOSION, sizeof(NETEVENT_EXPLOSION));
+	NETEVENT_EXPLOSION *ev = (NETEVENT_EXPLOSION *)m_Events.Create(NETEVENTTYPE_EXPLOSION, sizeof(NETEVENT_EXPLOSION));
 	if(ev)
 	{
-		ev->x = (int)p.x;
-		ev->y = (int)p.y;
+		ev->m_X = (int)p.x;
+		ev->m_Y = (int)p.y;
 	}
 
-	if (!bnodamage)
+	if (!NoDamage)
 	{
 		// deal damage
-		CHARACTER *ents[64];
-		float radius = 135.0f;
-		float innerradius = 48.0f;
-		int num = game.world.find_entities(p, radius, (ENTITY**)ents, 64, NETOBJTYPE_CHARACTER);
-		for(int i = 0; i < num; i++)
+		CCharacter *apEnts[64];
+		float Radius = 135.0f;
+		float InnerRadius = 48.0f;
+		int Num = m_World.FindEntities(p, Radius, (CEntity**)apEnts, 64, NETOBJTYPE_CHARACTER);
+		for(int i = 0; i < Num; i++)
 		{
-			vec2 diff = ents[i]->pos - p;
-			vec2 forcedir(0,1);
-			float l = length(diff);
+			vec2 Diff = apEnts[i]->m_Pos - p;
+			vec2 ForceDir(0,1);
+			float l = length(Diff);
 			if(l)
-				forcedir = normalize(diff);
-			l = 1-clamp((l-innerradius)/(radius-innerradius), 0.0f, 1.0f);
-			float dmg = 6 * l;
-			if((int)dmg)
-				ents[i]->take_damage(forcedir*dmg*2, (int)dmg, owner, weapon);
+				ForceDir = normalize(Diff);
+			l = 1-clamp((l-InnerRadius)/(Radius-InnerRadius), 0.0f, 1.0f);
+			float Dmg = 6 * l;
+			if((int)Dmg)
+				apEnts[i]->TakeDamage(ForceDir*Dmg*2, (int)Dmg, Owner, Weapon);
 		}
 	}
 }
@@ -110,273 +154,893 @@ void create_smoke(vec2 p)
 	}
 }*/
 
-void GAMECONTEXT::create_playerspawn(vec2 p)
+void CGameContext::CreatePlayerSpawn(vec2 p)
 {
 	// create the event
-	NETEVENT_SPAWN *ev = (NETEVENT_SPAWN *)events.create(NETEVENTTYPE_SPAWN, sizeof(NETEVENT_SPAWN));
+	NETEVENT_SPAWN *ev = (NETEVENT_SPAWN *)m_Events.Create(NETEVENTTYPE_SPAWN, sizeof(NETEVENT_SPAWN));
 	if(ev)
 	{
-		ev->x = (int)p.x;
-		ev->y = (int)p.y;
+		ev->m_X = (int)p.x;
+		ev->m_Y = (int)p.y;
 	}
 }
 
-void GAMECONTEXT::create_death(vec2 p, int cid)
+void CGameContext::CreateDeath(vec2 p, int ClientId)
 {
 	// create the event
-	NETEVENT_DEATH *ev = (NETEVENT_DEATH *)events.create(NETEVENTTYPE_DEATH, sizeof(NETEVENT_DEATH));
+	NETEVENT_DEATH *ev = (NETEVENT_DEATH *)m_Events.Create(NETEVENTTYPE_DEATH, sizeof(NETEVENT_DEATH));
 	if(ev)
 	{
-		ev->x = (int)p.x;
-		ev->y = (int)p.y;
-		ev->cid = cid;
+		ev->m_X = (int)p.x;
+		ev->m_Y = (int)p.y;
+		ev->m_ClientId = ClientId;
 	}
 }
 
-void GAMECONTEXT::create_sound(vec2 pos, int sound, int mask)
+void CGameContext::CreateSound(vec2 Pos, int Sound, int Mask)
 {
-	if (sound < 0)
+	if (Sound < 0)
 		return;
 
 	// create a sound
-	NETEVENT_SOUNDWORLD *ev = (NETEVENT_SOUNDWORLD *)events.create(NETEVENTTYPE_SOUNDWORLD, sizeof(NETEVENT_SOUNDWORLD), mask);
+	NETEVENT_SOUNDWORLD *ev = (NETEVENT_SOUNDWORLD *)m_Events.Create(NETEVENTTYPE_SOUNDWORLD, sizeof(NETEVENT_SOUNDWORLD), Mask);
 	if(ev)
 	{
-		ev->x = (int)pos.x;
-		ev->y = (int)pos.y;
-		ev->soundid = sound;
+		ev->m_X = (int)Pos.x;
+		ev->m_Y = (int)Pos.y;
+		ev->m_SoundId = Sound;
 	}
 }
 
-void GAMECONTEXT::create_sound_global(int sound, int target)
+void CGameContext::CreateSoundGlobal(int Sound, int Target)
 {
-	if (sound < 0)
+	if (Sound < 0)
 		return;
 
-	NETMSG_SV_SOUNDGLOBAL msg;
-	msg.soundid = sound;
-	msg.pack(MSGFLAG_VITAL);
-	server_send_msg(target);
+	CNetMsg_Sv_SoundGlobal Msg;
+	Msg.m_Soundid = Sound;
+	Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, Target);
 }
 
 
-void GAMECONTEXT::send_chat_target(int to, const char *text)
+void CGameContext::SendChatTarget(int To, const char *pText)
 {
-	NETMSG_SV_CHAT msg;
-	msg.team = 0;
-	msg.cid = -1;
-	msg.message = text;
-	msg.pack(MSGFLAG_VITAL);
-	server_send_msg(to);
+	CNetMsg_Sv_Chat Msg;
+	Msg.m_Team = 0;
+	Msg.m_Cid = -1;
+	Msg.m_pMessage = pText;
+	Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, To);
 }
 
 
-void GAMECONTEXT::send_chat(int chatter_cid, int team, const char *text)
+void CGameContext::SendChat(int ChatterClientId, int Team, const char *pText)
 {
-	if(chatter_cid >= 0 && chatter_cid < MAX_CLIENTS)
-		dbg_msg("chat", "%d:%d:%s: %s", chatter_cid, team, server_clientname(chatter_cid), text);
+	if(ChatterClientId >= 0 && ChatterClientId < MAX_CLIENTS)
+		dbg_msg("chat", "%d:%d:%s: %s", ChatterClientId, Team, Server()->ClientName(ChatterClientId), pText);
 	else
-		dbg_msg("chat", "*** %s", text);
+		dbg_msg("chat", "*** %s", pText);
 
-	if(team == CHAT_ALL)
+	if(Team == CHAT_ALL)
 	{
-		NETMSG_SV_CHAT msg;
-		msg.team = 0;
-		msg.cid = chatter_cid;
-		msg.message = text;
-		msg.pack(MSGFLAG_VITAL);
-		server_send_msg(-1);
+		CNetMsg_Sv_Chat Msg;
+		Msg.m_Team = 0;
+		Msg.m_Cid = ChatterClientId;
+		Msg.m_pMessage = pText;
+		Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, -1);
 	}
 	else
 	{
-		NETMSG_SV_CHAT msg;
-		msg.team = 1;
-		msg.cid = chatter_cid;
-		msg.message = text;
+		CNetMsg_Sv_Chat Msg;
+		Msg.m_Team = 1;
+		Msg.m_Cid = ChatterClientId;
+		Msg.m_pMessage = pText;
 		
 		// pack one for the recording only
-		msg.pack(MSGFLAG_VITAL|MSGFLAG_NOSEND);
-		server_send_msg(-1);
+		Server()->SendPackMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_NOSEND, -1);
 
 		// send to the clients
-		msg.pack(MSGFLAG_VITAL|MSGFLAG_NORECORD);
 		for(int i = 0; i < MAX_CLIENTS; i++)
 		{
-			if(game.players[i] && game.players[i]->team == team)
-				server_send_msg(i);
+			if(m_apPlayers[i] && m_apPlayers[i]->GetTeam() == Team)
+				Server()->SendPackMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_NORECORD, i);
 		}
 	}
 }
 
-void GAMECONTEXT::send_emoticon(int cid, int emoticon)
+void CGameContext::SendEmoticon(int ClientId, int Emoticon)
 {
-	NETMSG_SV_EMOTICON msg;
-	msg.cid = cid;
-	msg.emoticon = emoticon;
-	msg.pack(MSGFLAG_VITAL);
-	server_send_msg(-1);
+	CNetMsg_Sv_Emoticon Msg;
+	Msg.m_Cid = ClientId;
+	Msg.m_Emoticon = Emoticon;
+	Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, -1);
 }
 
-void GAMECONTEXT::send_weapon_pickup(int cid, int weapon)
+void CGameContext::SendWeaponPickup(int ClientId, int Weapon)
 {
-	NETMSG_SV_WEAPONPICKUP msg;
-	msg.weapon = weapon;
-	msg.pack(MSGFLAG_VITAL);
-	server_send_msg(cid);
+	CNetMsg_Sv_WeaponPickup Msg;
+	Msg.m_Weapon = Weapon;
+	Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientId);
 }
 
 
-void GAMECONTEXT::send_broadcast(const char *text, int cid)
+void CGameContext::SendBroadcast(const char *pText, int ClientId)
 {
-	NETMSG_SV_BROADCAST msg;
-	msg.message = text;
-	msg.pack(MSGFLAG_VITAL);
-	server_send_msg(cid);
+	CNetMsg_Sv_Broadcast Msg;
+	Msg.m_pMessage = pText;
+	Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientId);
 }
 
 // 
-void GAMECONTEXT::start_vote(const char *desc, const char *command)
+void CGameContext::StartVote(const char *pDesc, const char *pCommand)
 {
 	// check if a vote is already running
-	if(vote_closetime)
+	if(m_VoteCloseTime)
 		return;
 
 	// reset votes
-	vote_enforce = VOTE_ENFORCE_UNKNOWN;
+	m_VoteEnforce = VOTE_ENFORCE_UNKNOWN;
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
-		if(players[i])
-			players[i]->vote = 0;
+		if(m_apPlayers[i])
+		{
+			m_apPlayers[i]->m_Vote = 0;
+			m_apPlayers[i]->m_VotePos = 0;
+		}
 	}
 	
 	// start vote
-	vote_closetime = time_get() + time_freq()*25;
-	str_copy(vote_description, desc, sizeof(vote_description));
-	str_copy(vote_command, command, sizeof(vote_description));
-	send_vote_set(-1);
-	send_vote_status(-1);
+	m_VoteCloseTime = time_get() + time_freq()*25;
+	str_copy(m_aVoteDescription, pDesc, sizeof(m_aVoteDescription));
+	str_copy(m_aVoteCommand, pCommand, sizeof(m_aVoteCommand));
+	SendVoteSet(-1);
+	m_VoteUpdate = true;
 }
 
 
-void GAMECONTEXT::end_vote()
+void CGameContext::EndVote()
 {
-	vote_closetime = 0;
-	send_vote_set(-1);
+	m_VoteCloseTime = 0;
+	SendVoteSet(-1);
 }
 
-void GAMECONTEXT::send_vote_set(int cid)
+void CGameContext::SendVoteSet(int ClientId)
 {
-	NETMSG_SV_VOTE_SET msg;
-	if(vote_closetime)
+	CNetMsg_Sv_VoteSet Msg;
+	if(m_VoteCloseTime)
 	{
-		msg.timeout = (vote_closetime-time_get())/time_freq();
-		msg.description = vote_description;
-		msg.command = vote_command;
+		Msg.m_Timeout = (m_VoteCloseTime-time_get())/time_freq();
+		Msg.m_pDescription = m_aVoteDescription;
+		Msg.m_pCommand = "";
 	}
 	else
 	{
-		msg.timeout = 0;
-		msg.description = "";
-		msg.command = "";
+		Msg.m_Timeout = 0;
+		Msg.m_pDescription = "";
+		Msg.m_pCommand = "";
 	}
-	msg.pack(MSGFLAG_VITAL);
-	server_send_msg(cid);
+	Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientId);
 }
 
-void GAMECONTEXT::send_vote_status(int cid)
+void CGameContext::SendVoteStatus(int ClientId, int Total, int Yes, int No)
 {
-	NETMSG_SV_VOTE_STATUS msg = {0};
-	for(int i = 0; i < MAX_CLIENTS; i++)
+	CNetMsg_Sv_VoteStatus Msg = {0};
+	Msg.m_Total = Total;
+	Msg.m_Yes = Yes;
+	Msg.m_No = No;
+	Msg.m_Pass = Total - (Yes+No);
+
+	Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientId);
+	
+}
+
+void CGameContext::AbortVoteKickOnDisconnect(int ClientId)
+{
+	if(m_VoteCloseTime && !str_comp_num(m_aVoteCommand, "kick ", 5) && str_toint(&m_aVoteCommand[5]) == ClientId)
+		m_VoteCloseTime = -1;
+}
+
+
+void CGameContext::CheckPureTuning()
+{
+	// might not be created yet during start up
+	if(!m_pController)
+		return;
+	
+	if(	str_comp(m_pController->m_pGameType, "DM")==0 ||
+		str_comp(m_pController->m_pGameType, "TDM")==0 ||
+		str_comp(m_pController->m_pGameType, "CTF")==0)
 	{
-		if(players[i])
+		CTuningParams p;
+		if(mem_comp(&p, &m_Tuning, sizeof(p)) != 0)
 		{
-			msg.total++;
-			if(players[i]->vote > 0)
-				msg.yes++;
-			else if(players[i]->vote < 0)
-				msg.no++;
-			else
-				msg.pass++;
+			dbg_msg("server", "resetting tuning due to pure server");
+			m_Tuning = p;
 		}
 	}	
-
-	msg.pack(MSGFLAG_VITAL);
-	server_send_msg(cid);
-	
 }
 
-void GAMECONTEXT::abort_vote_kick_on_disconnect(int client_id)
+void CGameContext::SendTuningParams(int Cid)
 {
-	if(vote_closetime && !strncmp(vote_command, "kick ", 5) && atoi(&vote_command[5]) == client_id)
-		vote_closetime = -1;
+	CheckPureTuning();
+	
+	CMsgPacker Msg(NETMSGTYPE_SV_TUNEPARAMS);
+	int *pParams = (int *)&m_Tuning;
+	for(unsigned i = 0; i < sizeof(m_Tuning)/sizeof(int); i++)
+		Msg.AddInt(pParams[i]);
+	Server()->SendMsg(&Msg, MSGFLAG_VITAL, Cid);
 }
 
-void GAMECONTEXT::tick()
+void CGameContext::OnTick()
 {
-	world.core.tuning = tuning;
-	world.tick();
+	// check tuning
+	CheckPureTuning();
+
+	// copy tuning
+	m_World.m_Core.m_Tuning = m_Tuning;
+	m_World.Tick();
 
 	//if(world.paused) // make sure that the game object always updates
-	controller->tick();
+	m_pController->Tick();
 		
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
-		if(players[i])
-			players[i]->tick();
+		if(m_apPlayers[i])
+			m_apPlayers[i]->Tick();
 	}
 	
 	// update voting
-	if(vote_closetime)
+	if(m_VoteCloseTime)
 	{
 		// abort the kick-vote on player-leave
-		if(vote_closetime == -1)
+		if(m_VoteCloseTime == -1)
 		{
-			send_chat(-1, GAMECONTEXT::CHAT_ALL, "Vote aborted");
-			end_vote();
+			SendChat(-1, CGameContext::CHAT_ALL, "Vote aborted");
+			EndVote();
 		}
 		else
 		{
-			// count votes
-			int total = 0, yes = 0, no = 0;
-			for(int i = 0; i < MAX_CLIENTS; i++)
+			int Total = 0, Yes = 0, No = 0;
+			if(m_VoteUpdate)
 			{
-				if(players[i])
+				// count votes
+				char aaBuf[MAX_CLIENTS][64] = {{0}};
+				for(int i = 0; i < MAX_CLIENTS; i++)
+					if(m_apPlayers[i])
+						Server()->GetClientIP(i, aaBuf[i], 64);
+				bool aVoteChecked[MAX_CLIENTS] = {0};
+				for(int i = 0; i < MAX_CLIENTS; i++)
 				{
-					total++;
-					if(players[i]->vote > 0)
-						yes++;
-					else if(players[i]->vote < 0)
-						no++;
+					if(!m_apPlayers[i] || m_apPlayers[i]->GetTeam() == -1 || aVoteChecked[i])	// don't count in votes by spectators
+						continue;
+					
+					int ActVote = m_apPlayers[i]->m_Vote;
+					int ActVotePos = m_apPlayers[i]->m_VotePos;
+					
+					// check for more players with the same ip (only use the vote of the one who voted first)
+					for(int j = i+1; j < MAX_CLIENTS; ++j)
+					{
+						if(!m_apPlayers[j] || aVoteChecked[j] || str_comp(aaBuf[j], aaBuf[i]))
+							continue;
+
+						aVoteChecked[j] = true;
+						if(m_apPlayers[j]->m_Vote && (!ActVote || ActVotePos > m_apPlayers[j]->m_VotePos))
+						{
+							ActVote = m_apPlayers[j]->m_Vote;
+							ActVotePos = m_apPlayers[j]->m_VotePos;
+						}
+					}
+
+					Total++;
+					if(ActVote > 0)
+						Yes++;
+					else if(ActVote < 0)
+						No++;
 				}
+
+				if(Yes >= Total/2+1)
+					m_VoteEnforce = VOTE_ENFORCE_YES;
+				else if(No >= Total/2+1 || Yes+No == Total)
+					m_VoteEnforce = VOTE_ENFORCE_NO;
 			}
+			
+			if(m_VoteEnforce == VOTE_ENFORCE_YES)
+			{
+				Console()->ExecuteLine(m_aVoteCommand);
+				EndVote();
+				SendChat(-1, CGameContext::CHAT_ALL, "Vote passed");
+			
+				if(m_apPlayers[m_VoteCreator])
+					m_apPlayers[m_VoteCreator]->m_Last_VoteCall = 0;
+			}
+			else if(m_VoteEnforce == VOTE_ENFORCE_NO || time_get() > m_VoteCloseTime)
+			{
+				EndVote();
+				SendChat(-1, CGameContext::CHAT_ALL, "Vote failed");
+			}
+			else if(m_VoteUpdate)
+			{
+				m_VoteUpdate = false;
+				SendVoteStatus(-1, Total, Yes, No);
+			}
+		}
+	}
+	
+
+#ifdef CONF_DEBUG
+	if(g_Config.m_DbgDummies)
+	{
+		for(int i = 0; i < g_Config.m_DbgDummies ; i++)
+		{
+			CNetObj_PlayerInput Input = {0};
+			Input.m_Direction = (i&1)?-1:1;
+			m_apPlayers[MAX_CLIENTS-i-1]->OnPredictedInput(&Input);
+		}
+	}
+#endif	
+}
+
+// Server hooks
+void CGameContext::OnClientDirectInput(int ClientID, void *pInput)
+{
+	if(!m_World.m_Paused)
+		m_apPlayers[ClientID]->OnDirectInput((CNetObj_PlayerInput *)pInput);
+}
+
+void CGameContext::OnClientPredictedInput(int ClientID, void *pInput)
+{
+	if(!m_World.m_Paused)
+		m_apPlayers[ClientID]->OnPredictedInput((CNetObj_PlayerInput *)pInput);
+}
+
+void CGameContext::OnClientEnter(int ClientId)
+{
+	//world.insert_entity(&players[client_id]);
+	m_apPlayers[ClientId]->Respawn();
+	dbg_msg("game", "join player='%d:%s'", ClientId, Server()->ClientName(ClientId));
+
+
+	char aBuf[512];
+	str_format(aBuf, sizeof(aBuf), "%s entered and joined the %s", Server()->ClientName(ClientId), m_pController->GetTeamName(m_apPlayers[ClientId]->GetTeam()));
+	SendChat(-1, CGameContext::CHAT_ALL, aBuf); 
+
+	dbg_msg("game", "team_join player='%d:%s' team=%d", ClientId, Server()->ClientName(ClientId), m_apPlayers[ClientId]->GetTeam());
+
+	m_VoteUpdate = true;
+}
+
+void CGameContext::OnClientConnected(int ClientId)
+{
+	// Check which team the player should be on
+	const int StartTeam = g_Config.m_SvTournamentMode ? -1 : m_pController->GetAutoTeam(ClientId);
+
+	m_apPlayers[ClientId] = new(ClientId) CPlayer(this, ClientId, StartTeam);
+	//players[client_id].init(client_id);
+	//players[client_id].client_id = client_id;
+	
+	(void)m_pController->CheckTeamBalance();
+
+#ifdef CONF_DEBUG
+	if(g_Config.m_DbgDummies)
+	{
+		if(ClientId >= MAX_CLIENTS-g_Config.m_DbgDummies)
+			return;
+	}
+#endif
+
+	// send active vote
+	if(m_VoteCloseTime)
+		SendVoteSet(ClientId);
+
+	// send motd
+	CNetMsg_Sv_Motd Msg;
+	Msg.m_pMessage = g_Config.m_SvMotd;
+	Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientId);
+}
+
+void CGameContext::OnClientDrop(int ClientId)
+{
+	AbortVoteKickOnDisconnect(ClientId);
+	m_apPlayers[ClientId]->OnDisconnect();
+	delete m_apPlayers[ClientId];
+	m_apPlayers[ClientId] = 0;
+	
+	(void)m_pController->CheckTeamBalance();
+	m_VoteUpdate = true;
+}
+
+void CGameContext::OnMessage(int MsgId, CUnpacker *pUnpacker, int ClientId)
+{
+	void *pRawMsg = m_NetObjHandler.SecureUnpackMsg(MsgId, pUnpacker);
+	CPlayer *p = m_apPlayers[ClientId];
+	
+	if(!pRawMsg)
+	{
+		dbg_msg("server", "dropped weird message '%s' (%d), failed on '%s'", m_NetObjHandler.GetMsgName(MsgId), MsgId, m_NetObjHandler.FailedMsgOn());
+		return;
+	}
+	
+	if(MsgId == NETMSGTYPE_CL_SAY)
+	{
+		CNetMsg_Cl_Say *pMsg = (CNetMsg_Cl_Say *)pRawMsg;
+		int Team = pMsg->m_Team;
+		if(Team)
+			Team = p->GetTeam();
+		else
+			Team = CGameContext::CHAT_ALL;
+		
+		if(g_Config.m_SvSpamprotection && p->m_Last_Chat && p->m_Last_Chat+Server()->TickSpeed() > Server()->Tick())
+			return;
+		
+		p->m_Last_Chat = Server()->Tick();
+
+		// check for invalid chars
+		unsigned char *pMessage = (unsigned char *)pMsg->m_pMessage;
+		while (*pMessage)
+		{
+			if(*pMessage < 32)
+				*pMessage = ' ';
+			pMessage++;
+		}
+		
+		SendChat(ClientId, Team, pMsg->m_pMessage);
+	}
+	else if(MsgId == NETMSGTYPE_CL_CALLVOTE)
+	{
+		if(g_Config.m_SvSpamprotection && p->m_Last_VoteTry && p->m_Last_VoteTry+Server()->TickSpeed()*3 > Server()->Tick())
+			return;
+
+		int64 Now = Server()->Tick();
+		p->m_Last_VoteTry = Now;
+		if(m_VoteCloseTime)
+		{
+			SendChatTarget(ClientId, "Wait for current vote to end before calling a new one.");
+			return;
+		}
 		
-			if(vote_enforce == VOTE_ENFORCE_YES || yes >= total/2+1)
+		int Timeleft = p->m_Last_VoteCall + Server()->TickSpeed()*60 - Now;
+		if(p->m_Last_VoteCall && Timeleft > 0)
+		{
+			char aChatmsg[512] = {0};
+			str_format(aChatmsg, sizeof(aChatmsg), "You must wait %d seconds before making another vote", (Timeleft/Server()->TickSpeed())+1);
+			SendChatTarget(ClientId, aChatmsg);
+			return;
+		}
+		
+		char aChatmsg[512] = {0};
+		char aDesc[512] = {0};
+		char aCmd[512] = {0};
+		CNetMsg_Cl_CallVote *pMsg = (CNetMsg_Cl_CallVote *)pRawMsg;
+		if(str_comp_nocase(pMsg->m_Type, "option") == 0)
+		{
+			CVoteOption *pOption = m_pVoteOptionFirst;
+			while(pOption)
 			{
-				console_execute_line(vote_command);
-				end_vote();
-				send_chat(-1, GAMECONTEXT::CHAT_ALL, "Vote passed");
+				if(str_comp_nocase(pMsg->m_Value, pOption->m_aCommand) == 0)
+				{
+					str_format(aChatmsg, sizeof(aChatmsg), "%s called vote to change server option '%s'", Server()->ClientName(ClientId), pOption->m_aCommand);
+					str_format(aDesc, sizeof(aDesc), "%s", pOption->m_aCommand);
+					str_format(aCmd, sizeof(aCmd), "%s", pOption->m_aCommand);
+					break;
+				}
+
+				pOption = pOption->m_pNext;
+			}
 			
-				if(players[vote_creator])
-					players[vote_creator]->last_votecall = 0;
+			if(!pOption)
+			{
+				str_format(aChatmsg, sizeof(aChatmsg), "'%s' isn't an option on this server", pMsg->m_Value);
+				SendChatTarget(ClientId, aChatmsg);
+				return;
 			}
-			else if(vote_enforce == VOTE_ENFORCE_NO || time_get() > vote_closetime || no >= total/2+1 || yes+no == total)
+		}
+		else if(str_comp_nocase(pMsg->m_Type, "kick") == 0)
+		{
+			if(!g_Config.m_SvVoteKick)
 			{
-				end_vote();
-				send_chat(-1, GAMECONTEXT::CHAT_ALL, "Vote failed");
+				SendChatTarget(ClientId, "Server does not allow voting to kick players");
+				return;
 			}
+			
+			int KickId = str_toint(pMsg->m_Value);
+			if(KickId < 0 || KickId >= MAX_CLIENTS || !m_apPlayers[KickId])
+			{
+				SendChatTarget(ClientId, "Invalid client id to kick");
+				return;
+			}
+			
+			str_format(aChatmsg, sizeof(aChatmsg), "%s called for vote to kick '%s'", Server()->ClientName(ClientId), Server()->ClientName(KickId));
+			str_format(aDesc, sizeof(aDesc), "Kick '%s'", Server()->ClientName(KickId));
+			if (!g_Config.m_SvVoteKickBantime)
+				str_format(aCmd, sizeof(aCmd), "kick %d", KickId);
+			else
+			{
+				char aBuf[64] = {0};
+				Server()->GetClientIP(KickId, aBuf, sizeof(aBuf));
+				str_format(aCmd, sizeof(aCmd), "ban %s %d", aBuf, g_Config.m_SvVoteKickBantime);
+			}
+		}
+		
+		if(aCmd[0])
+		{
+			SendChat(-1, CGameContext::CHAT_ALL, aChatmsg);
+			StartVote(aDesc, aCmd);
+			p->m_Vote = 1;
+			p->m_VotePos = m_VotePos = 1;
+			m_VoteCreator = ClientId;
+			p->m_Last_VoteCall = Now;
+		}
+	}
+	else if(MsgId == NETMSGTYPE_CL_VOTE)
+	{
+		if(!m_VoteCloseTime)
+			return;
+
+		if(p->m_Vote == 0)
+		{
+			CNetMsg_Cl_Vote *pMsg = (CNetMsg_Cl_Vote *)pRawMsg;
+			if(!pMsg->m_Vote)
+				return;
+
+			p->m_Vote = pMsg->m_Vote;
+			p->m_VotePos = ++m_VotePos;
+			m_VoteUpdate = true;
 		}
 	}
+	else if (MsgId == NETMSGTYPE_CL_SETTEAM && !m_World.m_Paused)
+	{
+		CNetMsg_Cl_SetTeam *pMsg = (CNetMsg_Cl_SetTeam *)pRawMsg;
+		
+		if(p->GetTeam() == pMsg->m_Team || (g_Config.m_SvSpamprotection && p->m_Last_SetTeam && p->m_Last_SetTeam+Server()->TickSpeed()*3 > Server()->Tick()))
+			return;
+
+		// Switch team on given client and kill/respawn him
+		if(m_pController->CanJoinTeam(pMsg->m_Team, ClientId))
+		{
+			if(m_pController->CanChangeTeam(p, pMsg->m_Team))
+			{
+				p->m_Last_SetTeam = Server()->Tick();
+				if(p->GetTeam() == -1 || pMsg->m_Team == -1)
+					m_VoteUpdate = true;
+				p->SetTeam(pMsg->m_Team);
+				(void)m_pController->CheckTeamBalance();
+			}
+			else
+				SendBroadcast("Teams must be balanced, please join other team", ClientId);
+		}
+		else
+		{
+			char aBuf[128];
+			str_format(aBuf, sizeof(aBuf), "Only %d active players are allowed", g_Config.m_SvMaxClients-g_Config.m_SvSpectatorSlots);
+			SendBroadcast(aBuf, ClientId);
+		}
+	}
+	else if (MsgId == NETMSGTYPE_CL_CHANGEINFO || MsgId == NETMSGTYPE_CL_STARTINFO)
+	{
+		CNetMsg_Cl_ChangeInfo *pMsg = (CNetMsg_Cl_ChangeInfo *)pRawMsg;
+		
+		if(g_Config.m_SvSpamprotection && p->m_Last_ChangeInfo && p->m_Last_ChangeInfo+Server()->TickSpeed()*5 > Server()->Tick())
+			return;
+			
+		p->m_Last_ChangeInfo = Server()->Tick();
+		
+		p->m_TeeInfos.m_UseCustomColor = pMsg->m_UseCustomColor;
+		p->m_TeeInfos.m_ColorBody = pMsg->m_ColorBody;
+		p->m_TeeInfos.m_ColorFeet = pMsg->m_ColorFeet;
+
+		// check for invalid chars
+		unsigned char *pName = (unsigned char *)pMsg->m_pName;
+		while (*pName)
+		{
+			if(*pName < 32)
+				*pName = ' ';
+			pName++;
+		}
+
+		// copy old name
+		char aOldName[MAX_NAME_LENGTH];
+		str_copy(aOldName, Server()->ClientName(ClientId), MAX_NAME_LENGTH);
+		
+		Server()->SetClientName(ClientId, pMsg->m_pName);
+		if(MsgId == NETMSGTYPE_CL_CHANGEINFO && str_comp(aOldName, Server()->ClientName(ClientId)) != 0)
+		{
+			char aChatText[256];
+			str_format(aChatText, sizeof(aChatText), "%s changed name to %s", aOldName, Server()->ClientName(ClientId));
+			SendChat(-1, CGameContext::CHAT_ALL, aChatText);
+		}
+		
+		// set skin
+		str_copy(p->m_TeeInfos.m_SkinName, pMsg->m_pSkin, sizeof(p->m_TeeInfos.m_SkinName));
+		
+		m_pController->OnPlayerInfoChange(p);
+		
+		if(MsgId == NETMSGTYPE_CL_STARTINFO)
+		{
+			// send vote options
+			CNetMsg_Sv_VoteClearOptions ClearMsg;
+			Server()->SendPackMsg(&ClearMsg, MSGFLAG_VITAL, ClientId);
+			CVoteOption *pCurrent = m_pVoteOptionFirst;
+			while(pCurrent)
+			{
+				CNetMsg_Sv_VoteOption OptionMsg;
+				OptionMsg.m_pCommand = pCurrent->m_aCommand;
+				Server()->SendPackMsg(&OptionMsg, MSGFLAG_VITAL, ClientId);
+				pCurrent = pCurrent->m_pNext;
+			}
+			
+			// send tuning parameters to client
+			SendTuningParams(ClientId);
+
+			//
+			CNetMsg_Sv_ReadyToEnter m;
+			Server()->SendPackMsg(&m, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientId);
+		}
+	}
+	else if (MsgId == NETMSGTYPE_CL_EMOTICON && !m_World.m_Paused)
+	{
+		CNetMsg_Cl_Emoticon *pMsg = (CNetMsg_Cl_Emoticon *)pRawMsg;
+		
+		if(g_Config.m_SvSpamprotection && p->m_Last_Emote && p->m_Last_Emote+Server()->TickSpeed()*3 > Server()->Tick())
+			return;
+			
+		p->m_Last_Emote = Server()->Tick();
+		
+		SendEmoticon(ClientId, pMsg->m_Emoticon);
+	}
+	else if (MsgId == NETMSGTYPE_CL_KILL && !m_World.m_Paused)
+	{
+		if(p->m_Last_Kill && p->m_Last_Kill+Server()->TickSpeed()*3 > Server()->Tick())
+			return;
+		
+		p->m_Last_Kill = Server()->Tick();
+		p->KillCharacter(WEAPON_SELF);
+		p->m_RespawnTick = Server()->Tick()+Server()->TickSpeed()*3;
+	}
+}
+
+void CGameContext::ConTuneParam(IConsole::IResult *pResult, void *pUserData)
+{
+	CGameContext *pSelf = (CGameContext *)pUserData;
+	const char *pParamName = pResult->GetString(0);
+	float NewValue = pResult->GetFloat(1);
+
+	if(pSelf->Tuning()->Set(pParamName, NewValue))
+	{
+		dbg_msg("tuning", "%s changed to %.2f", pParamName, NewValue);
+		pSelf->SendTuningParams(-1);
+	}
+	else
+		dbg_msg("tuning", "No such tuning parameter");
+}
+
+void CGameContext::ConTuneReset(IConsole::IResult *pResult, void *pUserData)
+{
+	CGameContext *pSelf = (CGameContext *)pUserData;
+	CTuningParams p;
+	*pSelf->Tuning() = p;
+	pSelf->SendTuningParams(-1);
+	dbg_msg("tuning", "Tuning reset");
+}
+
+void CGameContext::ConTuneDump(IConsole::IResult *pResult, void *pUserData)
+{
+	CGameContext *pSelf = (CGameContext *)pUserData;
+	for(int i = 0; i < pSelf->Tuning()->Num(); i++)
+	{
+		float v;
+		pSelf->Tuning()->Get(i, &v);
+		dbg_msg("tuning", "%s %.2f", pSelf->Tuning()->m_apNames[i], v);
+	}
+}
+
+void CGameContext::ConChangeMap(IConsole::IResult *pResult, void *pUserData)
+{
+	CGameContext *pSelf = (CGameContext *)pUserData;
+	pSelf->m_pController->ChangeMap(pResult->GetString(0));
+}
+
+void CGameContext::ConRestart(IConsole::IResult *pResult, void *pUserData)
+{
+	CGameContext *pSelf = (CGameContext *)pUserData;
+	if(pResult->NumArguments())
+		pSelf->m_pController->DoWarmup(pResult->GetInteger(0));
+	else
+		pSelf->m_pController->StartRound();
+}
+
+void CGameContext::ConBroadcast(IConsole::IResult *pResult, void *pUserData)
+{
+	CGameContext *pSelf = (CGameContext *)pUserData;
+	pSelf->SendBroadcast(pResult->GetString(0), -1);
+}
+
+void CGameContext::ConSay(IConsole::IResult *pResult, void *pUserData)
+{
+	CGameContext *pSelf = (CGameContext *)pUserData;
+	pSelf->SendChat(-1, CGameContext::CHAT_ALL, pResult->GetString(0));
+}
+
+void CGameContext::ConSetTeam(IConsole::IResult *pResult, void *pUserData)
+{
+	CGameContext *pSelf = (CGameContext *)pUserData;
+	int ClientId = clamp(pResult->GetInteger(0), 0, (int)MAX_CLIENTS-1);
+	int Team = clamp(pResult->GetInteger(1), -1, 1);
+	
+	dbg_msg("", "%d %d", ClientId, Team);
+	
+	if(!pSelf->m_apPlayers[ClientId])
+		return;
+	
+	pSelf->m_apPlayers[ClientId]->SetTeam(Team);
+	(void)pSelf->m_pController->CheckTeamBalance();
+}
+
+void CGameContext::ConAddVote(IConsole::IResult *pResult, void *pUserData)
+{
+	CGameContext *pSelf = (CGameContext *)pUserData;
+	int Len = str_length(pResult->GetString(0));
+	
+	CGameContext::CVoteOption *pOption = (CGameContext::CVoteOption *)pSelf->m_pVoteOptionHeap->Allocate(sizeof(CGameContext::CVoteOption) + Len);
+	pOption->m_pNext = 0;
+	pOption->m_pPrev = pSelf->m_pVoteOptionLast;
+	if(pOption->m_pPrev)
+		pOption->m_pPrev->m_pNext = pOption;
+	pSelf->m_pVoteOptionLast = pOption;
+	if(!pSelf->m_pVoteOptionFirst)
+		pSelf->m_pVoteOptionFirst = pOption;
+	
+	mem_copy(pOption->m_aCommand, pResult->GetString(0), Len+1);
+	dbg_msg("server", "added option '%s'", pOption->m_aCommand);
+
+	CNetMsg_Sv_VoteOption OptionMsg;
+	OptionMsg.m_pCommand = pOption->m_aCommand;
+	pSelf->Server()->SendPackMsg(&OptionMsg, MSGFLAG_VITAL, -1);
+}
+
+void CGameContext::ConVote(IConsole::IResult *pResult, void *pUserData)
+{
+	CGameContext *pSelf = (CGameContext *)pUserData;
+	if(str_comp_nocase(pResult->GetString(0), "yes") == 0)
+		pSelf->m_VoteEnforce = CGameContext::VOTE_ENFORCE_YES;
+	else if(str_comp_nocase(pResult->GetString(0), "no") == 0)
+		pSelf->m_VoteEnforce = CGameContext::VOTE_ENFORCE_NO;
+	dbg_msg("server", "forcing vote %s", pResult->GetString(0));
+}
+
+void CGameContext::ConchainSpecialMotdupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
+{
+	pfnCallback(pResult, pCallbackUserData);
+	if(pResult->NumArguments())
+	{
+		CNetMsg_Sv_Motd Msg;
+		Msg.m_pMessage = g_Config.m_SvMotd;
+		CGameContext *pSelf = (CGameContext *)pUserData;
+		for(int i = 0; i < MAX_CLIENTS; ++i)
+			if(pSelf->m_apPlayers[i])
+				pSelf->Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, i);
+	}
+}
+
+void CGameContext::OnConsoleInit()
+{
+	m_pServer = Kernel()->RequestInterface<IServer>();
+	m_pConsole = Kernel()->RequestInterface<IConsole>();
+
+	Console()->Register("tune", "si", CFGFLAG_SERVER, ConTuneParam, this, "");
+	Console()->Register("tune_reset", "", CFGFLAG_SERVER, ConTuneReset, this, "");
+	Console()->Register("tune_dump", "", CFGFLAG_SERVER, ConTuneDump, this, "");
+
+	Console()->Register("change_map", "r", CFGFLAG_SERVER, ConChangeMap, this, "");
+	Console()->Register("restart", "?i", CFGFLAG_SERVER, ConRestart, this, "");
+	Console()->Register("broadcast", "r", CFGFLAG_SERVER, ConBroadcast, this, "");
+	Console()->Register("say", "r", CFGFLAG_SERVER, ConSay, this, "");
+	Console()->Register("set_team", "ii", CFGFLAG_SERVER, ConSetTeam, this, "");
+
+	Console()->Register("addvote", "r", CFGFLAG_SERVER, ConAddVote, this, "");
+	Console()->Register("vote", "r", CFGFLAG_SERVER, ConVote, this, "");
+
+	Console()->Chain("sv_motd", ConchainSpecialMotdupdate, this);
+}
+
+void CGameContext::OnInit(/*class IKernel *pKernel*/)
+{
+	m_pServer = Kernel()->RequestInterface<IServer>();
+	m_pConsole = Kernel()->RequestInterface<IConsole>();
+	m_World.SetGameServer(this);
+	m_Events.SetGameServer(this);
+	
+	//if(!data) // only load once
+		//data = load_data_from_memory(internal_data);
+		
+	for(int i = 0; i < NUM_NETOBJTYPES; i++)
+		Server()->SnapSetStaticsize(i, m_NetObjHandler.GetObjSize(i));
+
+	m_Layers.Init(Kernel());
+	m_Collision.Init(&m_Layers);
+
+	// reset everything here
+	//world = new GAMEWORLD;
+	//players = new CPlayer[MAX_CLIENTS];
+
+	// select gametype
+	if(str_comp(g_Config.m_SvGametype, "mod") == 0)
+		m_pController = new CGameControllerMOD(this);
+	else if(str_comp(g_Config.m_SvGametype, "ctf") == 0)
+		m_pController = new CGameControllerCTF(this);
+	else if(str_comp(g_Config.m_SvGametype, "tdm") == 0)
+		m_pController = new CGameControllerTDM(this);
+	else
+		m_pController = new CGameControllerDM(this);
+
+	// setup core world
+	//for(int i = 0; i < MAX_CLIENTS; i++)
+	//	game.players[i].core.world = &game.world.core;
+
+	// create all entities from the game layer
+	CMapItemLayerTilemap *pTileMap = m_Layers.GameLayer();
+	CTile *pTiles = (CTile *)Kernel()->RequestInterface<IMap>()->GetData(pTileMap->m_Data);
+	
+	
+	
+	
+	/*
+	num_spawn_points[0] = 0;
+	num_spawn_points[1] = 0;
+	num_spawn_points[2] = 0;
+	*/
+	
+	for(int y = 0; y < pTileMap->m_Height; y++)
+	{
+		for(int x = 0; x < pTileMap->m_Width; x++)
+		{
+			int Index = pTiles[y*pTileMap->m_Width+x].m_Index;
+			
+			if(Index >= ENTITY_OFFSET)
+			{
+				vec2 Pos(x*32.0f+16.0f, y*32.0f+16.0f);
+				m_pController->OnEntity(Index-ENTITY_OFFSET, Pos);
+			}
+		}
+	}
+
+	//game.world.insert_entity(game.Controller);
+
+#ifdef CONF_DEBUG
+	if(g_Config.m_DbgDummies)
+	{
+		for(int i = 0; i < g_Config.m_DbgDummies ; i++)
+		{
+			OnClientConnected(MAX_CLIENTS-i-1);
+		}
+	}
+#endif
+}
+
+void CGameContext::OnShutdown()
+{
+	delete m_pController;
+	m_pController = 0;
+	Clear();
 }
 
-void GAMECONTEXT::snap(int client_id)
+void CGameContext::OnSnap(int ClientId)
 {
-	world.snap(client_id);
-	controller->snap(client_id);
-	events.snap(client_id);
+	m_World.Snap(ClientId);
+	m_pController->Snap(ClientId);
+	m_Events.Snap(ClientId);
 	
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
-		if(players[i])
-			players[i]->snap(client_id);
+		if(m_apPlayers[i])
+			m_apPlayers[i]->Snap(ClientId);
 	}
 }
+void CGameContext::OnPreSnap() {}
+void CGameContext::OnPostSnap()
+{
+	m_Events.Clear();
+}
+
+const char *CGameContext::Version() { return GAME_VERSION; }
+const char *CGameContext::NetVersion() { return GAME_NETVERSION; }
+
+IGameServer *CreateGameServer() { return new CGameContext; }
diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h
new file mode 100644
index 00000000..d55203e7
--- /dev/null
+++ b/src/game/server/gamecontext.h
@@ -0,0 +1,168 @@
+#ifndef GAME_SERVER_GAMECONTEXT_H
+#define GAME_SERVER_GAMECONTEXT_H
+
+#include <engine/server.h>
+#include <engine/console.h>
+#include <engine/shared/memheap.h>
+
+#include <game/layers.h>
+
+#include "eventhandler.h"
+#include "gamecontroller.h"
+#include "gameworld.h"
+#include "player.h"
+
+/*
+	Tick
+		Game Context (CGameContext::tick)
+			Game World (GAMEWORLD::tick)
+				Reset world if requested (GAMEWORLD::reset)
+				All entities in the world (ENTITY::tick)
+				All entities in the world (ENTITY::tick_defered)
+				Remove entities marked for deletion (GAMEWORLD::remove_entities)
+			Game Controller (GAMECONTROLLER::tick)
+			All players (CPlayer::tick)
+			
+
+	Snap
+		Game Context (CGameContext::snap)
+			Game World (GAMEWORLD::snap)
+				All entities in the world (ENTITY::snap)
+			Game Controller (GAMECONTROLLER::snap)
+			Events handler (EVENT_HANDLER::snap)
+			All players (CPlayer::snap)
+
+*/
+class CGameContext : public IGameServer
+{
+	IServer *m_pServer;
+	class IConsole *m_pConsole;
+	CLayers m_Layers;
+	CCollision m_Collision;
+	CNetObjHandler m_NetObjHandler;
+	CTuningParams m_Tuning;
+
+	static void ConTuneParam(IConsole::IResult *pResult, void *pUserData);
+	static void ConTuneReset(IConsole::IResult *pResult, void *pUserData);
+	static void ConTuneDump(IConsole::IResult *pResult, void *pUserData);
+	static void ConChangeMap(IConsole::IResult *pResult, void *pUserData);
+	static void ConRestart(IConsole::IResult *pResult, void *pUserData);
+	static void ConBroadcast(IConsole::IResult *pResult, void *pUserData);
+	static void ConSay(IConsole::IResult *pResult, void *pUserData);
+	static void ConSetTeam(IConsole::IResult *pResult, void *pUserData);
+	static void ConAddVote(IConsole::IResult *pResult, void *pUserData);
+	static void ConVote(IConsole::IResult *pResult, void *pUserData);
+	static void ConchainSpecialMotdupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
+	
+	CGameContext(int Resetting);
+	void Construct(int Resetting);
+
+	bool m_Resetting;
+public:
+	IServer *Server() const { return m_pServer; }
+	class IConsole *Console() { return m_pConsole; }
+	CCollision *Collision() { return &m_Collision; }
+	CTuningParams *Tuning() { return &m_Tuning; }
+
+	CGameContext();
+	~CGameContext();
+	
+	void Clear();
+	
+	CEventHandler m_Events;
+	CPlayer *m_apPlayers[MAX_CLIENTS];
+
+	IGameController *m_pController;
+	CGameWorld m_World;
+	
+	// helper functions
+	class CCharacter *GetPlayerChar(int ClientId);
+	
+	// voting
+	void StartVote(const char *pDesc, const char *pCommand);
+	void EndVote();
+	void SendVoteSet(int ClientId);
+	void SendVoteStatus(int ClientId, int Total, int Yes, int No);
+	void AbortVoteKickOnDisconnect(int ClientId);
+	
+	int m_VoteCreator;
+	int64 m_VoteCloseTime;
+	bool m_VoteUpdate;
+	int m_VotePos;
+	char m_aVoteDescription[512];
+	char m_aVoteCommand[512];
+	int m_VoteEnforce;
+	enum
+	{
+		VOTE_ENFORCE_UNKNOWN=0,
+		VOTE_ENFORCE_NO,
+		VOTE_ENFORCE_YES,
+	};
+	struct CVoteOption
+	{
+		CVoteOption *m_pNext;
+		CVoteOption *m_pPrev;
+		char m_aCommand[1];
+	};
+	CHeap *m_pVoteOptionHeap;
+	CVoteOption *m_pVoteOptionFirst;
+	CVoteOption *m_pVoteOptionLast;
+
+	// helper functions
+	void CreateDamageInd(vec2 Pos, float AngleMod, int Amount);
+	void CreateExplosion(vec2 Pos, int Owner, int Weapon, bool NoDamage);
+	void CreateSmoke(vec2 Pos);
+	void CreateHammerHit(vec2 Pos);
+	void CreatePlayerSpawn(vec2 Pos);
+	void CreateDeath(vec2 Pos, int Who);
+	void CreateSound(vec2 Pos, int Sound, int Mask=-1);
+	void CreateSoundGlobal(int Sound, int Target=-1);	
+
+
+	enum
+	{
+		CHAT_ALL=-2,
+		CHAT_SPEC=-1,
+		CHAT_RED=0,
+		CHAT_BLUE=1
+	};
+
+	// network
+	void SendChatTarget(int To, const char *pText);
+	void SendChat(int ClientId, int Team, const char *pText);
+	void SendEmoticon(int ClientId, int Emoticon);
+	void SendWeaponPickup(int ClientId, int Weapon);
+	void SendBroadcast(const char *pText, int ClientId);
+	
+	
+	//
+	void CheckPureTuning();
+	void SendTuningParams(int ClientId);
+	
+	// engine events
+	virtual void OnInit();
+	virtual void OnConsoleInit();
+	virtual void OnShutdown();
+	
+	virtual void OnTick();
+	virtual void OnPreSnap();
+	virtual void OnSnap(int ClientId);
+	virtual void OnPostSnap();
+	
+	virtual void OnMessage(int MsgId, CUnpacker *pUnpacker, int ClientId);
+
+	virtual void OnClientConnected(int ClientId);
+	virtual void OnClientEnter(int ClientId);
+	virtual void OnClientDrop(int ClientId);
+	virtual void OnClientDirectInput(int ClientId, void *pInput);
+	virtual void OnClientPredictedInput(int ClientId, void *pInput);
+
+	virtual const char *Version();
+	virtual const char *NetVersion();
+};
+
+inline int CmaskAll() { return -1; }
+inline int CmaskOne(int ClientId) { return 1<<ClientId; }
+inline int CmaskAllExceptOne(int ClientId) { return 0x7fffffff^CmaskOne(ClientId); }
+inline bool CmaskIsSet(int Mask, int ClientId) { return (Mask&CmaskOne(ClientId)) != 0; }
+#endif
diff --git a/src/game/server/gamecontext.hpp b/src/game/server/gamecontext.hpp
deleted file mode 100644
index bea087cb..00000000
--- a/src/game/server/gamecontext.hpp
+++ /dev/null
@@ -1,105 +0,0 @@
-#ifndef GAME_SERVER_GAMECONTEXT_H
-#define GAME_SERVER_GAMECONTEXT_H
-
-#include "eventhandler.hpp"
-#include "gamecontroller.hpp"
-#include "gameworld.hpp"
-#include "player.hpp"
-
-/*
-	Tick
-		Game Context (GAMECONTEXT::tick)
-			Game World (GAMEWORLD::tick)
-				Reset world if requested (GAMEWORLD::reset)
-				All entities in the world (ENTITY::tick)
-				All entities in the world (ENTITY::tick_defered)
-				Remove entities marked for deletion (GAMEWORLD::remove_entities)
-			Game Controller (GAMECONTROLLER::tick)
-			All players (PLAYER::tick)
-			
-
-	Snap
-		Game Context (GAMECONTEXT::snap)
-			Game World (GAMEWORLD::snap)
-				All entities in the world (ENTITY::snap)
-			Game Controller (GAMECONTROLLER::snap)
-			Events handler (EVENT_HANDLER::snap)
-			All players (PLAYER::snap)
-
-*/
-class GAMECONTEXT
-{
-public:
-	GAMECONTEXT();
-	~GAMECONTEXT();
-	
-	void clear();
-	
-	EVENTHANDLER events;
-	PLAYER *players[MAX_CLIENTS];
-	
-	GAMECONTROLLER *controller;
-	GAMEWORLD world;
-
-	void tick();
-	void snap(int client_id);
-	
-	// helper functions
-	class CHARACTER *get_player_char(int client_id);
-	
-	// voting
-	void start_vote(const char *desc, const char *command);
-	void end_vote();
-	void send_vote_set(int cid);
-	void send_vote_status(int cid);
-	void abort_vote_kick_on_disconnect(int client_id);
-	int vote_creator;
-	int64 vote_closetime;
-	char vote_description[512];
-	char vote_command[512];
-	int vote_enforce;
-	enum
-	{
-		VOTE_ENFORCE_UNKNOWN=0,
-		VOTE_ENFORCE_NO,
-		VOTE_ENFORCE_YES,
-	};
-
-	// helper functions
-	void create_damageind(vec2 p, float angle_mod, int amount);
-	void create_explosion(vec2 p, int owner, int weapon, bool bnodamage);
-	void create_smoke(vec2 p);
-	void create_hammerhit(vec2 p);
-	void create_playerspawn(vec2 p);
-	void create_death(vec2 p, int who);
-	void create_sound(vec2 pos, int sound, int mask=-1);
-	void create_sound_global(int sound, int target=-1);	
-
-
-	enum
-	{
-		CHAT_ALL=-2,
-		CHAT_SPEC=-1,
-		CHAT_RED=0,
-		CHAT_BLUE=1
-	};
-
-	// network
-	void send_chat_target(int to, const char *text);
-	void send_chat(int cid, int team, const char *text);
-	void send_emoticon(int cid, int emoticon);
-	void send_weapon_pickup(int cid, int weapon);
-	void send_broadcast(const char *text, int cid);
-
-};
-
-extern GAMECONTEXT game;
-
-// MISC stuff, move to a better place later on
-
-extern TUNING_PARAMS tuning;
-inline int cmask_all() { return -1; }
-inline int cmask_one(int cid) { return 1<<cid; }
-inline int cmask_all_except_one(int cid) { return 0x7fffffff^cmask_one(cid); }
-inline bool cmask_is_set(int mask, int cid) { return (mask&cmask_one(cid)) != 0; }
-#endif
diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp
index cdbace8e..a822f7ca 100644
--- a/src/game/server/gamecontroller.cpp
+++ b/src/game/server/gamecontroller.cpp
@@ -1,607 +1,614 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <string.h>
-#include <engine/e_config.h>
-#include <engine/e_server_interface.h>
-#include <game/mapitems.hpp>
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+#include <engine/shared/config.h>
+#include <game/mapitems.h>
 
-#include <game/generated/g_protocol.hpp>
+#include <game/generated/protocol.h>
 
-#include "entities/pickup.hpp"
-#include "gamecontroller.hpp"
-#include "gamecontext.hpp"
+#include "entities/pickup.h"
+#include "gamecontroller.h"
+#include "gamecontext.h"
 
 
-
-GAMECONTROLLER::GAMECONTROLLER()
+IGameController::IGameController(class CGameContext *pGameServer)
 {
-	gametype = "unknown";
+	m_pGameServer = pGameServer;
+	m_pServer = m_pGameServer->Server();
+	m_pGameType = "unknown";
 	
 	//
-	do_warmup(config.sv_warmup);
-	game_over_tick = -1;
-	sudden_death = 0;
-	round_start_tick = server_tick();
-	round_count = 0;
-	game_flags = 0;
-	teamscore[0] = 0;
-	teamscore[1] = 0;
-	map_wish[0] = 0;
-	
-	unbalanced_tick = -1;
-	force_balanced = false;
-	
-	num_spawn_points[0] = 0;
-	num_spawn_points[1] = 0;
-	num_spawn_points[2] = 0;
+	DoWarmup(g_Config.m_SvWarmup);
+	m_GameOverTick = -1;
+	m_SuddenDeath = 0;
+	m_RoundStartTick = Server()->Tick();
+	m_RoundCount = 0;
+	m_GameFlags = 0;
+	m_aTeamscore[0] = 0;
+	m_aTeamscore[1] = 0;
+	m_aMapWish[0] = 0;
+	
+	m_UnbalancedTick = -1;
+	m_ForceBalanced = false;
+	
+	m_aNumSpawnPoints[0] = 0;
+	m_aNumSpawnPoints[1] = 0;
+	m_aNumSpawnPoints[2] = 0;
 }
 
-GAMECONTROLLER::~GAMECONTROLLER()
+IGameController::~IGameController()
 {
 }
 
-float GAMECONTROLLER::evaluate_spawn_pos(SPAWNEVAL *eval, vec2 pos)
+float IGameController::EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos)
 {
-	float score = 0.0f;
-	CHARACTER *c = (CHARACTER *)game.world.find_first(NETOBJTYPE_CHARACTER);
-	for(; c; c = (CHARACTER *)c->typenext())
+	float Score = 0.0f;
+	CCharacter *pC = static_cast<CCharacter *>(GameServer()->m_World.FindFirst(NETOBJTYPE_CHARACTER));
+	for(; pC; pC = (CCharacter *)pC->TypeNext())
 	{
 		// team mates are not as dangerous as enemies
-		float scoremod = 1.0f;
-		if(eval->friendly_team != -1 && c->team == eval->friendly_team)
-			scoremod = 0.5f;
+		float Scoremod = 1.0f;
+		if(pEval->m_FriendlyTeam != -1 && pC->GetPlayer()->GetTeam() == pEval->m_FriendlyTeam)
+			Scoremod = 0.5f;
 			
-		float d = distance(pos, c->pos);
+		float d = distance(Pos, pC->m_Pos);
 		if(d == 0)
-			score += 1000000000.0f;
+			Score += 1000000000.0f;
 		else
-			score += 1.0f/d;
+			Score += 1.0f/d;
 	}
 	
-	return score;
+	return Score;
 }
 
-void GAMECONTROLLER::evaluate_spawn_type(SPAWNEVAL *eval, int t)
+void IGameController::EvaluateSpawnType(CSpawnEval *pEval, int T)
 {
 	// get spawn point
-	for(int i  = 0; i < num_spawn_points[t]; i++)
+	for(int i  = 0; i < m_aNumSpawnPoints[T]; i++)
 	{
-		vec2 p = spawn_points[t][i];
-		float s = evaluate_spawn_pos(eval, p);
-		if(!eval->got || eval->score > s)
+		vec2 P = m_aaSpawnPoints[T][i];
+		float S = EvaluateSpawnPos(pEval, P);
+		if(!pEval->m_Got || pEval->m_Score > S)
 		{
-			eval->got = true;
-			eval->score = s;
-			eval->pos = p;
+			pEval->m_Got = true;
+			pEval->m_Score = S;
+			pEval->m_Pos = P;
 		}
 	}
 }
 
-bool GAMECONTROLLER::can_spawn(PLAYER *player, vec2 *out_pos)
+bool IGameController::CanSpawn(CPlayer *pPlayer, vec2 *pOutPos)
 {
-	SPAWNEVAL eval;
+	CSpawnEval Eval;
 	
 	// spectators can't spawn
-	if(player->team == -1)
+	if(pPlayer->GetTeam() == -1)
 		return false;
 	
-	if(is_teamplay())
+	if(IsTeamplay())
 	{
-		eval.friendly_team = player->team;
+		Eval.m_FriendlyTeam = pPlayer->GetTeam();
 		
 		// try first try own team spawn, then normal spawn and then enemy
-		evaluate_spawn_type(&eval, 1+(player->team&1));
-		if(!eval.got)
+		EvaluateSpawnType(&Eval, 1+(pPlayer->GetTeam()&1));
+		if(!Eval.m_Got)
 		{
-			evaluate_spawn_type(&eval, 0);
-			if(!eval.got)
-				evaluate_spawn_type(&eval, 1+((player->team+1)&1));
+			EvaluateSpawnType(&Eval, 0);
+			if(!Eval.m_Got)
+				EvaluateSpawnType(&Eval, 1+((pPlayer->GetTeam()+1)&1));
 		}
 	}
 	else
 	{
-		evaluate_spawn_type(&eval, 0);
-		evaluate_spawn_type(&eval, 1);
-		evaluate_spawn_type(&eval, 2);
+		EvaluateSpawnType(&Eval, 0);
+		EvaluateSpawnType(&Eval, 1);
+		EvaluateSpawnType(&Eval, 2);
 	}
 	
-	*out_pos = eval.pos;
-	return eval.got;
+	*pOutPos = Eval.m_Pos;
+	return Eval.m_Got;
 }
 
 
-bool GAMECONTROLLER::on_entity(int index, vec2 pos)
+bool IGameController::OnEntity(int Index, vec2 Pos)
 {
-	int type = -1;
-	int subtype = 0;
+	int Type = -1;
+	int SubType = 0;
 	
-	if(index == ENTITY_SPAWN)
-		spawn_points[0][num_spawn_points[0]++] = pos;
-	else if(index == ENTITY_SPAWN_RED)
-		spawn_points[1][num_spawn_points[1]++] = pos;
-	else if(index == ENTITY_SPAWN_BLUE)
-		spawn_points[2][num_spawn_points[2]++] = pos;
-	else if(index == ENTITY_ARMOR_1)
-		type = POWERUP_ARMOR;
-	else if(index == ENTITY_HEALTH_1)
-		type = POWERUP_HEALTH;
-	else if(index == ENTITY_WEAPON_SHOTGUN)
+	if(Index == ENTITY_SPAWN)
+		m_aaSpawnPoints[0][m_aNumSpawnPoints[0]++] = Pos;
+	else if(Index == ENTITY_SPAWN_RED)
+		m_aaSpawnPoints[1][m_aNumSpawnPoints[1]++] = Pos;
+	else if(Index == ENTITY_SPAWN_BLUE)
+		m_aaSpawnPoints[2][m_aNumSpawnPoints[2]++] = Pos;
+	else if(Index == ENTITY_ARMOR_1)
+		Type = POWERUP_ARMOR;
+	else if(Index == ENTITY_HEALTH_1)
+		Type = POWERUP_HEALTH;
+	else if(Index == ENTITY_WEAPON_SHOTGUN)
 	{
-		type = POWERUP_WEAPON;
-		subtype = WEAPON_SHOTGUN;
+		Type = POWERUP_WEAPON;
+		SubType = WEAPON_SHOTGUN;
 	}
-	else if(index == ENTITY_WEAPON_GRENADE)
+	else if(Index == ENTITY_WEAPON_GRENADE)
 	{
-		type = POWERUP_WEAPON;
-		subtype = WEAPON_GRENADE;
+		Type = POWERUP_WEAPON;
+		SubType = WEAPON_GRENADE;
 	}
-	else if(index == ENTITY_WEAPON_RIFLE)
+	else if(Index == ENTITY_WEAPON_RIFLE)
 	{
-		type = POWERUP_WEAPON;
-		subtype = WEAPON_RIFLE;
+		Type = POWERUP_WEAPON;
+		SubType = WEAPON_RIFLE;
 	}
-	else if(index == ENTITY_POWERUP_NINJA && config.sv_powerups)
+	else if(Index == ENTITY_POWERUP_NINJA && g_Config.m_SvPowerups)
 	{
-		type = POWERUP_NINJA;
-		subtype = WEAPON_NINJA;
+		Type = POWERUP_NINJA;
+		SubType = WEAPON_NINJA;
 	}
 	
-	if(type != -1)
+	if(Type != -1)
 	{
-		PICKUP *pickup = new PICKUP(type, subtype);
-		pickup->pos = pos;
+		CPickup *pPickup = new CPickup(&GameServer()->m_World, Type, SubType);
+		pPickup->m_Pos = Pos;
 		return true;
 	}
 
 	return false;
 }
 
-void GAMECONTROLLER::endround()
+void IGameController::EndRound()
 {
-	if(warmup) // game can't end when we are running warmup
+	if(m_Warmup) // game can't end when we are running warmup
 		return;
 		
-	game.world.paused = true;
-	game_over_tick = server_tick();
-	sudden_death = 0;
+	GameServer()->m_World.m_Paused = true;
+	m_GameOverTick = Server()->Tick();
+	m_SuddenDeath = 0;
 }
 
-void GAMECONTROLLER::resetgame()
+void IGameController::ResetGame()
 {
-	game.world.reset_requested = true;
+	GameServer()->m_World.m_ResetRequested = true;
 }
 
-const char *GAMECONTROLLER::get_team_name(int team)
+const char *IGameController::GetTeamName(int Team)
 {
-	if(is_teamplay())
+	if(IsTeamplay())
 	{
-		if(team == 0)
+		if(Team == 0)
 			return "red team";
-		else if(team == 1)
+		else if(Team == 1)
 			return "blue team";
 	}
 	else
 	{
-		if(team == 0)
+		if(Team == 0)
 			return "game";
 	}
 	
 	return "spectators";
 }
 
-static bool is_separator(char c) { return c == ';' || c == ' ' || c == ',' || c == '\t'; }
+static bool IsSeparator(char c) { return c == ';' || c == ' ' || c == ',' || c == '\t'; }
 
-void GAMECONTROLLER::startround()
+void IGameController::StartRound()
 {
-	resetgame();
-	
-	round_start_tick = server_tick();
-	sudden_death = 0;
-	game_over_tick = -1;
-	game.world.paused = false;
-	teamscore[0] = 0;
-	teamscore[1] = 0;
-	unbalanced_tick = -1;
-	force_balanced = false;
-	dbg_msg("game","start round type='%s' teamplay='%d'", gametype, game_flags&GAMEFLAG_TEAMS);
+	ResetGame();
+	
+	m_RoundStartTick = Server()->Tick();
+	m_SuddenDeath = 0;
+	m_GameOverTick = -1;
+	GameServer()->m_World.m_Paused = false;
+	m_aTeamscore[0] = 0;
+	m_aTeamscore[1] = 0;
+	m_ForceBalanced = false;
+	dbg_msg("game","start round type='%s' teamplay='%d'", m_pGameType, m_GameFlags&GAMEFLAG_TEAMS);
 }
 
-void GAMECONTROLLER::change_map(const char *to_map)
+void IGameController::ChangeMap(const char *pToMap)
 {
-	str_copy(map_wish, to_map, sizeof(map_wish));
-	endround();
+	str_copy(m_aMapWish, pToMap, sizeof(m_aMapWish));
+	EndRound();
 }
 
-void GAMECONTROLLER::cyclemap()
+void IGameController::CycleMap()
 {
-	if(map_wish[0] != 0)
+	if(m_aMapWish[0] != 0)
 	{
-		dbg_msg("game", "rotating map to %s", map_wish);
-		str_copy(config.sv_map, map_wish, sizeof(config.sv_map));
-		map_wish[0] = 0;
-		round_count = 0;
+		dbg_msg("game", "rotating map to %s", m_aMapWish);
+		str_copy(g_Config.m_SvMap, m_aMapWish, sizeof(g_Config.m_SvMap));
+		m_aMapWish[0] = 0;
+		m_RoundCount = 0;
 		return;
 	}
-	if(!strlen(config.sv_maprotation))
+	if(!str_length(g_Config.m_SvMaprotation))
 		return;
 
-	if(round_count < config.sv_rounds_per_map-1)
+	if(m_RoundCount < g_Config.m_SvRoundsPerMap-1)
 		return;
 		
 	// handle maprotation
-	const char *map_rotation = config.sv_maprotation;
-	const char *current_map = config.sv_map;
+	const char *pMapRotation = g_Config.m_SvMaprotation;
+	const char *pCurrentMap = g_Config.m_SvMap;
 	
-	int current_map_len = strlen(current_map);
-	const char *next_map = map_rotation;
-	while(*next_map)
+	int CurrentMapLen = str_length(pCurrentMap);
+	const char *pNextMap = pMapRotation;
+	while(*pNextMap)
 	{
-		int wordlen = 0;
-		while(next_map[wordlen] && !is_separator(next_map[wordlen]))
-			wordlen++;
+		int WordLen = 0;
+		while(pNextMap[WordLen] && !IsSeparator(pNextMap[WordLen]))
+			WordLen++;
 		
-		if(wordlen == current_map_len && strncmp(next_map, current_map, current_map_len) == 0)
+		if(WordLen == CurrentMapLen && str_comp_num(pNextMap, pCurrentMap, CurrentMapLen) == 0)
 		{
 			// map found
-			next_map += current_map_len;
-			while(*next_map && is_separator(*next_map))
-				next_map++;
+			pNextMap += CurrentMapLen;
+			while(*pNextMap && IsSeparator(*pNextMap))
+				pNextMap++;
 				
 			break;
 		}
 		
-		next_map++;
+		pNextMap++;
 	}
 	
 	// restart rotation
-	if(next_map[0] == 0)
-		next_map = map_rotation;
+	if(pNextMap[0] == 0)
+		pNextMap = pMapRotation;
 
 	// cut out the next map	
-	char buf[512];
+	char Buf[512];
 	for(int i = 0; i < 512; i++)
 	{
-		buf[i] = next_map[i];
-		if(is_separator(next_map[i]) || next_map[i] == 0)
+		Buf[i] = pNextMap[i];
+		if(IsSeparator(pNextMap[i]) || pNextMap[i] == 0)
 		{
-			buf[i] = 0;
+			Buf[i] = 0;
 			break;
 		}
 	}
 	
 	// skip spaces
 	int i = 0;
-	while(is_separator(buf[i]))
+	while(IsSeparator(Buf[i]))
 		i++;
 	
-	round_count = 0;
+	m_RoundCount = 0;
 	
-	dbg_msg("game", "rotating map to %s", &buf[i]);
-	str_copy(config.sv_map, &buf[i], sizeof(config.sv_map));
+	dbg_msg("game", "rotating map to %s", &Buf[i]);
+	str_copy(g_Config.m_SvMap, &Buf[i], sizeof(g_Config.m_SvMap));
 }
 
-void GAMECONTROLLER::post_reset()
+void IGameController::PostReset()
 {
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
-		if(game.players[i])
+		if(GameServer()->m_apPlayers[i])
 		{
-			game.players[i]->respawn();
-			game.players[i]->score = 0;
+			GameServer()->m_apPlayers[i]->Respawn();
+			GameServer()->m_apPlayers[i]->m_Score = 0;
 		}
 	}
 }
 	
-void GAMECONTROLLER::on_player_info_change(class PLAYER *p)
+void IGameController::OnPlayerInfoChange(class CPlayer *pP)
 {
-	const int team_colors[2] = {65387, 10223467};
-	if(is_teamplay())
+	const int aTeamColors[2] = {65387, 10223467};
+	if(IsTeamplay())
 	{
-		if(p->team >= 0 || p->team <= 1)
+		if(pP->GetTeam() >= 0 || pP->GetTeam() <= 1)
 		{
-			p->use_custom_color = 1;
-			p->color_body = team_colors[p->team];
-			p->color_feet = team_colors[p->team];
+			pP->m_TeeInfos.m_UseCustomColor = 1;
+			pP->m_TeeInfos.m_ColorBody = aTeamColors[pP->GetTeam()];
+			pP->m_TeeInfos.m_ColorFeet = aTeamColors[pP->GetTeam()];
 		}
 	}
 }
 
 
-int GAMECONTROLLER::on_character_death(class CHARACTER *victim, class PLAYER *killer, int weapon)
+int IGameController::OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon)
 {
 	// do scoreing
-	if(!killer)
+	if(!pKiller)
 		return 0;
-	if(killer == victim->player)
-		victim->player->score--; // suicide
+	if(pKiller == pVictim->GetPlayer())
+		pVictim->GetPlayer()->m_Score--; // suicide
 	else
 	{
-		if(is_teamplay() && victim->team == killer->team)
-			killer->score--; // teamkill
+		if(IsTeamplay() && pVictim->GetPlayer()->GetTeam() == pKiller->GetTeam())
+			pKiller->m_Score--; // teamkill
 		else
-			killer->score++; // normal kill
+			pKiller->m_Score++; // normal kill
 	}
 	return 0;
 }
 
-void GAMECONTROLLER::on_character_spawn(class CHARACTER *chr)
+void IGameController::OnCharacterSpawn(class CCharacter *pChr)
 {
 	// default health
-	chr->health = 10;
+	pChr->IncreaseHealth(10);
 	
 	// give default weapons
-	chr->weapons[WEAPON_HAMMER].got = 1;
-	chr->weapons[WEAPON_HAMMER].ammo = -1;
-	chr->weapons[WEAPON_GUN].got = 1;
-	chr->weapons[WEAPON_GUN].ammo = 10;
+	pChr->GiveWeapon(WEAPON_HAMMER, -1);
+	pChr->GiveWeapon(WEAPON_GUN, 10);
 }
 
-void GAMECONTROLLER::do_warmup(int seconds)
+void IGameController::DoWarmup(int Seconds)
 {
-	warmup = seconds*server_tickspeed();
+	if(Seconds < 0)
+		m_Warmup = 0;
+	else
+		m_Warmup = Seconds*Server()->TickSpeed();
 }
 
-bool GAMECONTROLLER::is_friendly_fire(int cid1, int cid2)
+bool IGameController::IsFriendlyFire(int Cid1, int Cid2)
 {
-	if(cid1 == cid2)
+	if(Cid1 == Cid2)
 		return false;
 	
-	if(is_teamplay())
+	if(IsTeamplay())
 	{
-		if(!game.players[cid1] || !game.players[cid2])
+		if(!GameServer()->m_apPlayers[Cid1] || !GameServer()->m_apPlayers[Cid2])
 			return false;
 			
-		if(game.players[cid1]->team == game.players[cid2]->team)
+		if(GameServer()->m_apPlayers[Cid1]->GetTeam() == GameServer()->m_apPlayers[Cid2]->GetTeam())
 			return true;
 	}
 	
 	return false;
 }
 
-bool GAMECONTROLLER::is_force_balanced()
+bool IGameController::IsForceBalanced()
 {
-	if(force_balanced)
+	if(m_ForceBalanced)
 	{
-		force_balanced = false;
+		m_ForceBalanced = false;
 		return true;
 	}
 	else
 		return false;
 }
 
-void GAMECONTROLLER::tick()
+bool IGameController::CanBeMovedOnBalance(int Cid)
+{
+	return true;
+}
+
+void IGameController::Tick()
 {
 	// do warmup
-	if(warmup)
+	if(m_Warmup)
 	{
-		warmup--;
-		if(!warmup)
-			startround();
+		m_Warmup--;
+		if(!m_Warmup)
+			StartRound();
 	}
 	
-	if(game_over_tick != -1)
+	if(m_GameOverTick != -1)
 	{
 		// game over.. wait for restart
-		if(server_tick() > game_over_tick+server_tickspeed()*10)
+		if(Server()->Tick() > m_GameOverTick+Server()->TickSpeed()*10)
 		{
-			cyclemap();
-			startround();
-			round_count++;
+			CycleMap();
+			StartRound();
+			m_RoundCount++;
 		}
 	}
 	
 	// do team-balancing
-	if (is_teamplay() && unbalanced_tick != -1 && server_tick() > unbalanced_tick+config.sv_teambalance_time*server_tickspeed()*60)
+	if (IsTeamplay() && m_UnbalancedTick != -1 && Server()->Tick() > m_UnbalancedTick+g_Config.m_SvTeambalanceTime*Server()->TickSpeed()*60)
 	{
 		dbg_msg("game", "Balancing teams");
 		
-		int t[2] = {0,0};
-		int tscore[2] = {0,0};
+		int aT[2] = {0,0};
+		int aTScore[2] = {0,0};
 		for(int i = 0; i < MAX_CLIENTS; i++)
 		{
-			if(game.players[i] && game.players[i]->team != -1)
+			if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() != -1)
 			{
-				t[game.players[i]->team]++;
-				tscore[game.players[i]->team]+=game.players[i]->score;
+				aT[GameServer()->m_apPlayers[i]->GetTeam()]++;
+				aTScore[GameServer()->m_apPlayers[i]->GetTeam()] += GameServer()->m_apPlayers[i]->m_Score;
 			}
 		}
 		
 		// are teams unbalanced?
-		if(abs(t[0]-t[1]) >= 2)
+		if(absolute(aT[0]-aT[1]) >= 2)
 		{
-			int m = (t[0] > t[1]) ? 0 : 1;
-			int num_balance = abs(t[0]-t[1]) / 2;
+			int M = (aT[0] > aT[1]) ? 0 : 1;
+			int NumBalance = absolute(aT[0]-aT[1]) / 2;
 			
 			do
 			{
-				PLAYER *p = 0;
-				int pd = tscore[m];
+				CPlayer *pP = 0;
+				int PD = aTScore[M];
 				for(int i = 0; i < MAX_CLIENTS; i++)
 				{
-					if(!game.players[i])
+					if(!GameServer()->m_apPlayers[i])
+						continue;
+					if(!CanBeMovedOnBalance(i))
 						continue;
-					
 					// remember the player who would cause lowest score-difference
-					if(game.players[i]->team == m && (!p || abs((tscore[m^1]+game.players[i]->score) - (tscore[m]-game.players[i]->score)) < pd))
+					if(GameServer()->m_apPlayers[i]->GetTeam() == M && (!pP || absolute((aTScore[M^1]+GameServer()->m_apPlayers[i]->m_Score) - (aTScore[M]-GameServer()->m_apPlayers[i]->m_Score)) < PD))
 					{
-						p = game.players[i];
-						pd = abs((tscore[m^1]+p->score) - (tscore[m]-p->score));
+						pP = GameServer()->m_apPlayers[i];
+						PD = absolute((aTScore[M^1]+pP->m_Score) - (aTScore[M]-pP->m_Score));
 					}
 				}
 				
 				// move the player to other team without losing his score
 				// TODO: change in player::set_team needed: player won't lose score on team-change
-				int score_before = p->score;
-				p->set_team(m^1);
-				p->score = score_before;
+				int ScoreBefore = pP->m_Score;
+				pP->SetTeam(M^1);
+				pP->m_Score = ScoreBefore;
 				
-				p->respawn();
-				p->force_balanced = true;
-			} while (--num_balance);
+				pP->Respawn();
+				pP->m_ForceBalanced = true;
+			} while (--NumBalance);
 			
-			force_balanced = true;
+			m_ForceBalanced = true;
 		}
-		unbalanced_tick = -1;
+		m_UnbalancedTick = -1;
 	}
 	
 	// update browse info
-	int prog = -1;
-	if(config.sv_timelimit > 0)
-		prog = max(prog, (server_tick()-round_start_tick) * 100 / (config.sv_timelimit*server_tickspeed()*60));
+	int Prog = -1;
+	if(g_Config.m_SvTimelimit > 0)
+		Prog = max(Prog, (Server()->Tick()-m_RoundStartTick) * 100 / (g_Config.m_SvTimelimit*Server()->TickSpeed()*60));
 
-	if(config.sv_scorelimit)
+	if(g_Config.m_SvScorelimit)
 	{
-		if(is_teamplay())
+		if(IsTeamplay())
 		{
-			prog = max(prog, (teamscore[0]*100)/config.sv_scorelimit);
-			prog = max(prog, (teamscore[1]*100)/config.sv_scorelimit);
+			Prog = max(Prog, (m_aTeamscore[0]*100)/g_Config.m_SvScorelimit);
+			Prog = max(Prog, (m_aTeamscore[1]*100)/g_Config.m_SvScorelimit);
 		}
 		else
 		{
 			for(int i = 0; i < MAX_CLIENTS; i++)
 			{
-				if(game.players[i])
-					prog = max(prog, (game.players[i]->score*100)/config.sv_scorelimit);
+				if(GameServer()->m_apPlayers[i])
+					Prog = max(Prog, (GameServer()->m_apPlayers[i]->m_Score*100)/g_Config.m_SvScorelimit);
 			}
 		}
 	}
 
-	if(warmup)
-		prog = -1;
+	if(m_Warmup)
+		Prog = -1;
 		
-	server_setbrowseinfo(gametype, prog);
+	Server()->SetBrowseInfo(m_pGameType, Prog);
 }
 
 
-bool GAMECONTROLLER::is_teamplay() const
+bool IGameController::IsTeamplay() const
 {
-	return game_flags&GAMEFLAG_TEAMS;
+	return m_GameFlags&GAMEFLAG_TEAMS;
 }
 
-void GAMECONTROLLER::snap(int snapping_client)
+void IGameController::Snap(int SnappingClient)
 {
-	NETOBJ_GAME *gameobj = (NETOBJ_GAME *)snap_new_item(NETOBJTYPE_GAME, 0, sizeof(NETOBJ_GAME));
-	gameobj->paused = game.world.paused;
-	gameobj->game_over = game_over_tick==-1?0:1;
-	gameobj->sudden_death = sudden_death;
+	CNetObj_Game *pGameObj = (CNetObj_Game *)Server()->SnapNewItem(NETOBJTYPE_GAME, 0, sizeof(CNetObj_Game));
+	pGameObj->m_Paused = GameServer()->m_World.m_Paused;
+	pGameObj->m_GameOver = m_GameOverTick==-1?0:1;
+	pGameObj->m_SuddenDeath = m_SuddenDeath;
 	
-	gameobj->score_limit = config.sv_scorelimit;
-	gameobj->time_limit = config.sv_timelimit;
-	gameobj->round_start_tick = round_start_tick;
-	gameobj->flags = game_flags;
+	pGameObj->m_ScoreLimit = g_Config.m_SvScorelimit;
+	pGameObj->m_TimeLimit = g_Config.m_SvTimelimit;
+	pGameObj->m_RoundStartTick = m_RoundStartTick;
+	pGameObj->m_Flags = m_GameFlags;
 	
-	gameobj->warmup = warmup;
+	pGameObj->m_Warmup = m_Warmup;
 	
-	gameobj->round_num = (strlen(config.sv_maprotation) && config.sv_rounds_per_map) ? config.sv_rounds_per_map : 0;
-	gameobj->round_current = round_count+1;
+	pGameObj->m_RoundNum = (str_length(g_Config.m_SvMaprotation) && g_Config.m_SvRoundsPerMap) ? g_Config.m_SvRoundsPerMap : 0;
+	pGameObj->m_RoundCurrent = m_RoundCount+1;
 	
 	
-	if(snapping_client == -1)
+	if(SnappingClient == -1)
 	{
 		// we are recording a demo, just set the scores
-		gameobj->teamscore_red = teamscore[0];
-		gameobj->teamscore_blue = teamscore[1];
+		pGameObj->m_TeamscoreRed = m_aTeamscore[0];
+		pGameObj->m_TeamscoreBlue = m_aTeamscore[1];
 	}
 	else
 	{
 		// TODO: this little hack should be removed
-		gameobj->teamscore_red = is_teamplay() ? teamscore[0] : game.players[snapping_client]->score;
-		gameobj->teamscore_blue = teamscore[1];
+		pGameObj->m_TeamscoreRed = IsTeamplay() ? m_aTeamscore[0] : GameServer()->m_apPlayers[SnappingClient]->m_Score;
+		pGameObj->m_TeamscoreBlue = m_aTeamscore[1];
 	}
 }
 
-int GAMECONTROLLER::get_auto_team(int notthisid)
+int IGameController::GetAutoTeam(int Notthisid)
 {
 	// this will force the auto balancer to work overtime aswell
-	if(config.dbg_stress)
+	if(g_Config.m_DbgStress)
 		return 0;
 	
-	int numplayers[2] = {0,0};
+	int aNumplayers[2] = {0,0};
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
-		if(game.players[i] && i != notthisid)
+		if(GameServer()->m_apPlayers[i] && i != Notthisid)
 		{
-			if(game.players[i]->team == 0 || game.players[i]->team == 1)
-				numplayers[game.players[i]->team]++;
+			if(GameServer()->m_apPlayers[i]->GetTeam() == 0 || GameServer()->m_apPlayers[i]->GetTeam() == 1)
+				aNumplayers[GameServer()->m_apPlayers[i]->GetTeam()]++;
 		}
 	}
 
-	int team = 0;
-	if(is_teamplay())
-		team = numplayers[0] > numplayers[1] ? 1 : 0;
+	int Team = 0;
+	if(IsTeamplay())
+		Team = aNumplayers[0] > aNumplayers[1] ? 1 : 0;
 		
-	if(can_join_team(team, notthisid))
-		return team;
+	if(CanJoinTeam(Team, Notthisid))
+		return Team;
 	return -1;
 }
 
-bool GAMECONTROLLER::can_join_team(int team, int notthisid)
+bool IGameController::CanJoinTeam(int Team, int Notthisid)
 {
-	(void)team;
-	int numplayers[2] = {0,0};
+	if(Team == -1)
+		return true;
+
+	int aNumplayers[2] = {0,0};
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
-		if(game.players[i] && i != notthisid)
+		if(GameServer()->m_apPlayers[i] && i != Notthisid)
 		{
-			if(game.players[i]->team >= 0 || game.players[i]->team == 1)
-				numplayers[game.players[i]->team]++;
+			if(GameServer()->m_apPlayers[i]->GetTeam() >= 0 || GameServer()->m_apPlayers[i]->GetTeam() == 1)
+				aNumplayers[GameServer()->m_apPlayers[i]->GetTeam()]++;
 		}
 	}
 	
-	return (numplayers[0] + numplayers[1]) < config.sv_max_clients-config.sv_spectator_slots;
+	return (aNumplayers[0] + aNumplayers[1]) < g_Config.m_SvMaxClients-g_Config.m_SvSpectatorSlots;
 }
 
-bool GAMECONTROLLER::check_team_balance()
+bool IGameController::CheckTeamBalance()
 {
-	if(!is_teamplay() || !config.sv_teambalance_time)
+	if(!IsTeamplay() || !g_Config.m_SvTeambalanceTime)
 		return true;
 	
-	int t[2] = {0, 0};
+	int aT[2] = {0, 0};
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
-		PLAYER *p = game.players[i];
-		if(p && p->team != -1)
-			t[p->team]++;
+		CPlayer *pP = GameServer()->m_apPlayers[i];
+		if(pP && pP->GetTeam() != -1)
+			aT[pP->GetTeam()]++;
 	}
 	
-	if(abs(t[0]-t[1]) >= 2)
+	if(absolute(aT[0]-aT[1]) >= 2)
 	{
-		dbg_msg("game", "Team is NOT balanced (red=%d blue=%d)", t[0], t[1]);
-		if (game.controller->unbalanced_tick == -1)
-			game.controller->unbalanced_tick = server_tick();
+		dbg_msg("game", "Team is NOT balanced (red=%d blue=%d)", aT[0], aT[1]);
+		if(GameServer()->m_pController->m_UnbalancedTick == -1)
+			GameServer()->m_pController->m_UnbalancedTick = Server()->Tick();
 		return false;
 	}
 	else
 	{
-		dbg_msg("game", "Team is balanced (red=%d blue=%d)", t[0], t[1]);
-		game.controller->unbalanced_tick = -1;
+		dbg_msg("game", "Team is balanced (red=%d blue=%d)", aT[0], aT[1]);
+		GameServer()->m_pController->m_UnbalancedTick = -1;
 		return true;
 	}
 }
 
-bool GAMECONTROLLER::can_change_team(PLAYER *pplayer, int jointeam)
+bool IGameController::CanChangeTeam(CPlayer *pPlayer, int JoinTeam)
 {
-	int t[2] = {0, 0};
+	int aT[2] = {0, 0};
 	
-	if (!is_teamplay() || jointeam == -1 || !config.sv_teambalance_time)
+	if (!IsTeamplay() || JoinTeam == -1 || !g_Config.m_SvTeambalanceTime)
 		return true;
 	
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
-		PLAYER *p = game.players[i];
-		if(p && p->team != -1)
-			t[p->team]++;
+		CPlayer *pP = GameServer()->m_apPlayers[i];
+		if(pP && pP->GetTeam() != -1)
+			aT[pP->GetTeam()]++;
 	}
 	
 	// simulate what would happen if changed team
-	t[jointeam]++;
-	if (pplayer->team != -1)
-		t[jointeam^1]--;
+	aT[JoinTeam]++;
+	if (pPlayer->GetTeam() != -1)
+		aT[JoinTeam^1]--;
 	
 	// there is a player-difference of at least 2
-	if(abs(t[0]-t[1]) >= 2)
+	if(absolute(aT[0]-aT[1]) >= 2)
 	{
 		// player wants to join team with less players
-		if ((t[0] < t[1] && jointeam == 0) || (t[0] > t[1] && jointeam == 1))
+		if ((aT[0] < aT[1] && JoinTeam == 0) || (aT[0] > aT[1] && JoinTeam == 1))
 			return true;
 		else
 			return false;
@@ -610,62 +617,60 @@ bool GAMECONTROLLER::can_change_team(PLAYER *pplayer, int jointeam)
 		return true;
 }
 
-void GAMECONTROLLER::do_player_score_wincheck()
+void IGameController::DoPlayerScoreWincheck()
 {
-	if(game_over_tick == -1  && !warmup)
+	if(m_GameOverTick == -1  && !m_Warmup)
 	{
 		// gather some stats
-		int topscore = 0;
-		int topscore_count = 0;
+		int Topscore = 0;
+		int TopscoreCount = 0;
 		for(int i = 0; i < MAX_CLIENTS; i++)
 		{
-			if(game.players[i])
+			if(GameServer()->m_apPlayers[i])
 			{
-				if(game.players[i]->score > topscore)
+				if(GameServer()->m_apPlayers[i]->m_Score > Topscore)
 				{
-					topscore = game.players[i]->score;
-					topscore_count = 1;
+					Topscore = GameServer()->m_apPlayers[i]->m_Score;
+					TopscoreCount = 1;
 				}
-				else if(game.players[i]->score == topscore)
-					topscore_count++;
+				else if(GameServer()->m_apPlayers[i]->m_Score == Topscore)
+					TopscoreCount++;
 			}
 		}
 		
 		// check score win condition
-		if((config.sv_scorelimit > 0 && topscore >= config.sv_scorelimit) ||
-			(config.sv_timelimit > 0 && (server_tick()-round_start_tick) >= config.sv_timelimit*server_tickspeed()*60))
+		if((g_Config.m_SvScorelimit > 0 && Topscore >= g_Config.m_SvScorelimit) ||
+			(g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_RoundStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60))
 		{
-			if(topscore_count == 1)
-				endround();
+			if(TopscoreCount == 1)
+				EndRound();
 			else
-				sudden_death = 1;
+				m_SuddenDeath = 1;
 		}
 	}
 }
 
-void GAMECONTROLLER::do_team_score_wincheck()
+void IGameController::DoTeamScoreWincheck()
 {
-	if(game_over_tick == -1 && !warmup)
+	if(m_GameOverTick == -1 && !m_Warmup)
 	{
 		// check score win condition
-		if((config.sv_scorelimit > 0 && (teamscore[0] >= config.sv_scorelimit || teamscore[1] >= config.sv_scorelimit)) ||
-			(config.sv_timelimit > 0 && (server_tick()-round_start_tick) >= config.sv_timelimit*server_tickspeed()*60))
+		if((g_Config.m_SvScorelimit > 0 && (m_aTeamscore[0] >= g_Config.m_SvScorelimit || m_aTeamscore[1] >= g_Config.m_SvScorelimit)) ||
+			(g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_RoundStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60))
 		{
-			if(teamscore[0] != teamscore[1])
-				endround();
+			if(m_aTeamscore[0] != m_aTeamscore[1])
+				EndRound();
 			else
-				sudden_death = 1;
+				m_SuddenDeath = 1;
 		}
 	}
 }
 
-int GAMECONTROLLER::clampteam(int team)
+int IGameController::ClampTeam(int Team)
 {
-	if(team < 0) // spectator
+	if(Team < 0) // spectator
 		return -1;
-	if(is_teamplay())
-		return team&1;
+	if(IsTeamplay())
+		return Team&1;
 	return  0;
 }
-
-GAMECONTROLLER *gamecontroller = 0;
diff --git a/src/game/server/gamecontroller.h b/src/game/server/gamecontroller.h
new file mode 100644
index 00000000..0624dcab
--- /dev/null
+++ b/src/game/server/gamecontroller.h
@@ -0,0 +1,145 @@
+#ifndef GAME_SERVER_GAMECONTROLLER_H
+#define GAME_SERVER_GAMECONTROLLER_H
+
+#include <base/vmath.h>
+
+/*
+	Class: Game Controller
+		Controls the main game logic. Keeping track of team and player score,
+		winning conditions and specific game logic.
+*/
+class IGameController
+{
+	vec2 m_aaSpawnPoints[3][64];
+	int m_aNumSpawnPoints[3];
+	
+	class CGameContext *m_pGameServer;
+	class IServer *m_pServer;
+	
+protected:
+	CGameContext *GameServer() const { return m_pGameServer; }
+	IServer *Server() const { return m_pServer; }
+
+	struct CSpawnEval
+	{
+		CSpawnEval()
+		{
+			m_Got = false;
+			m_FriendlyTeam = -1;
+			m_Pos = vec2(100,100);
+		}
+			
+		vec2 m_Pos;
+		bool m_Got;
+		int m_FriendlyTeam;
+		float m_Score;
+	};
+
+	float EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos);
+	void EvaluateSpawnType(CSpawnEval *pEval, int Type);
+	bool EvaluateSpawn(class CPlayer *pP, vec2 *pPos);
+
+	void CycleMap();
+	void ResetGame();
+	
+	char m_aMapWish[128];
+
+	
+	int m_RoundStartTick;
+	int m_GameOverTick;
+	int m_SuddenDeath;
+	
+	int m_aTeamscore[2];
+	
+	int m_Warmup;
+	int m_RoundCount;
+	
+	int m_GameFlags;
+	int m_UnbalancedTick;
+	bool m_ForceBalanced;
+	
+public:
+	const char *m_pGameType;
+
+	bool IsTeamplay() const;
+	
+	IGameController(class CGameContext *pGameServer);
+	virtual ~IGameController();
+
+	void DoTeamScoreWincheck();
+	void DoPlayerScoreWincheck();
+	
+	void DoWarmup(int Seconds);
+	
+	void StartRound();
+	void EndRound();
+	void ChangeMap(const char *pToMap);
+	
+	bool IsFriendlyFire(int Cid1, int Cid2);
+	
+	bool IsForceBalanced();
+
+	/*
+	
+	*/	
+	virtual bool CanBeMovedOnBalance(int Cid);
+
+	virtual void Tick();
+	
+	virtual void Snap(int SnappingClient);
+	
+	/*
+		Function: on_entity
+			Called when the map is loaded to process an entity
+			in the map.
+			
+		Arguments:
+			index - Entity index.
+			pos - Where the entity is located in the world.
+			
+		Returns:
+			bool?
+	*/
+	virtual bool OnEntity(int Index, vec2 Pos);
+	
+	/*
+		Function: on_CCharacter_spawn
+			Called when a CCharacter spawns into the game world.
+			
+		Arguments:
+			chr - The CCharacter that was spawned.
+	*/
+	virtual void OnCharacterSpawn(class CCharacter *pChr);
+	
+	/*
+		Function: on_CCharacter_death
+			Called when a CCharacter in the world dies.
+			
+		Arguments:
+			victim - The CCharacter that died.
+			killer - The player that killed it.
+			weapon - What weapon that killed it. Can be -1 for undefined
+				weapon when switching team or player suicides.
+	*/
+	virtual int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon);
+
+
+	virtual void OnPlayerInfoChange(class CPlayer *pP);
+
+	//
+	virtual bool CanSpawn(class CPlayer *pP, vec2 *pPos);
+
+	/*
+	
+	*/	
+	virtual const char *GetTeamName(int Team);
+	virtual int GetAutoTeam(int NotThisId);
+	virtual bool CanJoinTeam(int Team, int NotThisId);
+	bool CheckTeamBalance();
+	bool CanChangeTeam(CPlayer *pPplayer, int JoinTeam);
+	int ClampTeam(int Team);
+
+	virtual void PostReset();
+};
+
+#endif
diff --git a/src/game/server/gamecontroller.hpp b/src/game/server/gamecontroller.hpp
deleted file mode 100644
index 26b8a81f..00000000
--- a/src/game/server/gamecontroller.hpp
+++ /dev/null
@@ -1,136 +0,0 @@
-#ifndef GAME_SERVER_GAMECONTROLLER_H
-#define GAME_SERVER_GAMECONTROLLER_H
-
-#include <base/vmath.hpp>
-
-/*
-	Class: Game Controller
-		Controls the main game logic. Keeping track of team and player score,
-		winning conditions and specific game logic.
-*/
-class GAMECONTROLLER
-{
-	vec2 spawn_points[3][64];
-	int num_spawn_points[3];
-protected:
-	struct SPAWNEVAL
-	{
-		SPAWNEVAL()
-		{
-			got = false;
-			friendly_team = -1;
-			pos = vec2(100,100);
-		}
-			
-		vec2 pos;
-		bool got;
-		int friendly_team;
-		float score;
-	};
-
-	float evaluate_spawn_pos(SPAWNEVAL *eval, vec2 pos);
-	void evaluate_spawn_type(SPAWNEVAL *eval, int type);
-	bool evaluate_spawn(class PLAYER *p, vec2 *pos);
-
-	void cyclemap();
-	void resetgame();
-	
-	char map_wish[128];
-
-	
-	int round_start_tick;
-	int game_over_tick;
-	int sudden_death;
-	
-	int teamscore[2];
-	
-	int warmup;
-	int round_count;
-	
-	int game_flags;
-	int unbalanced_tick;
-	bool force_balanced;
-	
-public:
-	const char *gametype;
-
-	bool is_teamplay() const;
-	
-	GAMECONTROLLER();
-	virtual ~GAMECONTROLLER();
-
-	void do_team_score_wincheck();
-	void do_player_score_wincheck();
-	
-	void do_warmup(int seconds);
-	
-	void startround();
-	void endround();
-	void change_map(const char *to_map);
-	
-	bool is_friendly_fire(int cid1, int cid2);
-	
-	bool is_force_balanced();
-
-	/*
-	
-	*/	
-	virtual void tick();
-	
-	virtual void snap(int snapping_client);
-	
-	/*
-		Function: on_entity
-			Called when the map is loaded to process an entity
-			in the map.
-			
-		Arguments:
-			index - Entity index.
-			pos - Where the entity is located in the world.
-			
-		Returns:
-			bool?
-	*/
-	virtual bool on_entity(int index, vec2 pos);
-	
-	/*
-		Function: on_character_spawn
-			Called when a character spawns into the game world.
-			
-		Arguments:
-			chr - The character that was spawned.
-	*/
-	virtual void on_character_spawn(class CHARACTER *chr);
-	
-	/*
-		Function: on_character_death
-			Called when a character in the world dies.
-			
-		Arguments:
-			victim - The character that died.
-			killer - The player that killed it.
-			weapon - What weapon that killed it. Can be -1 for undefined
-				weapon when switching team or player suicides.
-	*/
-	virtual int on_character_death(class CHARACTER *victim, class PLAYER *killer, int weapon);
-
-
-	virtual void on_player_info_change(class PLAYER *p);
-
-	//
-	virtual bool can_spawn(class PLAYER *p, vec2 *pos);
-
-	/*
-	
-	*/	
-	virtual const char *get_team_name(int team);
-	virtual int get_auto_team(int notthisid);
-	virtual bool can_join_team(int team, int notthisid);
-	bool check_team_balance();
-	bool can_change_team(PLAYER *pplayer, int jointeam);
-	int clampteam(int team);
-
-	virtual void post_reset();
-};
-
-#endif
diff --git a/src/game/server/gamemodes/ctf.cpp b/src/game/server/gamemodes/ctf.cpp
index b2146b51..3da88342 100644
--- a/src/game/server/gamemodes/ctf.cpp
+++ b/src/game/server/gamemodes/ctf.cpp
@@ -1,188 +1,205 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <engine/e_server_interface.h>
-#include <game/mapitems.hpp>
-#include <game/server/entities/character.hpp>
-#include <game/server/player.hpp>
-#include <game/server/gamecontext.hpp>
-#include "ctf.hpp"
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+#include <game/mapitems.h>
+#include <game/server/entities/character.h>
+#include <game/server/player.h>
+#include <game/server/gamecontext.h>
+#include "ctf.h"
 
-GAMECONTROLLER_CTF::GAMECONTROLLER_CTF()
+CGameControllerCTF::CGameControllerCTF(class CGameContext *pGameServer)
+: IGameController(pGameServer)
 {
-	flags[0] = 0;
-	flags[1] = 0;
-	gametype = "CTF";
-	game_flags = GAMEFLAG_TEAMS|GAMEFLAG_FLAGS;
+	m_apFlags[0] = 0;
+	m_apFlags[1] = 0;
+	m_pGameType = "CTF";
+	m_GameFlags = GAMEFLAG_TEAMS|GAMEFLAG_FLAGS;
 }
 
-bool GAMECONTROLLER_CTF::on_entity(int index, vec2 pos)
+bool CGameControllerCTF::OnEntity(int Index, vec2 Pos)
 {
-	if(GAMECONTROLLER::on_entity(index, pos))
+	if(IGameController::OnEntity(Index, Pos))
 		return true;
 	
-	int team = -1;
-	if(index == ENTITY_FLAGSTAND_RED) team = 0;
-	if(index == ENTITY_FLAGSTAND_BLUE) team = 1;
-	if(team == -1)
+	int Team = -1;
+	if(Index == ENTITY_FLAGSTAND_RED) Team = 0;
+	if(Index == ENTITY_FLAGSTAND_BLUE) Team = 1;
+	if(Team == -1)
 		return false;
 		
-	FLAG *f = new FLAG(team);
-	f->stand_pos = pos;
-	f->pos = pos;
-	flags[team] = f;
+	CFlag *F = new CFlag(&GameServer()->m_World, Team);
+	F->m_StandPos = Pos;
+	F->m_Pos = Pos;
+	m_apFlags[Team] = F;
+	GameServer()->m_World.InsertEntity(F);
 	return true;
 }
 
-int GAMECONTROLLER_CTF::on_character_death(class CHARACTER *victim, class PLAYER *killer, int weaponid)
+int CGameControllerCTF::OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int WeaponID)
 {
-	GAMECONTROLLER::on_character_death(victim, killer, weaponid);
-	int had_flag = 0;
+	IGameController::OnCharacterDeath(pVictim, pKiller, WeaponID);
+	int HadFlag = 0;
 	
 	// drop flags
-	for(int fi = 0; fi < 2; fi++)
+	for(int i = 0; i < 2; i++)
 	{
-		FLAG *f = flags[fi];
-		if(f && killer && f->carrying_character == killer->get_character())
-			had_flag |= 2;
-		if(f && f->carrying_character == victim)
+		CFlag *F = m_apFlags[i];
+		if(F && pKiller && pKiller->GetCharacter() && F->m_pCarryingCCharacter == pKiller->GetCharacter())
+			HadFlag |= 2;
+		if(F && F->m_pCarryingCCharacter == pVictim)
 		{
-			game.create_sound_global(SOUND_CTF_DROP);
-			f->drop_tick = server_tick();
-			f->carrying_character = 0;
-			f->vel = vec2(0,0);
+			GameServer()->CreateSoundGlobal(SOUND_CTF_DROP);
+			F->m_DropTick = Server()->Tick();
+			F->m_pCarryingCCharacter = 0;
+			F->m_Vel = vec2(0,0);
 			
-			if(killer && killer->team != victim->team)
-				killer->score++;
+			if(pKiller && pKiller->GetTeam() != pVictim->GetPlayer()->GetTeam())
+				pKiller->m_Score++;
 				
-			had_flag |= 1;
+			HadFlag |= 1;
 		}
 	}
 	
-	return had_flag;
+	return HadFlag;
+}
+
+bool CGameControllerCTF::CanBeMovedOnBalance(int Cid)
+{
+	CCharacter* Character = GameServer()->m_apPlayers[Cid]->GetCharacter();
+	if(Character)
+	{
+		for(int fi = 0; fi < 2; fi++)
+		{
+			CFlag *F = m_apFlags[fi];
+			if(F->m_pCarryingCCharacter == Character)
+				return false;
+		}
+	}
+	return true;
 }
 
-void GAMECONTROLLER_CTF::tick()
+void CGameControllerCTF::Tick()
 {
-	GAMECONTROLLER::tick();
+	IGameController::Tick();
 
-	do_team_score_wincheck();
+	DoTeamScoreWincheck();
 	
 	for(int fi = 0; fi < 2; fi++)
 	{
-		FLAG *f = flags[fi];
+		CFlag *F = m_apFlags[fi];
 		
-		if(!f)
+		if(!F)
 			continue;
 		
 		// flag hits death-tile, reset it
-		if(col_get((int)f->pos.x, (int)f->pos.y)&COLFLAG_DEATH)
+		if(GameServer()->Collision()->GetCollisionAt(F->m_Pos.x, F->m_Pos.y)&CCollision::COLFLAG_DEATH)
 		{
-			game.create_sound_global(SOUND_CTF_RETURN);
-			f->reset();
+			GameServer()->CreateSoundGlobal(SOUND_CTF_RETURN);
+			F->Reset();
 			continue;
 		}
 		
 		//
-		if(f->carrying_character)
+		if(F->m_pCarryingCCharacter)
 		{
 			// update flag position
-			f->pos = f->carrying_character->pos;
+			F->m_Pos = F->m_pCarryingCCharacter->m_Pos;
 			
-			if(flags[fi^1] && flags[fi^1]->at_stand)
+			if(m_apFlags[fi^1] && m_apFlags[fi^1]->m_AtStand)
 			{
-				if(distance(f->pos, flags[fi^1]->pos) < 32)
+				if(distance(F->m_Pos, m_apFlags[fi^1]->m_Pos) < 32)
 				{
 					// CAPTURE! \o/
-					teamscore[fi^1] += 100;
-					f->carrying_character->player->score += 5;
+					m_aTeamscore[fi^1] += 100;
+					F->m_pCarryingCCharacter->GetPlayer()->m_Score += 5;
 
 					dbg_msg("game", "flag_capture player='%d:%s'",
-						f->carrying_character->player->client_id,
-						server_clientname(f->carrying_character->player->client_id));
+						F->m_pCarryingCCharacter->GetPlayer()->GetCID(),
+						Server()->ClientName(F->m_pCarryingCCharacter->GetPlayer()->GetCID()));
 
-					char buf[512];
-					float capture_time = (server_tick() - f->grab_tick)/(float)server_tickspeed();
-					if(capture_time <= 60)
+					char Buf[512];
+					float CaptureTime = (Server()->Tick() - F->m_GrabTick)/(float)Server()->TickSpeed();
+					if(CaptureTime <= 60)
 					{
-						str_format(buf, sizeof(buf), "the %s flag was captured by %s (%d.%s%d seconds)", fi ? "blue" : "red", server_clientname(f->carrying_character->player->client_id), (int)capture_time%60, ((int)(capture_time*100)%100)<10?"0":"", (int)(capture_time*100)%100);
+						str_format(Buf, sizeof(Buf), "The %s flag was captured by %s (%d.%s%d seconds)", fi ? "blue" : "red", Server()->ClientName(F->m_pCarryingCCharacter->GetPlayer()->GetCID()), (int)CaptureTime%60, ((int)(CaptureTime*100)%100)<10?"0":"", (int)(CaptureTime*100)%100);
 					}
 					else
 					{
-						str_format(buf, sizeof(buf), "the %s flag was captured by %s", fi ? "blue" : "red", server_clientname(f->carrying_character->player->client_id));
+						str_format(Buf, sizeof(Buf), "The %s flag was captured by %s", fi ? "blue" : "red", Server()->ClientName(F->m_pCarryingCCharacter->GetPlayer()->GetCID()));
 					}
-					game.send_chat(-1, -2, buf);
+					GameServer()->SendChat(-1, -2, Buf);
 					for(int i = 0; i < 2; i++)
-						flags[i]->reset();
+						m_apFlags[i]->Reset();
 					
-					game.create_sound_global(SOUND_CTF_CAPTURE);
+					GameServer()->CreateSoundGlobal(SOUND_CTF_CAPTURE);
 				}
-			}			
+			}
 		}
 		else
 		{
-			CHARACTER *close_characters[MAX_CLIENTS];
-			int num = game.world.find_entities(f->pos, 32.0f, (ENTITY**)close_characters, MAX_CLIENTS, NETOBJTYPE_CHARACTER);
-			for(int i = 0; i < num; i++)
+			CCharacter *apCloseCCharacters[MAX_CLIENTS];
+			int Num = GameServer()->m_World.FindEntities(F->m_Pos, 32.0f, (CEntity**)apCloseCCharacters, MAX_CLIENTS, NETOBJTYPE_CHARACTER);
+			for(int i = 0; i < Num; i++)
 			{
-				if(!close_characters[i]->alive || close_characters[i]->player->team == -1 || col_intersect_line(f->pos, close_characters[i]->pos, NULL, NULL))
+				if(!apCloseCCharacters[i]->IsAlive() || apCloseCCharacters[i]->GetPlayer()->GetTeam() == -1 || GameServer()->Collision()->IntersectLine(F->m_Pos, apCloseCCharacters[i]->m_Pos, NULL, NULL))
 					continue;
 				
-				if(close_characters[i]->team == f->team)
+				if(apCloseCCharacters[i]->GetPlayer()->GetTeam() == F->m_Team)
 				{
 					// return the flag
-					if(!f->at_stand)
+					if(!F->m_AtStand)
 					{
-						CHARACTER *chr = close_characters[i];
-						chr->player->score += 1;
+						CCharacter *pChr = apCloseCCharacters[i];
+						pChr->GetPlayer()->m_Score += 1;
 
 						dbg_msg("game", "flag_return player='%d:%s'",
-							chr->player->client_id,
-							server_clientname(chr->player->client_id));
+							pChr->GetPlayer()->GetCID(),
+							Server()->ClientName(pChr->GetPlayer()->GetCID()));
 
-						game.create_sound_global(SOUND_CTF_RETURN);
-						f->reset();
+						GameServer()->CreateSoundGlobal(SOUND_CTF_RETURN);
+						F->Reset();
 					}
 				}
 				else
 				{
 					// take the flag
-					if(f->at_stand)
+					if(F->m_AtStand)
 					{
-						teamscore[fi^1]++;
-						f->grab_tick = server_tick();
+						m_aTeamscore[fi^1]++;
+						F->m_GrabTick = Server()->Tick();
 					}
-					f->at_stand = 0;
-					f->carrying_character = close_characters[i];
-					f->carrying_character->player->score += 1;
+					
+					F->m_AtStand = 0;
+					F->m_pCarryingCCharacter = apCloseCCharacters[i];
+					F->m_pCarryingCCharacter->GetPlayer()->m_Score += 1;
 
 					dbg_msg("game", "flag_grab player='%d:%s'",
-						f->carrying_character->player->client_id,
-						server_clientname(f->carrying_character->player->client_id));
+						F->m_pCarryingCCharacter->GetPlayer()->GetCID(),
+						Server()->ClientName(F->m_pCarryingCCharacter->GetPlayer()->GetCID()));
 					
 					for(int c = 0; c < MAX_CLIENTS; c++)
 					{
-						if(!game.players[c])
+						if(!GameServer()->m_apPlayers[c])
 							continue;
 							
-						if(game.players[c]->team == fi)
-							game.create_sound_global(SOUND_CTF_GRAB_EN, game.players[c]->client_id);
+						if(GameServer()->m_apPlayers[c]->GetTeam() == fi)
+							GameServer()->CreateSoundGlobal(SOUND_CTF_GRAB_EN, GameServer()->m_apPlayers[c]->GetCID());
 						else
-							game.create_sound_global(SOUND_CTF_GRAB_PL, game.players[c]->client_id);
+							GameServer()->CreateSoundGlobal(SOUND_CTF_GRAB_PL, GameServer()->m_apPlayers[c]->GetCID());
 					}
 					break;
 				}
 			}
 			
-			if(!f->carrying_character && !f->at_stand)
+			if(!F->m_pCarryingCCharacter && !F->m_AtStand)
 			{
-				if(server_tick() > f->drop_tick + server_tickspeed()*30)
+				if(Server()->Tick() > F->m_DropTick + Server()->TickSpeed()*30)
 				{
-					game.create_sound_global(SOUND_CTF_RETURN);
-					f->reset();
+					GameServer()->CreateSoundGlobal(SOUND_CTF_RETURN);
+					F->Reset();
 				}
 				else
 				{
-					f->vel.y += game.world.core.tuning.gravity;
-					move_box(&f->pos, &f->vel, vec2(f->phys_size, f->phys_size), 0.5f);
+					F->m_Vel.y += GameServer()->m_World.m_Core.m_Tuning.m_Gravity;
+					GameServer()->Collision()->MoveBox(&F->m_Pos, &F->m_Vel, vec2(F->m_PhysSize, F->m_PhysSize), 0.5f);
 				}
 			}
 		}
@@ -190,39 +207,36 @@ void GAMECONTROLLER_CTF::tick()
 }
 
 // Flag
-FLAG::FLAG(int _team)
-: ENTITY(NETOBJTYPE_FLAG)
+CFlag::CFlag(CGameWorld *pGameWorld, int Team)
+: CEntity(pGameWorld, NETOBJTYPE_FLAG)
 {
-	team = _team;
-	proximity_radius = phys_size;
-	carrying_character = 0x0;
-	grab_tick = 0;
-	
-	reset();
+	m_Team = Team;
+	m_ProximityRadius = m_PhysSize;
+	m_pCarryingCCharacter = 0x0;
+	m_GrabTick = 0;
 	
-	// TODO: should this be done here?
-	game.world.insert_entity(this);
+	Reset();
 }
 
-void FLAG::reset()
+void CFlag::Reset()
 {
-	carrying_character = 0x0;
-	at_stand = 1;
-	pos = stand_pos;
-	vel = vec2(0,0);
-	grab_tick = 0;
+	m_pCarryingCCharacter = 0x0;
+	m_AtStand = 1;
+	m_Pos = m_StandPos;
+	m_Vel = vec2(0,0);
+	m_GrabTick = 0;
 }
 
-void FLAG::snap(int snapping_client)
+void CFlag::Snap(int SnappingClient)
 {
-	NETOBJ_FLAG *flag = (NETOBJ_FLAG *)snap_new_item(NETOBJTYPE_FLAG, team, sizeof(NETOBJ_FLAG));
-	flag->x = (int)pos.x;
-	flag->y = (int)pos.y;
-	flag->team = team;
-	flag->carried_by = -1;
+	CNetObj_Flag *pFlag = (CNetObj_Flag *)Server()->SnapNewItem(NETOBJTYPE_FLAG, m_Team, sizeof(CNetObj_Flag));
+	pFlag->m_X = (int)m_Pos.x;
+	pFlag->m_Y = (int)m_Pos.y;
+	pFlag->m_Team = m_Team;
+	pFlag->m_CarriedBy = -1;
 	
-	if(at_stand)
-		flag->carried_by = -2;
-	else if(carrying_character && carrying_character->player)
-		flag->carried_by = carrying_character->player->client_id;
+	if(m_AtStand)
+		pFlag->m_CarriedBy = -2;
+	else if(m_pCarryingCCharacter && m_pCarryingCCharacter->GetPlayer())
+		pFlag->m_CarriedBy = m_pCarryingCCharacter->GetPlayer()->GetCID();
 }
diff --git a/src/game/server/gamemodes/ctf.h b/src/game/server/gamemodes/ctf.h
new file mode 100644
index 00000000..b86ad688
--- /dev/null
+++ b/src/game/server/gamemodes/ctf.h
@@ -0,0 +1,38 @@
+#ifndef GAME_SERVER_GAMEMODES_CTF_H
+#define GAME_SERVER_GAMEMODES_CTF_H
+#include <game/server/gamecontroller.h>
+#include <game/server/entity.h>
+
+class CGameControllerCTF : public IGameController
+{
+public:
+	class CFlag *m_apFlags[2];
+	
+	CGameControllerCTF(class CGameContext *pGameServer);
+	virtual bool CanBeMovedOnBalance(int Cid);
+	virtual void Tick();
+	
+	virtual bool OnEntity(int Index, vec2 Pos);
+	virtual int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon);
+};
+
+// TODO: move to seperate file
+class CFlag : public CEntity
+{
+public:
+	static const int m_PhysSize = 14;
+	CCharacter *m_pCarryingCCharacter;
+	vec2 m_Vel;
+	vec2 m_StandPos;
+	
+	int m_Team;
+	int m_AtStand;
+	int m_DropTick;
+	int m_GrabTick;
+	
+	CFlag(CGameWorld *pGameWorld, int Team);
+
+	virtual void Reset();
+	virtual void Snap(int SnappingClient);
+};
+#endif
diff --git a/src/game/server/gamemodes/ctf.hpp b/src/game/server/gamemodes/ctf.hpp
deleted file mode 100644
index 67a098a4..00000000
--- a/src/game/server/gamemodes/ctf.hpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-
-#include <game/server/gamecontroller.hpp>
-#include <game/server/entity.hpp>
-
-class GAMECONTROLLER_CTF : public GAMECONTROLLER
-{
-public:
-	class FLAG *flags[2];
-	
-	GAMECONTROLLER_CTF();
-	virtual void tick();
-	
-	virtual bool on_entity(int index, vec2 pos);
-	virtual int on_character_death(class CHARACTER *victim, class PLAYER *killer, int weapon);
-};
-
-// TODO: move to seperate file
-class FLAG : public ENTITY
-{
-public:
-	static const int phys_size = 14;
-	CHARACTER *carrying_character;
-	vec2 vel;
-	vec2 stand_pos;
-	
-	int team;
-	int at_stand;
-	int drop_tick;
-	int grab_tick;
-	
-	FLAG(int _team);
-
-	virtual void reset();
-	virtual void snap(int snapping_client);
-};
diff --git a/src/game/server/gamemodes/dm.cpp b/src/game/server/gamemodes/dm.cpp
index 15c0b987..173ef5fd 100644
--- a/src/game/server/gamemodes/dm.cpp
+++ b/src/game/server/gamemodes/dm.cpp
@@ -1,14 +1,15 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include "dm.hpp"
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+#include "dm.h"
 
 
-GAMECONTROLLER_DM::GAMECONTROLLER_DM()
+CGameControllerDM::CGameControllerDM(class CGameContext *pGameServer)
+: IGameController(pGameServer)
 {
-	gametype = "DM";
+	m_pGameType = "DM";
 }
 
-void GAMECONTROLLER_DM::tick()
+void CGameControllerDM::Tick()
 {
-	do_player_score_wincheck();
-	GAMECONTROLLER::tick();
+	DoPlayerScoreWincheck();
+	IGameController::Tick();
 }
diff --git a/src/game/server/gamemodes/dm.h b/src/game/server/gamemodes/dm.h
new file mode 100644
index 00000000..f2854680
--- /dev/null
+++ b/src/game/server/gamemodes/dm.h
@@ -0,0 +1,11 @@
+#ifndef GAME_SERVER_GAMEMODES_DM_H
+#define GAME_SERVER_GAMEMODES_DM_H
+#include <game/server/gamecontroller.h>
+
+class CGameControllerDM : public IGameController
+{
+public:
+	CGameControllerDM(class CGameContext *pGameServer);
+	virtual void Tick();
+};
+#endif
diff --git a/src/game/server/gamemodes/dm.hpp b/src/game/server/gamemodes/dm.hpp
deleted file mode 100644
index 6fb25f61..00000000
--- a/src/game/server/gamemodes/dm.hpp
+++ /dev/null
@@ -1,10 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-
-#include <game/server/gamecontroller.hpp>
-
-class GAMECONTROLLER_DM : public GAMECONTROLLER
-{
-public:
-	GAMECONTROLLER_DM();
-	virtual void tick();
-};
diff --git a/src/game/server/gamemodes/mod.cpp b/src/game/server/gamemodes/mod.cpp
index 87b37411..44d0effc 100644
--- a/src/game/server/gamemodes/mod.cpp
+++ b/src/game/server/gamemodes/mod.cpp
@@ -1,20 +1,21 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */

-#include "mod.hpp"

+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+#include "mod.h"

 

-GAMECONTROLLER_MOD::GAMECONTROLLER_MOD()

+CGameControllerMOD::CGameControllerMOD(class CGameContext *pGameServer)

+: IGameController(pGameServer)

 {

 	// Exchange this to a string that identifies your game mode.

 	// DM, TDM and CTF are reserved for teeworlds original modes.

-	gametype = "MOD";

+	m_pGameType = "MOD";

 	

-	//game_flags = GAMEFLAG_TEAMS; // GAMEFLAG_TEAMS makes it a two-team gamemode

+	//m_GameFlags = GAMEFLAG_TEAMS; // GAMEFLAG_TEAMS makes it a two-team gamemode

 }

 

-void GAMECONTROLLER_MOD::tick()

+void CGameControllerMOD::Tick()

 {

 	// this is the main part of the gamemode, this function is run every tick

-	do_player_score_wincheck(); // checks for winners, no teams version

-	//do_team_score_wincheck(); // checks for winners, two teams version

+	DoPlayerScoreWincheck(); // checks for winners, no teams version

+	//DoTeamScoreWincheck(); // checks for winners, two teams version

 	

-	GAMECONTROLLER::tick();

+	IGameController::Tick();

 }

diff --git a/src/game/server/gamemodes/mod.h b/src/game/server/gamemodes/mod.h
new file mode 100644
index 00000000..86dff78b
--- /dev/null
+++ b/src/game/server/gamemodes/mod.h
@@ -0,0 +1,14 @@
+#ifndef GAME_SERVER_GAMEMODES_MOD_H
+#define GAME_SERVER_GAMEMODES_MOD_H
+#include <game/server/gamecontroller.h>

+

+// you can subclass GAMECONTROLLER_CTF, GAMECONTROLLER_TDM etc if you want

+// todo a modification with their base as well.

+class CGameControllerMOD : public IGameController

+{

+public:

+	CGameControllerMOD(class CGameContext *pGameServer);

+	virtual void Tick();

+	// add more virtual functions here if you wish

+};

+#endif
diff --git a/src/game/server/gamemodes/mod.hpp b/src/game/server/gamemodes/mod.hpp
deleted file mode 100644
index 9915a615..00000000
--- a/src/game/server/gamemodes/mod.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */

-

-#include <game/server/gamecontroller.hpp>

-

-// you can subclass GAMECONTROLLER_CTF, GAMECONTROLLER_TDM etc if you want

-// todo a modification with their base as well.

-class GAMECONTROLLER_MOD : public GAMECONTROLLER

-{

-public:

-	GAMECONTROLLER_MOD();

-	virtual void tick();

-	// add more virtual functions here if you wish

-};

diff --git a/src/game/server/gamemodes/tdm.cpp b/src/game/server/gamemodes/tdm.cpp
index 72605000..b54e3ac0 100644
--- a/src/game/server/gamemodes/tdm.cpp
+++ b/src/game/server/gamemodes/tdm.cpp
@@ -1,34 +1,33 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <engine/e_server_interface.h>
-#include <game/server/entities/character.hpp>
-#include <game/server/player.hpp>
-#include "tdm.hpp"
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+#include <game/server/entities/character.h>
+#include <game/server/player.h>
+#include "tdm.h"
 
-GAMECONTROLLER_TDM::GAMECONTROLLER_TDM()
+CGameControllerTDM::CGameControllerTDM(class CGameContext *pGameServer) : IGameController(pGameServer)
 {
-	gametype = "TDM";
-	game_flags = GAMEFLAG_TEAMS;
+	m_pGameType = "TDM";
+	m_GameFlags = GAMEFLAG_TEAMS;
 }
 
-int GAMECONTROLLER_TDM::on_character_death(class CHARACTER *victim, class PLAYER *killer, int weapon)
+int CGameControllerTDM::OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon)
 {
-	GAMECONTROLLER::on_character_death(victim, killer, weapon);
+	IGameController::OnCharacterDeath(pVictim, pKiller, Weapon);
 	
 	
-	if(weapon != WEAPON_GAME)
+	if(Weapon != WEAPON_GAME)
 	{
 		// do team scoring
-		if(killer == victim->player || killer->team == victim->player->team)
-			teamscore[killer->team&1]--; // klant arschel
+		if(pKiller == pVictim->GetPlayer() || pKiller->GetTeam() == pVictim->GetPlayer()->GetTeam())
+			m_aTeamscore[pKiller->GetTeam()&1]--; // klant arschel
 		else
-			teamscore[killer->team&1]++; // good shit
+			m_aTeamscore[pKiller->GetTeam()&1]++; // good shit
 	}
 		
 	return 0;
 }
 
-void GAMECONTROLLER_TDM::tick()
+void CGameControllerTDM::Tick()
 {
-	do_team_score_wincheck();
-	GAMECONTROLLER::tick();
+	DoTeamScoreWincheck();
+	IGameController::Tick();
 }
diff --git a/src/game/server/gamemodes/tdm.h b/src/game/server/gamemodes/tdm.h
new file mode 100644
index 00000000..2d149456
--- /dev/null
+++ b/src/game/server/gamemodes/tdm.h
@@ -0,0 +1,13 @@
+#ifndef GAME_SERVER_GAMEMODES_TDM_H
+#define GAME_SERVER_GAMEMODES_TDM_H
+#include <game/server/gamecontroller.h>
+
+class CGameControllerTDM : public IGameController
+{
+public:
+	CGameControllerTDM(class CGameContext *pGameServer);
+	
+	int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon);
+	virtual void Tick();
+};
+#endif
diff --git a/src/game/server/gamemodes/tdm.hpp b/src/game/server/gamemodes/tdm.hpp
deleted file mode 100644
index 51c47ca5..00000000
--- a/src/game/server/gamemodes/tdm.hpp
+++ /dev/null
@@ -1,12 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-
-#include <game/server/gamecontroller.hpp>
-
-class GAMECONTROLLER_TDM : public GAMECONTROLLER
-{
-public:
-	GAMECONTROLLER_TDM();
-	
-	int on_character_death(class CHARACTER *victim, class PLAYER *killer, int weapon);
-	virtual void tick();
-};
diff --git a/src/game/server/gameworld.cpp b/src/game/server/gameworld.cpp
index 9e76f14b..42c19487 100644
--- a/src/game/server/gameworld.cpp
+++ b/src/game/server/gameworld.cpp
@@ -1,217 +1,226 @@
 
-#include "gameworld.hpp"
-#include "entity.hpp"
-#include "gamecontext.hpp"
+#include "gameworld.h"
+#include "entity.h"
+#include "gamecontext.h"
 
 //////////////////////////////////////////////////
 // game world
 //////////////////////////////////////////////////
-GAMEWORLD::GAMEWORLD()
+CGameWorld::CGameWorld()
 {
-	paused = false;
-	reset_requested = false;
-	first_entity = 0x0;
+	m_pGameServer = 0x0;
+	m_pServer = 0x0;
+	
+	m_Paused = false;
+	m_ResetRequested = false;
+	m_pFirstEntity = 0x0;
 	for(int i = 0; i < NUM_ENT_TYPES; i++)
-		first_entity_types[i] = 0;
+		m_apFirstEntityTypes[i] = 0;
 }
 
-GAMEWORLD::~GAMEWORLD()
+CGameWorld::~CGameWorld()
 {
 	// delete all entities
-	while(first_entity)
-		delete first_entity;
+	while(m_pFirstEntity)
+		delete m_pFirstEntity;
+}
+
+void CGameWorld::SetGameServer(CGameContext *pGameServer)
+{
+	m_pGameServer = pGameServer;
+	m_pServer = m_pGameServer->Server();
 }
 
-ENTITY *GAMEWORLD::find_first(int type)
+CEntity *CGameWorld::FindFirst(int Type)
 {
-	return first_entity_types[type];
+	return m_apFirstEntityTypes[Type];
 }
 
 
-int GAMEWORLD::find_entities(vec2 pos, float radius, ENTITY **ents, int max, int type)
+int CGameWorld::FindEntities(vec2 Pos, float Radius, CEntity **ppEnts, int Max, int Type)
 {
-	int num = 0;
-	for(ENTITY *ent = (type<0) ? first_entity : first_entity_types[type];
-		ent; ent = (type<0) ? ent->next_entity : ent->next_type_entity)
+	int Num = 0;
+	for(CEntity *pEnt = (Type<0) ? m_pFirstEntity : m_apFirstEntityTypes[Type];
+		pEnt; pEnt = (Type<0) ? pEnt->m_pNextEntity : pEnt->m_pNextTypeEntity)
 	{
-		if(distance(ent->pos, pos) < radius+ent->proximity_radius)
+		if(distance(pEnt->m_Pos, Pos) < Radius+pEnt->m_ProximityRadius)
 		{
-			ents[num] = ent;
-			num++;
-			if(num == max)
+			ppEnts[Num] = pEnt;
+			Num++;
+			if(Num == Max)
 				break;
 		}
 	}
 
-	return num;
+	return Num;
 }
 
-void GAMEWORLD::insert_entity(ENTITY *ent)
+void CGameWorld::InsertEntity(CEntity *pEnt)
 {
-	ENTITY *cur = first_entity;
-	while(cur)
+	CEntity *pCur = m_pFirstEntity;
+	while(pCur)
 	{
-		dbg_assert(cur != ent, "err");
-		cur = cur->next_entity;
+		dbg_assert(pCur != pEnt, "err");
+		pCur = pCur->m_pNextEntity;
 	}
 
 	// insert it
-	if(first_entity)
-		first_entity->prev_entity = ent;
-	ent->next_entity = first_entity;
-	ent->prev_entity = 0x0;
-	first_entity = ent;
+	if(m_pFirstEntity)
+		m_pFirstEntity->m_pPrevEntity = pEnt;
+	pEnt->m_pNextEntity = m_pFirstEntity;
+	pEnt->m_pPrevEntity = 0x0;
+	m_pFirstEntity = pEnt;
 
 	// into typelist aswell
-	if(first_entity_types[ent->objtype])
-		first_entity_types[ent->objtype]->prev_type_entity = ent;
-	ent->next_type_entity = first_entity_types[ent->objtype];
-	ent->prev_type_entity = 0x0;
-	first_entity_types[ent->objtype] = ent;
+	if(m_apFirstEntityTypes[pEnt->m_Objtype])
+		m_apFirstEntityTypes[pEnt->m_Objtype]->m_pPrevTypeEntity = pEnt;
+	pEnt->m_pNextTypeEntity = m_apFirstEntityTypes[pEnt->m_Objtype];
+	pEnt->m_pPrevTypeEntity = 0x0;
+	m_apFirstEntityTypes[pEnt->m_Objtype] = pEnt;
 }
 
-void GAMEWORLD::destroy_entity(ENTITY *ent)
+void CGameWorld::DestroyEntity(CEntity *pEnt)
 {
-	ent->marked_for_destroy = true;
+	pEnt->m_MarkedForDestroy = true;
 }
 
-void GAMEWORLD::remove_entity(ENTITY *ent)
+void CGameWorld::RemoveEntity(CEntity *pEnt)
 {
 	// not in the list
-	if(!ent->next_entity && !ent->prev_entity && first_entity != ent)
+	if(!pEnt->m_pNextEntity && !pEnt->m_pPrevEntity && m_pFirstEntity != pEnt)
 		return;
 
 	// remove
-	if(ent->prev_entity)
-		ent->prev_entity->next_entity = ent->next_entity;
+	if(pEnt->m_pPrevEntity)
+		pEnt->m_pPrevEntity->m_pNextEntity = pEnt->m_pNextEntity;
 	else
-		first_entity = ent->next_entity;
-	if(ent->next_entity)
-		ent->next_entity->prev_entity = ent->prev_entity;
+		m_pFirstEntity = pEnt->m_pNextEntity;
+	if(pEnt->m_pNextEntity)
+		pEnt->m_pNextEntity->m_pPrevEntity = pEnt->m_pPrevEntity;
 
-	if(ent->prev_type_entity)
-		ent->prev_type_entity->next_type_entity = ent->next_type_entity;
+	if(pEnt->m_pPrevTypeEntity)
+		pEnt->m_pPrevTypeEntity->m_pNextTypeEntity = pEnt->m_pNextTypeEntity;
 	else
-		first_entity_types[ent->objtype] = ent->next_type_entity;
-	if(ent->next_type_entity)
-		ent->next_type_entity->prev_type_entity = ent->prev_type_entity;
-
-	ent->next_entity = 0;
-	ent->prev_entity = 0;
-	ent->next_type_entity = 0;
-	ent->prev_type_entity = 0;
+		m_apFirstEntityTypes[pEnt->m_Objtype] = pEnt->m_pNextTypeEntity;
+	if(pEnt->m_pNextTypeEntity)
+		pEnt->m_pNextTypeEntity->m_pPrevTypeEntity = pEnt->m_pPrevTypeEntity;
+
+	pEnt->m_pNextEntity = 0;
+	pEnt->m_pPrevEntity = 0;
+	pEnt->m_pNextTypeEntity = 0;
+	pEnt->m_pPrevTypeEntity = 0;
 }
 
 //
-void GAMEWORLD::snap(int snapping_client)
+void CGameWorld::Snap(int SnappingClient)
 {
-	for(ENTITY *ent = first_entity; ent; ent = ent->next_entity)
-		ent->snap(snapping_client);
+	for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity)
+		pEnt->Snap(SnappingClient);
 }
 
-void GAMEWORLD::reset()
+void CGameWorld::Reset()
 {
 	// reset all entities
-	for(ENTITY *ent = first_entity; ent; ent = ent->next_entity)
-		ent->reset();
-	remove_entities();
+	for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity)
+		pEnt->Reset();
+	RemoveEntities();
 
-	game.controller->post_reset();
-	remove_entities();
+	GameServer()->m_pController->PostReset();
+	RemoveEntities();
 
-	reset_requested = false;
+	m_ResetRequested = false;
 }
 
-void GAMEWORLD::remove_entities()
+void CGameWorld::RemoveEntities()
 {
 	// destroy objects marked for destruction
-	ENTITY *ent = first_entity;
-	while(ent)
+	CEntity *pEnt = m_pFirstEntity;
+	while(pEnt)
 	{
-		ENTITY *next = ent->next_entity;
-		if(ent->marked_for_destroy)
+		CEntity *pNext = pEnt->m_pNextEntity;
+		if(pEnt->m_MarkedForDestroy)
 		{
-			remove_entity(ent);
-			ent->destroy();
+			RemoveEntity(pEnt);
+			pEnt->Destroy();
 		}
-		ent = next;
+		pEnt = pNext;
 	}
 }
 
-void GAMEWORLD::tick()
+void CGameWorld::Tick()
 {
-	if(reset_requested)
-		reset();
+	if(m_ResetRequested)
+		Reset();
 
-	if(!paused)
+	if(!m_Paused)
 	{
-		if(game.controller->is_force_balanced())
-			game.send_chat(-1, GAMECONTEXT::CHAT_ALL, "Teams have been balanced");
+		if(GameServer()->m_pController->IsForceBalanced())
+			GameServer()->SendChat(-1, CGameContext::CHAT_ALL, "Teams have been balanced");
 		// update all objects
-		for(ENTITY *ent = first_entity; ent; ent = ent->next_entity)
-			ent->tick();
+		for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity)
+			pEnt->Tick();
 		
-		for(ENTITY *ent = first_entity; ent; ent = ent->next_entity)
-			ent->tick_defered();
+		for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity)
+			pEnt->TickDefered();
 	}
 
-	remove_entities();
+	RemoveEntities();
 }
 
 
 // TODO: should be more general
-CHARACTER *GAMEWORLD::intersect_character(vec2 pos0, vec2 pos1, float radius, vec2& new_pos, ENTITY *notthis)
+CCharacter *CGameWorld::IntersectCharacter(vec2 Pos0, vec2 Pos1, float Radius, vec2& NewPos, CEntity *pNotThis)
 {
 	// Find other players
-	float closest_len = distance(pos0, pos1) * 100.0f;
-	vec2 line_dir = normalize(pos1-pos0);
-	CHARACTER *closest = 0;
+	float ClosestLen = distance(Pos0, Pos1) * 100.0f;
+	vec2 LineDir = normalize(Pos1-Pos0);
+	CCharacter *pClosest = 0;
 
-	CHARACTER *p = (CHARACTER *)game.world.find_first(NETOBJTYPE_CHARACTER);
-	for(; p; p = (CHARACTER *)p->typenext())
+	CCharacter *p = (CCharacter *)FindFirst(NETOBJTYPE_CHARACTER);
+	for(; p; p = (CCharacter *)p->TypeNext())
  	{
-		if(p == notthis)
+		if(p == pNotThis)
 			continue;
 			
-		vec2 intersect_pos = closest_point_on_line(pos0, pos1, p->pos);
-		float len = distance(p->pos, intersect_pos);
-		if(len < CHARACTER::phys_size+radius)
+		vec2 IntersectPos = closest_point_on_line(Pos0, Pos1, p->m_Pos);
+		float Len = distance(p->m_Pos, IntersectPos);
+		if(Len < p->m_ProximityRadius+Radius)
 		{
-			if(len < closest_len)
+			if(Len < ClosestLen)
 			{
-				new_pos = intersect_pos;
-				closest_len = len;
-				closest = p;
+				NewPos = IntersectPos;
+				ClosestLen = Len;
+				pClosest = p;
 			}
 		}
 	}
 	
-	return closest;
+	return pClosest;
 }
 
 
-CHARACTER *GAMEWORLD::closest_character(vec2 pos, float radius, ENTITY *notthis)
+CCharacter *CGameWorld::ClosestCharacter(vec2 Pos, float Radius, CEntity *pNotThis)
 {
 	// Find other players
-	float closest_range = radius*2;
-	CHARACTER *closest = 0;
+	float ClosestRange = Radius*2;
+	CCharacter *pClosest = 0;
 		
-	CHARACTER *p = (CHARACTER *)game.world.find_first(NETOBJTYPE_CHARACTER);
-	for(; p; p = (CHARACTER *)p->typenext())
+	CCharacter *p = (CCharacter *)GameServer()->m_World.FindFirst(NETOBJTYPE_CHARACTER);
+	for(; p; p = (CCharacter *)p->TypeNext())
  	{
-		if(p == notthis)
+		if(p == pNotThis)
 			continue;
 			
-		float len = distance(pos, p->pos);
-		if(len < CHARACTER::phys_size+radius)
+		float Len = distance(Pos, p->m_Pos);
+		if(Len < p->m_ProximityRadius+Radius)
 		{
-			if(len < closest_range)
+			if(Len < ClosestRange)
 			{
-				closest_range = len;
-				closest = p;
+				ClosestRange = Len;
+				pClosest = p;
 			}
 		}
 	}
 	
-	return closest;
+	return pClosest;
 }
diff --git a/src/game/server/gameworld.hpp b/src/game/server/gameworld.h
index 4757ad67..2d1cc4be 100644
--- a/src/game/server/gameworld.hpp
+++ b/src/game/server/gameworld.h
@@ -1,20 +1,20 @@
 #ifndef GAME_SERVER_GAMEWORLD_H
 #define GAME_SERVER_GAMEWORLD_H
 
-#include <game/gamecore.hpp>
+#include <game/gamecore.h>
 
-class ENTITY;
-class CHARACTER;
+class CEntity;
+class CCharacter;
 
 /*
 	Class: Game World
 		Tracks all entities in the game. Propagates tick and
 		snap calls to all entities.
 */
-class GAMEWORLD
+class CGameWorld
 {
-	void reset();
-	void remove_entities();
+	void Reset();
+	void RemoveEntities();
 
 	enum
 	{
@@ -22,19 +22,27 @@ class GAMEWORLD
 	};
 
 	// TODO: two lists seams kinda not good, shouldn't be needed
-	ENTITY *first_entity;
-	ENTITY *first_entity_types[NUM_ENT_TYPES];
+	CEntity *m_pFirstEntity;
+	CEntity *m_apFirstEntityTypes[NUM_ENT_TYPES];
+	
+	class CGameContext *m_pGameServer;
+	class IServer *m_pServer;
 
 public:
-	bool reset_requested;
-	bool paused;
-	WORLD_CORE core;
+	class CGameContext *GameServer() { return m_pGameServer; }
+	class IServer *Server() { return m_pServer; }
+
+	bool m_ResetRequested;
+	bool m_Paused;
+	CWorldCore m_Core;
+	
+	CGameWorld();
+	~CGameWorld();
 	
-	GAMEWORLD();
-	~GAMEWORLD();
+	void SetGameServer(CGameContext *pGameServer);
 	
-	ENTITY *find_first() { return first_entity; }
-	ENTITY *find_first(int type);
+	CEntity *FindFirst() { return m_pFirstEntity; }
+	CEntity *FindFirst(int Type);
 	
 	/*
 		Function: find_entities
@@ -51,37 +59,37 @@ public:
 		Returns:
 			Number of entities found and added to the ents array.
 	*/
-	int find_entities(vec2 pos, float radius, ENTITY **ents, int max, int type = -1);
+	int FindEntities(vec2 Pos, float Radius, CEntity **ppEnts, int Max, int Type = -1);
 	
 	/*
-		Function: interserct_character
-			Finds the closest character that intersects the line.
+		Function: interserct_CCharacter
+			Finds the closest CCharacter that intersects the line.
 			
 		Arguments:
 			pos0 - Start position
 			pos2 - End position
-			radius - How for from the line the character is allowed to be.
+			radius - How for from the line the CCharacter is allowed to be.
 			new_pos - Intersection position
 			notthis - Entity to ignore intersecting with
 			
 		Returns:
 			Returns a pointer to the closest hit or NULL of there is no intersection.
 	*/
-	class CHARACTER *intersect_character(vec2 pos0, vec2 pos1, float radius, vec2 &new_pos, class ENTITY *notthis = 0);
+	class CCharacter *IntersectCharacter(vec2 Pos0, vec2 Pos1, float Radius, vec2 &NewPos, class CEntity *pNotThis = 0);
 	
 	/*
-		Function: closest_character
-			Finds the closest character to a specific point.
+		Function: closest_CCharacter
+			Finds the closest CCharacter to a specific point.
 			
 		Arguments:
 			pos - The center position.
-			radius - How far off the character is allowed to be
+			radius - How far off the CCharacter is allowed to be
 			notthis - Entity to ignore
 			
 		Returns:
-			Returns a pointer to the closest character or NULL if no character is close enough.
+			Returns a pointer to the closest CCharacter or NULL if no CCharacter is close enough.
 	*/
-	class CHARACTER *closest_character(vec2 pos, float radius, ENTITY *notthis);
+	class CCharacter *ClosestCharacter(vec2 Pos, float Radius, CEntity *ppNotThis);
 
 	/*
 		Function: insert_entity
@@ -90,7 +98,7 @@ public:
 		Arguments:
 			entity - Entity to add
 	*/
-	void insert_entity(ENTITY *entity);
+	void InsertEntity(CEntity *pEntity);
 
 	/*
 		Function: remove_entity
@@ -99,7 +107,7 @@ public:
 		Arguments:
 			entity - Entity to remove
 	*/
-	void remove_entity(ENTITY *entity);
+	void RemoveEntity(CEntity *pEntity);
 
 	/*
 		Function: destroy_entity
@@ -108,7 +116,7 @@ public:
 		Arguments:
 			entity - Entity to destroy
 	*/
-	void destroy_entity(ENTITY *entity);
+	void DestroyEntity(CEntity *pEntity);
 	
 	/*
 		Function: snap
@@ -119,7 +127,7 @@ public:
 			snapping_client - ID of the client which snapshot
 			is being created.
 	*/
-	void snap(int snapping_client);
+	void Snap(int SnappingClient);
 	
 	/*
 		Function: tick
@@ -127,7 +135,7 @@ public:
 			the world to the next tick.
 		
 	*/
-	void tick();
+	void Tick();
 };
 
 #endif
diff --git a/src/game/server/hooks.cpp b/src/game/server/hooks.cpp
deleted file mode 100644
index 89c95f79..00000000
--- a/src/game/server/hooks.cpp
+++ /dev/null
@@ -1,599 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <base/math.hpp>
-
-#include <engine/e_config.h>
-#include <engine/e_server_interface.h>
-#include <engine/e_memheap.h>
-
-#include <game/version.hpp>
-#include <game/collision.hpp>
-#include <game/layers.hpp>
-
-#include <game/gamecore.hpp>
-
-#include "gamecontext.hpp"
-#include "gamemodes/dm.hpp"
-#include "gamemodes/tdm.hpp"
-#include "gamemodes/ctf.hpp"
-#include "gamemodes/mod.hpp"
-
-TUNING_PARAMS tuning;
-
-static void check_pure_tuning()
-{
-	// might not be created yet during start up
-	if(!game.controller)
-		return;
-	
-	if(	strcmp(game.controller->gametype, "DM")==0 ||
-		strcmp(game.controller->gametype, "TDM")==0 ||
-		strcmp(game.controller->gametype, "CTF")==0)
-	{
-		TUNING_PARAMS p;
-		if(memcmp(&p, &tuning, sizeof(TUNING_PARAMS)) != 0)
-		{
-			dbg_msg("server", "resetting tuning due to pure server");
-			tuning = p;
-		}
-	}	
-}
-
-struct VOTEOPTION
-{
-	VOTEOPTION *next;
-	VOTEOPTION *prev;
-	char command[1];
-};
-
-static HEAP *voteoption_heap = 0;
-static VOTEOPTION *voteoption_first = 0;
-static VOTEOPTION *voteoption_last = 0;
-
-void send_tuning_params(int cid)
-{
-	check_pure_tuning();
-	
-	msg_pack_start(NETMSGTYPE_SV_TUNEPARAMS, MSGFLAG_VITAL);
-	int *params = (int *)&tuning;
-	for(unsigned i = 0; i < sizeof(tuning)/sizeof(int); i++)
-		msg_pack_int(params[i]);
-	msg_pack_end();
-	server_send_msg(cid);
-}
-
-// Server hooks
-void mods_client_direct_input(int client_id, void *input)
-{
-	if(!game.world.paused)
-		game.players[client_id]->on_direct_input((NETOBJ_PLAYER_INPUT *)input);
-}
-
-void mods_client_predicted_input(int client_id, void *input)
-{
-	if(!game.world.paused)
-		game.players[client_id]->on_predicted_input((NETOBJ_PLAYER_INPUT *)input);
-}
-
-// Server hooks
-void mods_tick()
-{
-	check_pure_tuning();
-	
-	game.tick();
-
-#ifdef CONF_DEBUG
-	if(config.dbg_dummies)
-	{
-		for(int i = 0; i < config.dbg_dummies ; i++)
-		{
-			NETOBJ_PLAYER_INPUT input = {0};
-			input.direction = (i&1)?-1:1;
-			game.players[MAX_CLIENTS-i-1]->on_predicted_input(&input);
-		}
-	}
-#endif
-}
-
-void mods_snap(int client_id)
-{
-	game.snap(client_id);
-}
-
-void mods_client_enter(int client_id)
-{
-	//game.world.insert_entity(&game.players[client_id]);
-	game.players[client_id]->respawn();
-	dbg_msg("game", "join player='%d:%s'", client_id, server_clientname(client_id));
-
-
-	char buf[512];
-	str_format(buf, sizeof(buf), "%s entered and joined the %s", server_clientname(client_id), game.controller->get_team_name(game.players[client_id]->team));
-	game.send_chat(-1, GAMECONTEXT::CHAT_ALL, buf); 
-
-	dbg_msg("game", "team_join player='%d:%s' team=%d", client_id, server_clientname(client_id), game.players[client_id]->team);
-}
-
-void mods_connected(int client_id)
-{
-	game.players[client_id] = new(client_id) PLAYER(client_id);
-	//game.players[client_id].init(client_id);
-	//game.players[client_id].client_id = client_id;
-	
-	// Check which team the player should be on
-	if(config.sv_tournament_mode)
-		game.players[client_id]->team = -1;
-	else
-		game.players[client_id]->team = game.controller->get_auto_team(client_id);
-		
-	(void) game.controller->check_team_balance();
-
-	// send motd
-	NETMSG_SV_MOTD msg;
-	msg.message = config.sv_motd;
-	msg.pack(MSGFLAG_VITAL);
-	server_send_msg(client_id);
-}
-
-void mods_client_drop(int client_id)
-{
-	game.abort_vote_kick_on_disconnect(client_id);
-	game.players[client_id]->on_disconnect();
-	delete game.players[client_id];
-	game.players[client_id] = 0;
-	
-	(void) game.controller->check_team_balance();
-}
-
-/*static bool is_separator(char c) { return c == ';' || c == ' ' || c == ',' || c == '\t'; }
-
-static const char *liststr_find(const char *str, const char *needle)
-{
-	int needle_len = strlen(needle);
-	while(*str)
-	{
-		int wordlen = 0;
-		while(str[wordlen] && !is_separator(str[wordlen]))
-			wordlen++;
-		
-		if(wordlen == needle_len && strncmp(str, needle, needle_len) == 0)
-			return str;
-		
-		str += wordlen+1;
-	}
-	
-	return 0;
-}*/
-
-void mods_message(int msgtype, int client_id)
-{
-	void *rawmsg = netmsg_secure_unpack(msgtype);
-	PLAYER *p = game.players[client_id];
-	
-	if(!rawmsg)
-	{
-		dbg_msg("server", "dropped weird message '%s' (%d), failed on '%s'", netmsg_get_name(msgtype), msgtype, netmsg_failed_on());
-		return;
-	}
-	
-	if(msgtype == NETMSGTYPE_CL_SAY)
-	{
-		NETMSG_CL_SAY *msg = (NETMSG_CL_SAY *)rawmsg;
-		int team = msg->team;
-		if(team)
-			team = p->team;
-		else
-			team = GAMECONTEXT::CHAT_ALL;
-		
-		if(config.sv_spamprotection && p->last_chat+time_freq() > time_get())
-			return;
-		
-		p->last_chat = time_get();
-		
-		game.send_chat(client_id, team, msg->message);
-	}
-	else if(msgtype == NETMSGTYPE_CL_CALLVOTE)
-	{
-		int64 now = time_get();
-		if(game.vote_closetime)
-		{
-			game.send_chat_target(client_id, "Wait for current vote to end before calling a new one.");
-			return;
-		}
-		
-		int64 timeleft = p->last_votecall + time_freq()*60 - now;
-		if(timeleft > 0)
-		{
-			char chatmsg[512] = {0};
-			str_format(chatmsg, sizeof(chatmsg), "You must wait %d seconds before making another vote", (timeleft/time_freq())+1);
-			game.send_chat_target(client_id, chatmsg);
-			return;
-		}
-		
-		char chatmsg[512] = {0};
-		char desc[512] = {0};
-		char cmd[512] = {0};
-		NETMSG_CL_CALLVOTE *msg = (NETMSG_CL_CALLVOTE *)rawmsg;
-		if(str_comp_nocase(msg->type, "option") == 0)
-		{
-			VOTEOPTION *option = voteoption_first;
-			while(option)
-			{
-				if(str_comp_nocase(msg->value, option->command) == 0)
-				{
-					str_format(chatmsg, sizeof(chatmsg), "%s called vote to change server option '%s'", server_clientname(client_id), option->command);
-					str_format(desc, sizeof(desc), "%s", option->command);
-					str_format(cmd, sizeof(cmd), "%s", option->command);
-					break;
-				}
-
-				option = option->next;
-			}
-			
-			if(!option)
-			{
-				str_format(chatmsg, sizeof(chatmsg), "'%s' isn't an option on this server", msg->value);
-				game.send_chat_target(client_id, chatmsg);
-				return;
-			}
-		}
-		else if(str_comp_nocase(msg->type, "kick") == 0)
-		{
-			if(!config.sv_vote_kick)
-			{
-				game.send_chat_target(client_id, "Server does not allow voting to kick players");
-				return;
-			}
-			
-			int kick_id = atoi(msg->value);
-			if(kick_id < 0 || kick_id >= MAX_CLIENTS || !game.players[kick_id])
-			{
-				game.send_chat_target(client_id, "Invalid client id to kick");
-				return;
-			}
-			
-			str_format(chatmsg, sizeof(chatmsg), "%s called for vote to kick '%s'", server_clientname(client_id), server_clientname(kick_id));
-			str_format(desc, sizeof(desc), "Kick '%s'", server_clientname(kick_id));
-			str_format(cmd, sizeof(cmd), "kick %d", kick_id);
-			if (!config.sv_vote_kick_bantime)
-				str_format(cmd, sizeof(cmd), "kick %d", kick_id);
-			else
-				str_format(cmd, sizeof(cmd), "ban %d %d", kick_id, config.sv_vote_kick_bantime);
-		}
-		
-		if(cmd[0])
-		{
-			game.send_chat(-1, GAMECONTEXT::CHAT_ALL, chatmsg);
-			game.start_vote(desc, cmd);
-			p->vote = 1;
-			game.vote_creator = client_id;
-			p->last_votecall = now;
-			game.send_vote_status(-1);
-		}
-	}
-	else if(msgtype == NETMSGTYPE_CL_VOTE)
-	{
-		if(!game.vote_closetime)
-			return;
-
-		if(p->vote == 0)
-		{
-			NETMSG_CL_VOTE *msg = (NETMSG_CL_VOTE *)rawmsg;
-			p->vote = msg->vote;
-			game.send_vote_status(-1);
-		}
-	}
-	else if (msgtype == NETMSGTYPE_CL_SETTEAM && !game.world.paused)
-	{
-		NETMSG_CL_SETTEAM *msg = (NETMSG_CL_SETTEAM *)rawmsg;
-		
-		if(config.sv_spamprotection && p->last_setteam+time_freq()*3 > time_get())
-			return;
-
-		// Switch team on given client and kill/respawn him
-		if(game.controller->can_join_team(msg->team, client_id))
-		{
-			if(game.controller->can_change_team(p, msg->team))
-			{
-				p->last_setteam = time_get();
-				p->set_team(msg->team);
-				(void) game.controller->check_team_balance();
-			}
-			else
-				game.send_broadcast("Teams must be balanced, please join other team", client_id);
-		}
-		else
-		{
-			char buf[128];
-			str_format(buf, sizeof(buf), "Only %d active players are allowed", config.sv_max_clients-config.sv_spectator_slots);
-			game.send_broadcast(buf, client_id);
-		}
-	}
-	else if (msgtype == NETMSGTYPE_CL_CHANGEINFO || msgtype == NETMSGTYPE_CL_STARTINFO)
-	{
-		NETMSG_CL_CHANGEINFO *msg = (NETMSG_CL_CHANGEINFO *)rawmsg;
-		
-		if(config.sv_spamprotection && p->last_changeinfo+time_freq()*5 > time_get())
-			return;
-			
-		p->last_changeinfo = time_get();
-		
-		p->use_custom_color = msg->use_custom_color;
-		p->color_body = msg->color_body;
-		p->color_feet = msg->color_feet;
-
-		// check for invalid chars
-		unsigned char *name = (unsigned char *)msg->name;
-		while (*name)
-		{
-			if(*name < 32)
-				*name = ' ';
-			name++;
-		}
-
-		// copy old name
-		char oldname[MAX_NAME_LENGTH];
-		str_copy(oldname, server_clientname(client_id), MAX_NAME_LENGTH);
-		
-		server_setclientname(client_id, msg->name);
-		if(msgtype == NETMSGTYPE_CL_CHANGEINFO && strcmp(oldname, server_clientname(client_id)) != 0)
-		{
-			char chattext[256];
-			str_format(chattext, sizeof(chattext), "%s changed name to %s", oldname, server_clientname(client_id));
-			game.send_chat(-1, GAMECONTEXT::CHAT_ALL, chattext);
-		}
-		
-		// set skin
-		str_copy(p->skin_name, msg->skin, sizeof(p->skin_name));
-		
-		game.controller->on_player_info_change(p);
-		
-		if(msgtype == NETMSGTYPE_CL_STARTINFO)
-		{
-			// send vote options
-			NETMSG_SV_VOTE_CLEAROPTIONS clearmsg;
-			clearmsg.pack(MSGFLAG_VITAL);
-			server_send_msg(client_id);
-			VOTEOPTION *current = voteoption_first;
-			while(current)
-			{
-				NETMSG_SV_VOTE_OPTION optionmsg;
-				optionmsg.command = current->command;
-				optionmsg.pack(MSGFLAG_VITAL);
-				server_send_msg(client_id);
-				current = current->next;
-			}
-			
-			// send tuning parameters to client
-			send_tuning_params(client_id);
-
-			//
-			NETMSG_SV_READYTOENTER m;
-			m.pack(MSGFLAG_VITAL|MSGFLAG_FLUSH);
-			server_send_msg(client_id);
-		}
-	}
-	else if (msgtype == NETMSGTYPE_CL_EMOTICON && !game.world.paused)
-	{
-		NETMSG_CL_EMOTICON *msg = (NETMSG_CL_EMOTICON *)rawmsg;
-		
-		if(config.sv_spamprotection && p->last_emote+time_freq()*3 > time_get())
-			return;
-			
-		p->last_emote = time_get();
-		
-		game.send_emoticon(client_id, msg->emoticon);
-	}
-	else if (msgtype == NETMSGTYPE_CL_KILL && !game.world.paused)
-	{
-		if(p->last_kill+time_freq()*3 > time_get())
-			return;
-		
-		p->last_kill = time_get();
-		p->kill_character(WEAPON_SELF);
-		p->respawn_tick = server_tick()+server_tickspeed()*3;
-	}
-}
-
-static void con_tune_param(void *result, void *user_data)
-{
-	const char *param_name = console_arg_string(result, 0);
-	float new_value = console_arg_float(result, 1);
-
-	if(tuning.set(param_name, new_value))
-	{
-		dbg_msg("tuning", "%s changed to %.2f", param_name, new_value);
-		send_tuning_params(-1);
-	}
-	else
-		console_print("No such tuning parameter");
-}
-
-static void con_tune_reset(void *result, void *user_data)
-{
-	TUNING_PARAMS p;
-	tuning = p;
-	send_tuning_params(-1);
-	console_print("tuning reset");
-}
-
-static void con_tune_dump(void *result, void *user_data)
-{
-	for(int i = 0; i < tuning.num(); i++)
-	{
-		float v;
-		tuning.get(i, &v);
-		dbg_msg("tuning", "%s %.2f", tuning.names[i], v);
-	}
-}
-
-
-static void con_change_map(void *result, void *user_data)
-{
-	game.controller->change_map(console_arg_string(result, 0));
-}
-
-static void con_restart(void *result, void *user_data)
-{
-	if(console_arg_num(result))
-		game.controller->do_warmup(console_arg_int(result, 0));
-	else
-		game.controller->startround();
-}
-
-static void con_broadcast(void *result, void *user_data)
-{
-	game.send_broadcast(console_arg_string(result, 0), -1);
-}
-
-static void con_say(void *result, void *user_data)
-{
-	game.send_chat(-1, GAMECONTEXT::CHAT_ALL, console_arg_string(result, 0));
-}
-
-static void con_set_team(void *result, void *user_data)
-{
-	int client_id = clamp(console_arg_int(result, 0), 0, (int)MAX_CLIENTS);
-	int team = clamp(console_arg_int(result, 1), -1, 1);
-	
-	dbg_msg("", "%d %d", client_id, team);
-	
-	if(!game.players[client_id])
-		return;
-	
-	game.players[client_id]->set_team(team);
-	(void) game.controller->check_team_balance();
-}
-
-static void con_addvote(void *result, void *user_data)
-{
-	int len = strlen(console_arg_string(result, 0));
-	
-	if(!voteoption_heap)
-		voteoption_heap = memheap_create();
-	
-	VOTEOPTION *option = (VOTEOPTION *)memheap_allocate(voteoption_heap, sizeof(VOTEOPTION) + len);
-	option->next = 0;
-	option->prev = voteoption_last;
-	if(option->prev)
-		option->prev->next = option;
-	voteoption_last = option;
-	if(!voteoption_first)
-		voteoption_first = option;
-	
-	mem_copy(option->command, console_arg_string(result, 0), len+1);
-	dbg_msg("server", "added option '%s'", option->command);
-}
-
-static void con_vote(void *result, void *user_data)
-{
-	if(str_comp_nocase(console_arg_string(result, 0), "yes") == 0)
-		game.vote_enforce = GAMECONTEXT::VOTE_ENFORCE_YES;
-	else if(str_comp_nocase(console_arg_string(result, 0), "no") == 0)
-		game.vote_enforce = GAMECONTEXT::VOTE_ENFORCE_NO;
-	dbg_msg("server", "forcing vote %s", console_arg_string(result, 0));
-}
-
-void mods_console_init()
-{
-	MACRO_REGISTER_COMMAND("tune", "si", CFGFLAG_SERVER, con_tune_param, 0, "");
-	MACRO_REGISTER_COMMAND("tune_reset", "", CFGFLAG_SERVER, con_tune_reset, 0, "");
-	MACRO_REGISTER_COMMAND("tune_dump", "", CFGFLAG_SERVER, con_tune_dump, 0, "");
-
-	MACRO_REGISTER_COMMAND("change_map", "r", CFGFLAG_SERVER, con_change_map, 0, "");
-	MACRO_REGISTER_COMMAND("restart", "?i", CFGFLAG_SERVER, con_restart, 0, "");
-	MACRO_REGISTER_COMMAND("broadcast", "r", CFGFLAG_SERVER, con_broadcast, 0, "");
-	MACRO_REGISTER_COMMAND("say", "r", CFGFLAG_SERVER, con_say, 0, "");
-	MACRO_REGISTER_COMMAND("set_team", "ii", CFGFLAG_SERVER, con_set_team, 0, "");
-
-	MACRO_REGISTER_COMMAND("addvote", "r", CFGFLAG_SERVER, con_addvote, 0, "");
-	MACRO_REGISTER_COMMAND("vote", "r", CFGFLAG_SERVER, con_vote, 0, "");
-}
-
-void mods_init()
-{
-	//if(!data) /* only load once */
-		//data = load_data_from_memory(internal_data);
-		
-	for(int i = 0; i < NUM_NETOBJTYPES; i++)
-		snap_set_staticsize(i, netobj_get_size(i));
-
-	layers_init();
-	col_init();
-
-	// reset everything here
-	//world = new GAMEWORLD;
-	//players = new PLAYER[MAX_CLIENTS];
-
-	// select gametype
-	if(strcmp(config.sv_gametype, "mod") == 0)
-		game.controller = new GAMECONTROLLER_MOD;
-	else if(strcmp(config.sv_gametype, "ctf") == 0)
-		game.controller = new GAMECONTROLLER_CTF;
-	else if(strcmp(config.sv_gametype, "tdm") == 0)
-		game.controller = new GAMECONTROLLER_TDM;
-	else
-		game.controller = new GAMECONTROLLER_DM;
-
-	// setup core world
-	//for(int i = 0; i < MAX_CLIENTS; i++)
-	//	game.players[i].core.world = &game.world.core;
-
-	// create all entities from the game layer
-	MAPITEM_LAYER_TILEMAP *tmap = layers_game_layer();
-	TILE *tiles = (TILE *)map_get_data(tmap->data);
-	
-	/*
-	num_spawn_points[0] = 0;
-	num_spawn_points[1] = 0;
-	num_spawn_points[2] = 0;
-	*/
-	
-	for(int y = 0; y < tmap->height; y++)
-	{
-		for(int x = 0; x < tmap->width; x++)
-		{
-			int index = tiles[y*tmap->width+x].index;
-			
-			if(index >= ENTITY_OFFSET)
-			{
-				vec2 pos(x*32.0f+16.0f, y*32.0f+16.0f);
-				game.controller->on_entity(index-ENTITY_OFFSET, pos);
-			}
-		}
-	}
-
-	//game.world.insert_entity(game.controller);
-
-#ifdef CONF_DEBUG
-	if(config.dbg_dummies)
-	{
-		for(int i = 0; i < config.dbg_dummies ; i++)
-		{
-			mods_connected(MAX_CLIENTS-i-1);
-			mods_client_enter(MAX_CLIENTS-i-1);
-			if(game.controller->is_teamplay())
-				game.players[MAX_CLIENTS-i-1]->team = i&1;
-		}
-	}
-#endif
-}
-
-void mods_shutdown()
-{
-	delete game.controller;
-	game.controller = 0;
-	game.clear();
-}
-
-void mods_presnap() {}
-void mods_postsnap()
-{
-	game.events.clear();
-}
-
-const char *mods_net_version() { return GAME_NETVERSION; }
-const char *mods_version() { return GAME_VERSION; }
diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp
index a0a2b051..0eb61cac 100644
--- a/src/game/server/player.cpp
+++ b/src/game/server/player.cpp
@@ -1,183 +1,185 @@
 #include <new>
+#include "player.h"
 
-#include <engine/e_server_interface.h>
 
-#include "player.hpp"
-#include "gamecontext.hpp"
+MACRO_ALLOC_POOL_ID_IMPL(CPlayer, MAX_CLIENTS)
 
-MACRO_ALLOC_POOL_ID_IMPL(PLAYER, MAX_CLIENTS)
-
-PLAYER::PLAYER(int client_id)
+IServer *CPlayer::Server() const { return m_pGameServer->Server(); }
+	
+CPlayer::CPlayer(CGameContext *pGameServer, int CID, int Team)
 {
-	respawn_tick = server_tick();
-	character = 0;
-	this->client_id = client_id;
+	m_pGameServer = pGameServer;
+	m_RespawnTick = Server()->Tick();
+	m_DieTick = Server()->Tick();
+	Character = 0;
+	this->m_ClientID = CID;
+	m_Team = GameServer()->m_pController->ClampTeam(Team);
 }
 
-PLAYER::~PLAYER()
+CPlayer::~CPlayer()
 {
-	delete character;
-	character = 0;
+	delete Character;
+	Character = 0;
 }
 
-void PLAYER::tick()
+void CPlayer::Tick()
 {
-	server_setclientscore(client_id, score);
+	Server()->SetClientScore(m_ClientID, m_Score);
 
 	// do latency stuff
 	{
-		CLIENT_INFO info;
-		if(server_getclientinfo(client_id, &info))
+		IServer::CClientInfo Info;
+		if(Server()->GetClientInfo(m_ClientID, &Info))
 		{
-			latency.accum += info.latency;
-			latency.accum_max = max(latency.accum_max, info.latency);
-			latency.accum_min = min(latency.accum_min, info.latency);
+			m_Latency.m_Accum += Info.m_Latency;
+			m_Latency.m_AccumMax = max(m_Latency.m_AccumMax, Info.m_Latency);
+			m_Latency.m_AccumMin = min(m_Latency.m_AccumMin, Info.m_Latency);
 		}
-
-		if(server_tick()%server_tickspeed() == 0)
+		// each second
+		if(Server()->Tick()%Server()->TickSpeed() == 0)
 		{
-			latency.avg = latency.accum/server_tickspeed();
-			latency.max = latency.accum_max;
-			latency.min = latency.accum_min;
-			latency.accum = 0;
-			latency.accum_min = 1000;
-			latency.accum_max = 0;
+			m_Latency.m_Avg = m_Latency.m_Accum/Server()->TickSpeed();
+			m_Latency.m_Max = m_Latency.m_AccumMax;
+			m_Latency.m_Min = m_Latency.m_AccumMin;
+			m_Latency.m_Accum = 0;
+			m_Latency.m_AccumMin = 1000;
+			m_Latency.m_AccumMax = 0;
 		}
 	}
 	
-	if(!character && die_tick+server_tickspeed()*3 <= server_tick())
-		spawning = true;
+	if(!Character && m_DieTick+Server()->TickSpeed()*3 <= Server()->Tick())
+		m_Spawning = true;
 
-	if(character)
+	if(Character)
 	{
-		if(character->alive)
+		if(Character->IsAlive())
 		{
-			view_pos = character->pos;
+			m_ViewPos = Character->m_Pos;
 		}
 		else
 		{
-			delete character;
-			character = 0;
+			delete Character;
+			Character = 0;
 		}
 	}
-	else if(spawning && respawn_tick <= server_tick())
-		try_respawn();
+	else if(m_Spawning && m_RespawnTick <= Server()->Tick())
+		TryRespawn();
 }
 
-void PLAYER::snap(int snapping_client)
+void CPlayer::Snap(int SnappingClient)
 {
-	NETOBJ_CLIENT_INFO *client_info = (NETOBJ_CLIENT_INFO *)snap_new_item(NETOBJTYPE_CLIENT_INFO, client_id, sizeof(NETOBJ_CLIENT_INFO));
-	str_to_ints(&client_info->name0, 6, server_clientname(client_id));
-	str_to_ints(&client_info->skin0, 6, skin_name);
-	client_info->use_custom_color = use_custom_color;
-	client_info->color_body = color_body;
-	client_info->color_feet = color_feet;
-
-	NETOBJ_PLAYER_INFO *info = (NETOBJ_PLAYER_INFO *)snap_new_item(NETOBJTYPE_PLAYER_INFO, client_id, sizeof(NETOBJ_PLAYER_INFO));
-
-	info->latency = latency.min;
-	info->latency_flux = latency.max-latency.min;
-	info->local = 0;
-	info->cid = client_id;
-	info->score = score;
-	info->team = team;
-
-	if(client_id == snapping_client)
-		info->local = 1;	
+	CNetObj_ClientInfo *ClientInfo = static_cast<CNetObj_ClientInfo *>(Server()->SnapNewItem(NETOBJTYPE_CLIENTINFO, m_ClientID, sizeof(CNetObj_ClientInfo)));
+	StrToInts(&ClientInfo->m_Name0, 6, Server()->ClientName(m_ClientID));
+	StrToInts(&ClientInfo->m_Skin0, 6, m_TeeInfos.m_SkinName);
+	ClientInfo->m_UseCustomColor = m_TeeInfos.m_UseCustomColor;
+	ClientInfo->m_ColorBody = m_TeeInfos.m_ColorBody;
+	ClientInfo->m_ColorFeet = m_TeeInfos.m_ColorFeet;
+
+	CNetObj_PlayerInfo *Info = static_cast<CNetObj_PlayerInfo *>(Server()->SnapNewItem(NETOBJTYPE_PLAYERINFO, m_ClientID, sizeof(CNetObj_PlayerInfo)));
+
+	Info->m_Latency = m_Latency.m_Min;
+	Info->m_LatencyFlux = m_Latency.m_Max-m_Latency.m_Min;
+	Info->m_Local = 0;
+	Info->m_ClientId = m_ClientID;
+	Info->m_Score = m_Score;
+	Info->m_Team = m_Team;
+
+	if(m_ClientID == SnappingClient)
+		Info->m_Local = 1;	
 }
 
-void PLAYER::on_disconnect()
+void CPlayer::OnDisconnect()
 {
-	kill_character(WEAPON_GAME);
-	
-	//game.controller->on_player_death(&game.players[client_id], 0, -1);
-		
-	char buf[512];
-	str_format(buf, sizeof(buf),  "%s has left the game", server_clientname(client_id));
-	game.send_chat(-1, GAMECONTEXT::CHAT_ALL, buf);
+	KillCharacter();
+
+	if(Server()->ClientIngame(m_ClientID))
+	{
+		char Buf[512];
+		str_format(Buf, sizeof(Buf),  "%s has left the game", Server()->ClientName(m_ClientID));
+		GameServer()->SendChat(-1, CGameContext::CHAT_ALL, Buf);
 
-	dbg_msg("game", "leave player='%d:%s'", client_id, server_clientname(client_id));
+		dbg_msg("game", "leave player='%d:%s'", m_ClientID, Server()->ClientName(m_ClientID));
+	}
 }
 
-void PLAYER::on_predicted_input(NETOBJ_PLAYER_INPUT *new_input)
+void CPlayer::OnPredictedInput(CNetObj_PlayerInput *NewInput)
 {
-	CHARACTER *chr = get_character();
-	if(chr)
-		chr->on_predicted_input(new_input);
+	if(Character)
+		Character->OnPredictedInput(NewInput);
 }
 
-void PLAYER::on_direct_input(NETOBJ_PLAYER_INPUT *new_input)
+void CPlayer::OnDirectInput(CNetObj_PlayerInput *NewInput)
 {
-	CHARACTER *chr = get_character();
-	if(chr)
-		chr->on_direct_input(new_input);
+	if(Character)
+		Character->OnDirectInput(NewInput);
 
-	if(!chr && team >= 0 && (new_input->fire&1))
-		spawning = true;
+	if(!Character && m_Team >= 0 && (NewInput->m_Fire&1))
+		m_Spawning = true;
 	
-	if(!chr && team == -1)
-		view_pos = vec2(new_input->target_x, new_input->target_y);
+	if(!Character && m_Team == -1)
+		m_ViewPos = vec2(NewInput->m_TargetX, NewInput->m_TargetY);
 }
 
-CHARACTER *PLAYER::get_character()
+CCharacter *CPlayer::GetCharacter()
 {
-	if(character && character->alive)
-		return character;
+	if(Character && Character->IsAlive())
+		return Character;
 	return 0;
 }
 
-void PLAYER::kill_character(int weapon)
+void CPlayer::KillCharacter(int Weapon)
 {
-	//CHARACTER *chr = get_character();
-	if(character)
+	if(Character)
 	{
-		character->die(client_id, weapon);
-		delete character;
-		character = 0;
+		Character->Die(m_ClientID, Weapon);
+		delete Character;
+		Character = 0;
 	}
 }
 
-void PLAYER::respawn()
+void CPlayer::Respawn()
 {
-	if(team > -1)
-		spawning = true;
+	if(m_Team > -1)
+		m_Spawning = true;
 }
 
-void PLAYER::set_team(int new_team)
+void CPlayer::SetTeam(int Team)
 {
 	// clamp the team
-	new_team = game.controller->clampteam(new_team);
-	if(team == new_team)
+	Team = GameServer()->m_pController->ClampTeam(Team);
+	if(m_Team == Team)
 		return;
 		
-	char buf[512];
-	str_format(buf, sizeof(buf), "%s joined the %s", server_clientname(client_id), game.controller->get_team_name(new_team));
-	game.send_chat(-1, GAMECONTEXT::CHAT_ALL, buf); 
+	char Buf[512];
+	str_format(Buf, sizeof(Buf), "%s joined the %s", Server()->ClientName(m_ClientID), GameServer()->m_pController->GetTeamName(Team));
+	GameServer()->SendChat(-1, CGameContext::CHAT_ALL, Buf); 
 	
-	kill_character(WEAPON_GAME);
-	team = new_team;
-	score = 0;
-	dbg_msg("game", "team_join player='%d:%s' team=%d", client_id, server_clientname(client_id), team);
+	KillCharacter();
+	m_Team = Team;
+	m_Score = 0;
+	// we got to wait 0.5 secs before respawning
+	m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2;
+	dbg_msg("game", "team_join player='%d:%s' m_Team=%d", m_ClientID, Server()->ClientName(m_ClientID), m_Team);
 	
-	game.controller->on_player_info_change(game.players[client_id]);
+	GameServer()->m_pController->OnPlayerInfoChange(GameServer()->m_apPlayers[m_ClientID]);
 }
 
-void PLAYER::try_respawn()
+void CPlayer::TryRespawn()
 {
-	vec2 spawnpos = vec2(100.0f, -60.0f);
+	vec2 SpawnPos = vec2(100.0f, -60.0f);
 	
-	if(!game.controller->can_spawn(this, &spawnpos))
+	if(!GameServer()->m_pController->CanSpawn(this, &SpawnPos))
 		return;
 
 	// check if the position is occupado
-	ENTITY *ents[2] = {0};
-	int num_ents = game.world.find_entities(spawnpos, 64, ents, 2, NETOBJTYPE_CHARACTER);
+	CEntity *apEnts[2] = {0};
+	int NumEnts = GameServer()->m_World.FindEntities(SpawnPos, 64, apEnts, 2, NETOBJTYPE_CHARACTER);
 	
-	if(num_ents == 0)
+	if(NumEnts == 0)
 	{
-		spawning = false;
-		character = new(client_id) CHARACTER();
-		character->spawn(this, spawnpos, team);
-		game.create_playerspawn(spawnpos);
+		m_Spawning = false;
+		Character = new(m_ClientID) CCharacter(&GameServer()->m_World);
+		Character->Spawn(this, SpawnPos);
+		GameServer()->CreatePlayerSpawn(SpawnPos);
 	}
 }
diff --git a/src/game/server/player.h b/src/game/server/player.h
new file mode 100644
index 00000000..1b631d45
--- /dev/null
+++ b/src/game/server/player.h
@@ -0,0 +1,89 @@
+#ifndef GAME_SERVER_PLAYER_H
+#define GAME_SERVER_PLAYER_H
+
+// this include should perhaps be removed
+#include "entities/character.h"
+#include "gamecontext.h"
+
+// player object
+class CPlayer
+{
+	MACRO_ALLOC_POOL_ID()
+	
+public:
+	CPlayer(CGameContext *pGameServer, int CID, int Team);
+	~CPlayer();
+
+	void Init(int CID);
+
+	void TryRespawn();
+	void Respawn();
+	void SetTeam(int Team);
+	int GetTeam() const { return m_Team; };
+	int GetCID() const { return m_ClientID; };
+	
+	void Tick();
+	void Snap(int SnappingClient);
+
+	void OnDirectInput(CNetObj_PlayerInput *NewInput);
+	void OnPredictedInput(CNetObj_PlayerInput *NewInput);
+	void OnDisconnect();
+	
+	void KillCharacter(int Weapon = WEAPON_GAME);
+	CCharacter *GetCharacter();
+	
+	//---------------------------------------------------------
+	// this is used for snapping so we know how we can clip the view for the player
+	vec2 m_ViewPos;
+	
+	//
+	int m_Vote;
+	int m_VotePos;
+	//
+	int m_Last_VoteCall;
+	int m_Last_VoteTry;
+	int m_Last_Chat;
+	int m_Last_SetTeam;
+	int m_Last_ChangeInfo;
+	int m_Last_Emote;
+	int m_Last_Kill;
+	
+	// TODO: clean this up
+	struct 
+	{
+		char m_SkinName[64];
+		int m_UseCustomColor;
+		int m_ColorBody;
+		int m_ColorFeet;
+	} m_TeeInfos;
+	
+	int m_RespawnTick;
+	int m_DieTick;
+	int m_Score;
+	bool m_ForceBalanced;
+	
+private:
+	CCharacter *Character;
+	CGameContext *m_pGameServer;
+	
+	CGameContext *GameServer() const { return m_pGameServer; }
+	IServer *Server() const;
+	
+	//
+	bool m_Spawning;
+	int m_ClientID;
+	int m_Team;
+
+	// network latency calculations	
+	struct
+	{
+		int m_Accum;
+		int m_AccumMin;
+		int m_AccumMax;
+		int m_Avg;
+		int m_Min;
+		int m_Max;	
+	} m_Latency;
+};
+
+#endif
diff --git a/src/game/server/player.hpp b/src/game/server/player.hpp
deleted file mode 100644
index e93aee01..00000000
--- a/src/game/server/player.hpp
+++ /dev/null
@@ -1,75 +0,0 @@
-#ifndef GAME_SERVER_PLAYER_H
-#define GAME_SERVER_PLAYER_H
-
-// this include should perhaps be removed
-#include "entities/character.hpp"
-
-// player object
-class PLAYER
-{
-	MACRO_ALLOC_POOL_ID()
-private:
-	CHARACTER *character;
-public:
-	PLAYER(int client_id);
-	~PLAYER();
-
-	// TODO: clean this up
-	char skin_name[64];
-	int use_custom_color;
-	int color_body;
-	int color_feet;
-	
-	int respawn_tick;
-	int die_tick;
-	//
-	bool spawning;
-	int client_id;
-	int team;
-	int score;
-	bool force_balanced;
-	
-	//
-	int vote;
-	int64 last_votecall;
-
-	//
-	int64 last_chat;
-	int64 last_setteam;
-	int64 last_changeinfo;
-	int64 last_emote;
-	int64 last_kill;
-
-	// network latency calculations	
-	struct
-	{
-		int accum;
-		int accum_min;
-		int accum_max;
-		int avg;
-		int min;
-		int max;	
-	} latency;
-	
-	// this is used for snapping so we know how we can clip the view for the player
-	vec2 view_pos;
-
-	void init(int client_id);
-	
-	CHARACTER *get_character();
-	
-	void kill_character(int weapon);
-
-	void try_respawn();
-	void respawn();
-	void set_team(int team);
-	
-	void tick();
-	void snap(int snapping_client);
-
-	void on_direct_input(NETOBJ_PLAYER_INPUT *new_input);
-	void on_predicted_input(NETOBJ_PLAYER_INPUT *new_input);
-	void on_disconnect();
-};
-
-#endif
diff --git a/src/game/tuning.h b/src/game/tuning.h
new file mode 100644
index 00000000..b336fcb3
--- /dev/null
+++ b/src/game/tuning.h
@@ -0,0 +1,46 @@
+#ifndef GAME_TUNING_H
+#define GAME_TUNING_H
+#undef GAME_TUNING_H // this file will be included several times
+
+// physics tuning
+MACRO_TUNING_PARAM(GroundControlSpeed, ground_control_speed, 10.0f)
+MACRO_TUNING_PARAM(GroundControlAccel, ground_control_accel, 100.0f / TicksPerSecond)
+MACRO_TUNING_PARAM(GroundFriction, ground_friction, 0.5f)
+MACRO_TUNING_PARAM(GroundJumpImpulse, ground_jump_impulse, 13.2f)
+MACRO_TUNING_PARAM(AirJumpImpulse, air_jump_impulse, 12.0f)
+MACRO_TUNING_PARAM(AirControlSpeed, air_control_speed, 250.0f / TicksPerSecond)
+MACRO_TUNING_PARAM(AirControlAccel, air_control_accel, 1.5f)
+MACRO_TUNING_PARAM(AirFriction, air_friction, 0.95f)
+MACRO_TUNING_PARAM(HookLength, hook_length, 380.0f)
+MACRO_TUNING_PARAM(HookFireSpeed, hook_fire_speed, 80.0f)
+MACRO_TUNING_PARAM(HookDragAccel, hook_drag_accel, 3.0f)
+MACRO_TUNING_PARAM(HookDragSpeed, hook_drag_speed, 15.0f)
+MACRO_TUNING_PARAM(Gravity, gravity, 0.5f)
+
+MACRO_TUNING_PARAM(VelrampStart, velramp_start, 550)
+MACRO_TUNING_PARAM(VelrampRange, velramp_range, 2000)
+MACRO_TUNING_PARAM(VelrampCurvature, velramp_curvature, 1.4f)
+
+// weapon tuning
+MACRO_TUNING_PARAM(GunCurvature, gun_curvature, 1.25f)
+MACRO_TUNING_PARAM(GunSpeed, gun_speed, 2200.0f)
+MACRO_TUNING_PARAM(GunLifetime, gun_lifetime, 2.0f)
+
+MACRO_TUNING_PARAM(ShotgunCurvature, shotgun_curvature, 1.25f)
+MACRO_TUNING_PARAM(ShotgunSpeed, shotgun_speed, 2750.0f)
+MACRO_TUNING_PARAM(ShotgunSpeeddiff, shotgun_speeddiff, 0.8f)
+MACRO_TUNING_PARAM(ShotgunLifetime, shotgun_lifetime, 0.20f)
+
+MACRO_TUNING_PARAM(GrenadeCurvature, grenade_curvature, 7.0f)
+MACRO_TUNING_PARAM(GrenadeSpeed, grenade_speed, 1000.0f)
+MACRO_TUNING_PARAM(GrenadeLifetime, grenade_lifetime, 2.0f)
+
+MACRO_TUNING_PARAM(LaserReach, laser_reach, 800.0f)
+MACRO_TUNING_PARAM(LaserBounceDelay, laser_bounce_delay, 150)
+MACRO_TUNING_PARAM(LaserBounceNum, laser_bounce_num, 1)
+MACRO_TUNING_PARAM(LaserBounceCost, laser_bounce_cost, 0)
+MACRO_TUNING_PARAM(LaserDamage, laser_damage, 5)
+
+MACRO_TUNING_PARAM(PlayerCollision, player_collision, 1)
+MACRO_TUNING_PARAM(PlayerHooking, player_hooking, 1)
+#endif
diff --git a/src/game/tuning.hpp b/src/game/tuning.hpp
deleted file mode 100644
index 4554a8eb..00000000
--- a/src/game/tuning.hpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/* physics tuning */
-MACRO_TUNING_PARAM(ground_control_speed, 10.0f)
-MACRO_TUNING_PARAM(ground_control_accel, 100.0f / ticks_per_second)
-MACRO_TUNING_PARAM(ground_friction, 0.5f)
-MACRO_TUNING_PARAM(ground_jump_impulse, 13.2f)
-MACRO_TUNING_PARAM(air_jump_impulse, 12.0f)
-MACRO_TUNING_PARAM(air_control_speed, 250.0f / ticks_per_second)
-MACRO_TUNING_PARAM(air_control_accel, 1.5f)
-MACRO_TUNING_PARAM(air_friction, 0.95f)
-MACRO_TUNING_PARAM(hook_length, 380.0f)
-MACRO_TUNING_PARAM(hook_fire_speed, 80.0f)
-MACRO_TUNING_PARAM(hook_drag_accel, 3.0f)
-MACRO_TUNING_PARAM(hook_drag_speed, 15.0f)
-MACRO_TUNING_PARAM(gravity, 0.5f)
-
-MACRO_TUNING_PARAM(velramp_start, 550)
-MACRO_TUNING_PARAM(velramp_range, 2000)
-MACRO_TUNING_PARAM(velramp_curvature, 1.4f)
-
-/* weapon tuning */
-MACRO_TUNING_PARAM(gun_curvature, 1.25f)
-MACRO_TUNING_PARAM(gun_speed, 2200.0f)
-MACRO_TUNING_PARAM(gun_lifetime, 2.0f)
-
-MACRO_TUNING_PARAM(shotgun_curvature, 1.25f)
-MACRO_TUNING_PARAM(shotgun_speed, 2750.0f)
-MACRO_TUNING_PARAM(shotgun_speeddiff, 0.8f)
-MACRO_TUNING_PARAM(shotgun_lifetime, 0.20f)
-
-MACRO_TUNING_PARAM(grenade_curvature, 7.0f)
-MACRO_TUNING_PARAM(grenade_speed, 1000.0f)
-MACRO_TUNING_PARAM(grenade_lifetime, 2.0f)
-
-MACRO_TUNING_PARAM(laser_reach, 800.0f)
-MACRO_TUNING_PARAM(laser_bounce_delay, 150)
-MACRO_TUNING_PARAM(laser_bounce_num, 1)
-MACRO_TUNING_PARAM(laser_bounce_cost, 0)
-MACRO_TUNING_PARAM(laser_damage, 5)
-
-MACRO_TUNING_PARAM(player_collision, 1)
-MACRO_TUNING_PARAM(player_hooking, 1)
diff --git a/src/game/variables.h b/src/game/variables.h
new file mode 100644
index 00000000..6a247671
--- /dev/null
+++ b/src/game/variables.h
@@ -0,0 +1,79 @@
+#ifndef GAME_VARIABLES_H
+#define GAME_VARIABLES_H
+#undef GAME_VARIABLES_H // this file will be included several times
+
+
+// client
+MACRO_CONFIG_INT(ClPredict, cl_predict, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Predict client movements")
+MACRO_CONFIG_INT(ClNameplates, cl_nameplates, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show nameplates")
+MACRO_CONFIG_INT(ClNameplatesAlways, cl_nameplates_always, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Always show nameplats disregarding of distance")
+MACRO_CONFIG_INT(ClAutoswitchWeapons, cl_autoswitch_weapons, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Auto switch weapon on pickup")
+
+MACRO_CONFIG_INT(ClShowfps, cl_showfps, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show ingame FPS counter")
+
+MACRO_CONFIG_INT(ClAirjumpindicator, cl_airjumpindicator, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "")
+MACRO_CONFIG_INT(ClThreadsoundloading, cl_threadsoundloading, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "")
+
+MACRO_CONFIG_INT(ClWarningTeambalance, cl_warning_teambalance, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Warn about team balance")
+
+MACRO_CONFIG_INT(ClMouseDeadzone, cl_mouse_deadzone, 300, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SAVE, "")
+MACRO_CONFIG_INT(ClMouseFollowfactor, cl_mouse_followfactor, 60, 0, 200, CFGFLAG_CLIENT|CFGFLAG_SAVE, "")
+MACRO_CONFIG_INT(ClMouseMaxDistance, cl_mouse_max_distance, 800, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SAVE, "")
+
+MACRO_CONFIG_INT(EdShowkeys, ed_showkeys, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "")
+
+MACRO_CONFIG_INT(ClFlow, cl_flow, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "")
+
+MACRO_CONFIG_INT(ClShowWelcome, cl_show_welcome, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "")
+MACRO_CONFIG_INT(ClMotdTime, cl_motd_time, 10, 0, 100, CFGFLAG_CLIENT|CFGFLAG_SAVE, "How long to show the server message of the day")
+
+MACRO_CONFIG_STR(ClVersionServer, cl_version_server, 100, "version.teeworlds.com", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Server to use to check for new versions")
+
+MACRO_CONFIG_STR(ClLanguagefile, cl_languagefile, 255, "", CFGFLAG_CLIENT|CFGFLAG_SAVE, "What language file to use")
+
+MACRO_CONFIG_INT(PlayerUseCustomColor, player_use_custom_color, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Toggles usage of custom colors")
+MACRO_CONFIG_INT(PlayerColorBody, player_color_body, 65408, 0, 0xFFFFFF, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player body color")
+MACRO_CONFIG_INT(PlayerColorFeet, player_color_feet, 65408, 0, 0xFFFFFF, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player feet color")
+MACRO_CONFIG_STR(PlayerSkin, player_skin, 64, "default", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player skin")
+
+MACRO_CONFIG_INT(UiPage, ui_page, 5, 0, 9, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface page")
+MACRO_CONFIG_INT(UiToolboxPage, ui_toolbox_page, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Toolbox page")
+MACRO_CONFIG_STR(UiServerAddress, ui_server_address, 25, "localhost:8303", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface server address")
+MACRO_CONFIG_INT(UiScale, ui_scale, 100, 1, 100000, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface scale")
+
+MACRO_CONFIG_INT(UiColorHue, ui_color_hue, 160, 0, 255, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface color hue")
+MACRO_CONFIG_INT(UiColorSat, ui_color_sat, 70, 0, 255, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface color saturation")
+MACRO_CONFIG_INT(UiColorLht, ui_color_lht, 175, 0, 255, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface color lightness")
+MACRO_CONFIG_INT(UiColorAlpha, ui_color_alpha, 228, 0, 255, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface alpha")
+
+MACRO_CONFIG_INT(GfxNoclip, gfx_noclip, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Disable clipping")
+
+// server
+MACRO_CONFIG_INT(SvWarmup, sv_warmup, 0, 0, 0, CFGFLAG_SERVER, "Number of seconds to do warpup before round starts")
+MACRO_CONFIG_STR(SvMotd, sv_motd, 900, "", CFGFLAG_SERVER, "Message of the day to display for the clients")
+MACRO_CONFIG_INT(SvTeamdamage, sv_teamdamage, 0, 0, 1, CFGFLAG_SERVER, "Team damage")
+MACRO_CONFIG_STR(SvMaprotation, sv_maprotation, 768, "", CFGFLAG_SERVER, "Maps to rotate between")
+MACRO_CONFIG_INT(SvRoundsPerMap, sv_rounds_per_map, 1, 1, 100, CFGFLAG_SERVER, "Number of rounds on each map before rotating")
+MACRO_CONFIG_INT(SvPowerups, sv_powerups, 1, 0, 1, CFGFLAG_SERVER, "Allow powerups like ninja")
+MACRO_CONFIG_INT(SvScorelimit, sv_scorelimit, 20, 0, 1000, CFGFLAG_SERVER, "Score limit (0 disables)")
+MACRO_CONFIG_INT(SvTimelimit, sv_timelimit, 0, 0, 1000, CFGFLAG_SERVER, "Time limit in minutes (0 disables)")
+MACRO_CONFIG_STR(SvGametype, sv_gametype, 32, "dm", CFGFLAG_SERVER, "Game type (dm, tdm, ctf)")
+MACRO_CONFIG_INT(SvTournamentMode, sv_tournament_mode, 0, 0, 1, CFGFLAG_SERVER, "Tournament mode. When enabled, players joins the server as spectator")
+MACRO_CONFIG_INT(SvSpamprotection, sv_spamprotection, 1, 0, 1, CFGFLAG_SERVER, "Spam protection")
+
+MACRO_CONFIG_INT(SvSpectatorSlots, sv_spectator_slots, 0, 0, MAX_CLIENTS, CFGFLAG_SERVER, "Number of slots to reserve for spectators")
+MACRO_CONFIG_INT(SvTeambalanceTime, sv_teambalance_time, 1, 0, 1000, CFGFLAG_SERVER, "How many minutes to wait before autobalancing teams")
+
+MACRO_CONFIG_INT(SvVoteKick, sv_vote_kick, 1, 0, 1, CFGFLAG_SERVER, "Allow voting to kick players")
+MACRO_CONFIG_INT(SvVoteKickBantime, sv_vote_kick_bantime, 5, 0, 1440, CFGFLAG_SERVER, "The time to ban a player if kicked by vote. 0 makes it just use kick")
+MACRO_CONFIG_INT(SvVoteScorelimit, sv_vote_scorelimit, 0, 0, 1, CFGFLAG_SERVER, "Allow voting to change score limit")
+MACRO_CONFIG_INT(SvVoteTimelimit, sv_vote_timelimit, 0, 0, 1, CFGFLAG_SERVER, "Allow voting to change time limit")
+
+// debug
+#ifdef CONF_DEBUG // this one can crash the server if not used correctly
+	MACRO_CONFIG_INT(DbgDummies, dbg_dummies, 0, 0, 15, CFGFLAG_SERVER, "")
+#endif
+
+MACRO_CONFIG_INT(DbgFocus, dbg_focus, 0, 0, 1, CFGFLAG_CLIENT, "")
+MACRO_CONFIG_INT(DbgTuning, dbg_tuning, 0, 0, 1, CFGFLAG_CLIENT, "")
+#endif
diff --git a/src/game/variables.hpp b/src/game/variables.hpp
deleted file mode 100644
index e0d9fe31..00000000
--- a/src/game/variables.hpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-
-
-/* client */
-MACRO_CONFIG_INT(cl_predict, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Predict client movements")
-MACRO_CONFIG_INT(cl_nameplates, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show nameplates")
-MACRO_CONFIG_INT(cl_nameplates_always, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Always show nameplats disregarding of distance")
-MACRO_CONFIG_INT(cl_autoswitch_weapons, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Auto switch weapon on pickup")
-
-MACRO_CONFIG_INT(cl_showfps, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show ingame FPS counter")
-
-MACRO_CONFIG_INT(cl_airjumpindicator, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "")
-MACRO_CONFIG_INT(cl_threadsoundloading, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "")
-
-MACRO_CONFIG_INT(cl_warning_teambalance, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Warn about team balance")
-
-MACRO_CONFIG_INT(cl_mouse_deadzone, 300, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SAVE, "")
-MACRO_CONFIG_INT(cl_mouse_followfactor, 60, 0, 200, CFGFLAG_CLIENT|CFGFLAG_SAVE, "")
-MACRO_CONFIG_INT(cl_mouse_max_distance, 800, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SAVE, "")
-
-MACRO_CONFIG_INT(ed_showkeys, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "")
-
-MACRO_CONFIG_INT(cl_flow, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "")
-
-MACRO_CONFIG_INT(cl_show_welcome, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "")
-MACRO_CONFIG_INT(cl_motd_time, 10, 0, 100, CFGFLAG_CLIENT|CFGFLAG_SAVE, "How long to show the server message of the day")
-
-MACRO_CONFIG_STR(cl_version_server, 100, "version.teeworlds.com", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Server to use to check for new versions")
-
-MACRO_CONFIG_STR(cl_languagefile, 255, "", CFGFLAG_CLIENT|CFGFLAG_SAVE, "What language file to use")
-
-MACRO_CONFIG_INT(player_use_custom_color, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Toggles usage of custom colors")
-MACRO_CONFIG_INT(player_color_body, 65408, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player body color")
-MACRO_CONFIG_INT(player_color_feet, 65408, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player feet color")
-MACRO_CONFIG_STR(player_skin, 64, "default", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player skin")
-
-MACRO_CONFIG_INT(ui_page, 5, 0, 9, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface page")
-MACRO_CONFIG_STR(ui_server_address, 128, "localhost:8303", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface server address")
-MACRO_CONFIG_INT(ui_scale, 100, 1, 100000, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface scale")
-
-MACRO_CONFIG_INT(ui_color_hue, 160, 0, 255, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface color hue")
-MACRO_CONFIG_INT(ui_color_sat, 70, 0, 255, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface color saturation")
-MACRO_CONFIG_INT(ui_color_lht, 175, 0, 255, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface color lightness")
-MACRO_CONFIG_INT(ui_color_alpha, 228, 0, 255, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface alpha")
-
-MACRO_CONFIG_INT(gfx_noclip, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Disable clipping")
-
-/* server */
-MACRO_CONFIG_INT(sv_warmup, 0, 0, 0, CFGFLAG_SERVER, "Number of seconds to do warpup before round starts")
-MACRO_CONFIG_STR(sv_motd, 900, "", CFGFLAG_SERVER, "Message of the day to display for the clients")
-MACRO_CONFIG_INT(sv_teamdamage, 0, 0, 1, CFGFLAG_SERVER, "Team damage")
-MACRO_CONFIG_STR(sv_maprotation, 768, "", CFGFLAG_SERVER, "Maps to rotate between")
-MACRO_CONFIG_INT(sv_rounds_per_map, 1, 1, 100, CFGFLAG_SERVER, "Number of rounds on each map before rotating")
-MACRO_CONFIG_INT(sv_powerups, 1, 0, 1, CFGFLAG_SERVER, "Allow powerups like ninja")
-MACRO_CONFIG_INT(sv_scorelimit, 20, 0, 1000, CFGFLAG_SERVER, "Score limit (0 disables)")
-MACRO_CONFIG_INT(sv_timelimit, 0, 0, 1000, CFGFLAG_SERVER, "Time limit in minutes (0 disables)")
-MACRO_CONFIG_STR(sv_gametype, 32, "dm", CFGFLAG_SERVER, "Game type (dm, tdm, ctf)")
-MACRO_CONFIG_INT(sv_tournament_mode, 0, 0, 1, CFGFLAG_SERVER, "Tournament mode. When enabled, players joins the server as spectator")
-MACRO_CONFIG_INT(sv_spamprotection, 1, 0, 1, CFGFLAG_SERVER, "Spam protection")
-
-MACRO_CONFIG_INT(sv_spectator_slots, 0, 0, MAX_CLIENTS, CFGFLAG_SERVER, "Number of slots to reserve for spectators")
-MACRO_CONFIG_INT(sv_teambalance_time, 1, 0, 1000, CFGFLAG_SERVER, "How many minutes to wait before autobalancing teams")
-
-MACRO_CONFIG_INT(sv_vote_kick, 1, 0, 1, CFGFLAG_SERVER, "Allow voting to kick players")
-MACRO_CONFIG_INT(sv_vote_kick_bantime, 5, 0, 1440, CFGFLAG_SERVER, "The time to ban a player if kicked by vote. 0 makes it just use kick")
-MACRO_CONFIG_INT(sv_vote_scorelimit, 0, 0, 1, CFGFLAG_SERVER, "Allow voting to change score limit")
-MACRO_CONFIG_INT(sv_vote_timelimit, 0, 0, 1, CFGFLAG_SERVER, "Allow voting to change time limit")
-
-/* debug */
-#ifdef CONF_DEBUG /* this one can crash the server if not used correctly */
-	MACRO_CONFIG_INT(dbg_dummies, 0, 0, 15, CFGFLAG_SERVER, "")
-#endif
-
-MACRO_CONFIG_INT(dbg_focus, 0, 0, 1, CFGFLAG_CLIENT, "")
-MACRO_CONFIG_INT(dbg_tuning, 0, 0, 1, CFGFLAG_CLIENT, "")
diff --git a/src/game/version.h b/src/game/version.h
new file mode 100644
index 00000000..0fe22c95
--- /dev/null
+++ b/src/game/version.h
@@ -0,0 +1,8 @@
+#ifndef GAME_VERSION_H
+#define GAME_VERSION_H
+#include "generated/nethash.c"
+#define GAME_VERSION "trunk"
+//#define GAME_NETVERSION "0.5 " GAME_NETVERSION_HASH
+// TODO: hash forced during refactoring. Remove later on
+#define GAME_NETVERSION "0.5 b67d1f1a1eea234e"
+#endif
diff --git a/src/game/version.hpp b/src/game/version.hpp
deleted file mode 100644
index 2692752c..00000000
--- a/src/game/version.hpp
+++ /dev/null
@@ -1,4 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include "generated/nethash.c"
-#define GAME_VERSION "trunk"
-#define GAME_NETVERSION "0.5 " GAME_NETVERSION_HASH
diff --git a/src/mastersrv/mastersrv.cpp b/src/mastersrv/mastersrv.cpp
index 34acf448..8e838086 100644
--- a/src/mastersrv/mastersrv.cpp
+++ b/src/mastersrv/mastersrv.cpp
@@ -1,10 +1,6 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <string.h>
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
 #include <base/system.h>
-
-extern "C" {
-	#include <engine/e_network.h>
-}
+#include <engine/shared/network.h>
 
 #include "mastersrv.h"
 
@@ -16,333 +12,338 @@ enum {
 	EXPIRE_TIME = 90
 };
 
-static struct CHECK_SERVER
+struct CCheckServer
 {
-	NETADDR address;
-	NETADDR alt_address;
-	int try_count;
-	int64 try_time;
-} check_servers[MAX_SERVERS];
-static int num_checkservers = 0;
+	NETADDR m_Address;
+	NETADDR m_AltAddress;
+	int m_TryCount;
+	int64 m_TryTime;
+};
 
+static CCheckServer m_aCheckServers[MAX_SERVERS];
+static int m_NumCheckServers = 0;
 
-typedef struct NETADDR_IPv4
+struct NETADDR_IPv4
 {
-	unsigned char ip[4];
-	unsigned short port;
-} NETADDR_IPv4;
+	unsigned char m_aIp[4];
+	unsigned short m_Port;
+};
 
-static struct SERVER_ENTRY
+struct CServerEntry
 {
-	NETADDR address;
-	int64 expire;
-} servers[MAX_SERVERS];
-static int num_servers = 0;
+	NETADDR m_Address;
+	int64 m_Expire;
+};
+
+static CServerEntry m_aServers[MAX_SERVERS];
+static int m_NumServers = 0;
 
-static struct PACKET_DATA
+struct CPacketData
 {
-	int size;
+	int m_Size;
 	struct {
-		unsigned char header[sizeof(SERVERBROWSE_LIST)];
-		NETADDR_IPv4 servers[MAX_SERVERS_PER_PACKET];
-	} data;
-} packets[MAX_PACKETS];
-static int num_packets = 0;
+		unsigned char m_aHeader[sizeof(SERVERBROWSE_LIST)];
+		NETADDR_IPv4 m_aServers[MAX_SERVERS_PER_PACKET];
+	} m_Data;
+};
 
-static struct COUNT_PACKET_DATA
+CPacketData m_aPackets[MAX_PACKETS];
+static int m_NumPackets = 0;
+
+struct CCountPacketData
 {
-	unsigned char header[sizeof(SERVERBROWSE_COUNT)];
-	unsigned char high;
-	unsigned char low;
-} count_data;
+	unsigned char m_Header[sizeof(SERVERBROWSE_COUNT)];
+	unsigned char m_High;
+	unsigned char m_Low;
+};
+
+static CCountPacketData m_CountData;
 
 //static int64 server_expire[MAX_SERVERS];
 
-static net_client net_checker; // NAT/FW checker
-static net_client net_op; // main
+static CNetClient m_NetChecker; // NAT/FW checker
+static CNetClient m_NetOp; // main
 
-void build_packets()
+void BuildPackets()
 {
-	SERVER_ENTRY *current = &servers[0];
-	int servers_left = num_servers;
-	int i;
-	num_packets = 0;
-	while(servers_left && num_packets < MAX_PACKETS)
+	CServerEntry *pCurrent = &m_aServers[0];
+	int ServersLeft = m_NumServers;
+	m_NumPackets = 0;
+	while(ServersLeft && m_NumPackets < MAX_PACKETS)
 	{
-		int chunk = servers_left;
-		if(chunk > MAX_SERVERS_PER_PACKET)
-			chunk = MAX_SERVERS_PER_PACKET;
-		servers_left -= chunk;
+		int Chunk = ServersLeft;
+		if(Chunk > MAX_SERVERS_PER_PACKET)
+			Chunk = MAX_SERVERS_PER_PACKET;
+		ServersLeft -= Chunk;
 		
 		// copy header	
-		mem_copy(packets[num_packets].data.header, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST));
+		mem_copy(m_aPackets[m_NumPackets].m_Data.m_aHeader, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST));
 		
 		// copy server addresses
-		for(i = 0; i < chunk; i++)
+		for(int i = 0; i < Chunk; i++)
 		{
 			// TODO: ipv6 support
-			packets[num_packets].data.servers[i].ip[0] = current->address.ip[0];
-			packets[num_packets].data.servers[i].ip[1] = current->address.ip[1];
-			packets[num_packets].data.servers[i].ip[2] = current->address.ip[2];
-			packets[num_packets].data.servers[i].ip[3] = current->address.ip[3];
-			packets[num_packets].data.servers[i].port = current->address.port;
-			current++;
+			m_aPackets[m_NumPackets].m_Data.m_aServers[i].m_aIp[0] = pCurrent->m_Address.ip[0];
+			m_aPackets[m_NumPackets].m_Data.m_aServers[i].m_aIp[1] = pCurrent->m_Address.ip[1];
+			m_aPackets[m_NumPackets].m_Data.m_aServers[i].m_aIp[2] = pCurrent->m_Address.ip[2];
+			m_aPackets[m_NumPackets].m_Data.m_aServers[i].m_aIp[3] = pCurrent->m_Address.ip[3];
+			m_aPackets[m_NumPackets].m_Data.m_aServers[i].m_Port = pCurrent->m_Address.port;
+			pCurrent++;
 		}
 		
-		packets[num_packets].size = sizeof(SERVERBROWSE_LIST) + sizeof(NETADDR_IPv4)*chunk;
+		m_aPackets[m_NumPackets].m_Size = sizeof(SERVERBROWSE_LIST) + sizeof(NETADDR_IPv4)*Chunk;
 		
-		num_packets++;
+		m_NumPackets++;
 	}
 }
 
-void send_ok(NETADDR *addr)
+void SendOk(NETADDR *pAddr)
 {
-	NETCHUNK p;
-	p.client_id = -1;
-	p.address = *addr;
-	p.flags = NETSENDFLAG_CONNLESS;
-	p.data_size = sizeof(SERVERBROWSE_FWOK);
-	p.data = SERVERBROWSE_FWOK;
+	CNetChunk p;
+	p.m_ClientID = -1;
+	p.m_Address = *pAddr;
+	p.m_Flags = NETSENDFLAG_CONNLESS;
+	p.m_DataSize = sizeof(SERVERBROWSE_FWOK);
+	p.m_pData = SERVERBROWSE_FWOK;
 	
 	// send on both to be sure
-	net_checker.send(&p);
-	net_op.send(&p);
+	m_NetChecker.Send(&p);
+	m_NetOp.Send(&p);
 }
 
-void send_error(NETADDR *addr)
+void SendError(NETADDR *pAddr)
 {
-	NETCHUNK p;
-	p.client_id = -1;
-	p.address = *addr;
-	p.flags = NETSENDFLAG_CONNLESS;
-	p.data_size = sizeof(SERVERBROWSE_FWERROR);
-	p.data = SERVERBROWSE_FWERROR;
-	net_op.send(&p);
+	CNetChunk p;
+	p.m_ClientID = -1;
+	p.m_Address = *pAddr;
+	p.m_Flags = NETSENDFLAG_CONNLESS;
+	p.m_DataSize = sizeof(SERVERBROWSE_FWERROR);
+	p.m_pData = SERVERBROWSE_FWERROR;
+	m_NetOp.Send(&p);
 }
 
-void send_check(NETADDR *addr)
+void SendCheck(NETADDR *pAddr)
 {
-	NETCHUNK p;
-	p.client_id = -1;
-	p.address = *addr;
-	p.flags = NETSENDFLAG_CONNLESS;
-	p.data_size = sizeof(SERVERBROWSE_FWCHECK);
-	p.data = SERVERBROWSE_FWCHECK;
-	net_checker.send(&p);
+	CNetChunk p;
+	p.m_ClientID = -1;
+	p.m_Address = *pAddr;
+	p.m_Flags = NETSENDFLAG_CONNLESS;
+	p.m_DataSize = sizeof(SERVERBROWSE_FWCHECK);
+	p.m_pData = SERVERBROWSE_FWCHECK;
+	m_NetChecker.Send(&p);
 }
 
-void add_checkserver(NETADDR *info, NETADDR *alt)
+void AddCheckserver(NETADDR *pInfo, NETADDR *pAlt)
 {
 	// add server
-	if(num_checkservers == MAX_SERVERS)
+	if(m_NumCheckServers == MAX_SERVERS)
 	{
 		dbg_msg("mastersrv", "error: mastersrv is full");
 		return;
 	}
 	
 	dbg_msg("mastersrv", "checking: %d.%d.%d.%d:%d (%d.%d.%d.%d:%d)",
-		info->ip[0], info->ip[1], info->ip[2], info->ip[3], info->port,
-		alt->ip[0], alt->ip[1], alt->ip[2], alt->ip[3], alt->port);
-	check_servers[num_checkservers].address = *info;
-	check_servers[num_checkservers].alt_address = *alt;
-	check_servers[num_checkservers].try_count = 0;
-	check_servers[num_checkservers].try_time = 0;
-	num_checkservers++;
+		pInfo->ip[0], pInfo->ip[1], pInfo->ip[2], pInfo->ip[3], pInfo->port,
+		pAlt->ip[0], pAlt->ip[1], pAlt->ip[2], pAlt->ip[3], pAlt->port);
+	m_aCheckServers[m_NumCheckServers].m_Address = *pInfo;
+	m_aCheckServers[m_NumCheckServers].m_AltAddress = *pAlt;
+	m_aCheckServers[m_NumCheckServers].m_TryCount = 0;
+	m_aCheckServers[m_NumCheckServers].m_TryTime = 0;
+	m_NumCheckServers++;
 }
 
-void add_server(NETADDR *info)
+void AddServer(NETADDR *pInfo)
 {
 	// see if server already exists in list
 	int i;
-	for(i = 0; i < num_servers; i++)
+	for(i = 0; i < m_NumServers; i++)
 	{
-		if(net_addr_comp(&servers[i].address, info) == 0)
+		if(net_addr_comp(&m_aServers[i].m_Address, pInfo) == 0)
 		{
 			dbg_msg("mastersrv", "updated: %d.%d.%d.%d:%d",
-				info->ip[0], info->ip[1], info->ip[2], info->ip[3], info->port);
-			servers[i].expire = time_get()+time_freq()*EXPIRE_TIME;
+				pInfo->ip[0], pInfo->ip[1], pInfo->ip[2], pInfo->ip[3], pInfo->port);
+			m_aServers[i].m_Expire = time_get()+time_freq()*EXPIRE_TIME;
 			return;
 		}
 	}
 	
 	// add server
-	if(num_servers == MAX_SERVERS)
+	if(m_NumServers == MAX_SERVERS)
 	{
 		dbg_msg("mastersrv", "error: mastersrv is full");
 		return;
 	}
 	
 	dbg_msg("mastersrv", "added: %d.%d.%d.%d:%d",
-		info->ip[0], info->ip[1], info->ip[2], info->ip[3], info->port);
-	servers[num_servers].address = *info;
-	servers[num_servers].expire = time_get()+time_freq()*EXPIRE_TIME;
-	num_servers++;
+		pInfo->ip[0], pInfo->ip[1], pInfo->ip[2], pInfo->ip[3], pInfo->port);
+	m_aServers[m_NumServers].m_Address = *pInfo;
+	m_aServers[m_NumServers].m_Expire = time_get()+time_freq()*EXPIRE_TIME;
+	m_NumServers++;
 }
 
-void update_servers()
+void UpdateServers()
 {
-	int64 now = time_get();
-	int64 freq = time_freq();
-	for(int i = 0; i < num_checkservers; i++)
+	int64 Now = time_get();
+	int64 Freq = time_freq();
+	for(int i = 0; i < m_NumCheckServers; i++)
 	{
-		if(now > check_servers[i].try_time+freq)
+		if(Now > m_aCheckServers[i].m_TryTime+Freq)
 		{
-			if(check_servers[i].try_count == 10)
+			if(m_aCheckServers[i].m_TryCount == 10)
 			{
 				dbg_msg("mastersrv", "check failed: %d.%d.%d.%d:%d",
-					check_servers[i].address.ip[0], check_servers[i].address.ip[1],
-					check_servers[i].address.ip[2], check_servers[i].address.ip[3],check_servers[i].address.port,
-					check_servers[i].alt_address.ip[0], check_servers[i].alt_address.ip[1],
-					check_servers[i].alt_address.ip[2], check_servers[i].alt_address.ip[3],check_servers[i].alt_address.port);
+					m_aCheckServers[i].m_Address.ip[0], m_aCheckServers[i].m_Address.ip[1],
+					m_aCheckServers[i].m_Address.ip[2], m_aCheckServers[i].m_Address.ip[3],m_aCheckServers[i].m_Address.port,
+					m_aCheckServers[i].m_AltAddress.ip[0], m_aCheckServers[i].m_AltAddress.ip[1],
+					m_aCheckServers[i].m_AltAddress.ip[2], m_aCheckServers[i].m_AltAddress.ip[3],m_aCheckServers[i].m_AltAddress.port);
 					
 				// FAIL!!
-				send_error(&check_servers[i].address);
-				check_servers[i] = check_servers[num_checkservers-1];
-				num_checkservers--;
+				SendError(&m_aCheckServers[i].m_Address);
+				m_aCheckServers[i] = m_aCheckServers[m_NumCheckServers-1];
+				m_NumCheckServers--;
 				i--;
 			}
 			else
 			{
-				check_servers[i].try_count++;
-				check_servers[i].try_time = now;
-				if(check_servers[i].try_count&1)
-					send_check(&check_servers[i].address);
+				m_aCheckServers[i].m_TryCount++;
+				m_aCheckServers[i].m_TryTime = Now;
+				if(m_aCheckServers[i].m_TryCount&1)
+					SendCheck(&m_aCheckServers[i].m_Address);
 				else
-					send_check(&check_servers[i].alt_address);
+					SendCheck(&m_aCheckServers[i].m_AltAddress);
 			}
 		}
 	}
 }
 
-void purge_servers()
+void PurgeServers()
 {
-	int64 now = time_get();
+	int64 Now = time_get();
 	int i = 0;
-	while(i < num_servers)
+	while(i < m_NumServers)
 	{
-		if(servers[i].expire < now)
+		if(m_aServers[i].m_Expire < Now)
 		{
 			// remove server
 			dbg_msg("mastersrv", "expired: %d.%d.%d.%d:%d",
-				servers[i].address.ip[0], servers[i].address.ip[1],
-				servers[i].address.ip[2], servers[i].address.ip[3], servers[i].address.port);
-			servers[i] = servers[num_servers-1];
-			num_servers--;
+				m_aServers[i].m_Address.ip[0], m_aServers[i].m_Address.ip[1],
+				m_aServers[i].m_Address.ip[2], m_aServers[i].m_Address.ip[3], m_aServers[i].m_Address.port);
+			m_aServers[i] = m_aServers[m_NumServers-1];
+			m_NumServers--;
 		}
 		else
 			i++;
 	}
 }
 
-int main(int argc, char **argv)
+int main(int argc, char **argv) // ignore_convention
 {
-	int64 last_build = 0;
-	NETADDR bindaddr;
+	int64 LastBuild = 0;
+	NETADDR BindAddr;
 
 	dbg_logger_stdout();
 	net_init();
 
-	mem_zero(&bindaddr, sizeof(bindaddr));
-	bindaddr.port = MASTERSERVER_PORT;
-	
-	
-	net_op.open(bindaddr, 0);
+	mem_zero(&BindAddr, sizeof(BindAddr));
+	BindAddr.port = MASTERSERVER_PORT;
+		
+	m_NetOp.Open(BindAddr, 0);
 
-	bindaddr.port = MASTERSERVER_PORT+1;
-	net_checker.open(bindaddr, 0);
+	BindAddr.port = MASTERSERVER_PORT+1;
+	m_NetChecker.Open(BindAddr, 0);
 	// TODO: check socket for errors
 	
 	//mem_copy(data.header, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST));
-	mem_copy(count_data.header, SERVERBROWSE_COUNT, sizeof(SERVERBROWSE_COUNT));
+	mem_copy(m_CountData.m_Header, SERVERBROWSE_COUNT, sizeof(SERVERBROWSE_COUNT));
 	
 	dbg_msg("mastersrv", "started");
 	
 	while(1)
 	{
-		net_op.update();
-		net_checker.update();
+		m_NetOp.Update();
+		m_NetChecker.Update();
 		
-		// process packets
-		NETCHUNK packet;
-		while(net_op.recv(&packet))
+		// process m_aPackets
+		CNetChunk Packet;
+		while(m_NetOp.Recv(&Packet))
 		{
-			if(packet.data_size == sizeof(SERVERBROWSE_HEARTBEAT)+2 &&
-				memcmp(packet.data, SERVERBROWSE_HEARTBEAT, sizeof(SERVERBROWSE_HEARTBEAT)) == 0)
+			if(Packet.m_DataSize == sizeof(SERVERBROWSE_HEARTBEAT)+2 &&
+				mem_comp(Packet.m_pData, SERVERBROWSE_HEARTBEAT, sizeof(SERVERBROWSE_HEARTBEAT)) == 0)
 			{
-				NETADDR alt;
-				unsigned char *d = (unsigned char *)packet.data;
-				alt = packet.address;
-				alt.port =
+				NETADDR Alt;
+				unsigned char *d = (unsigned char *)Packet.m_pData;
+				Alt = Packet.m_Address;
+				Alt.port =
 					(d[sizeof(SERVERBROWSE_HEARTBEAT)]<<8) |
 					d[sizeof(SERVERBROWSE_HEARTBEAT)+1];
 				
 				// add it
-				add_checkserver(&packet.address, &alt);
+				AddCheckserver(&Packet.m_Address, &Alt);
 			}
-			else if(packet.data_size == sizeof(SERVERBROWSE_GETCOUNT) &&
-				memcmp(packet.data, SERVERBROWSE_GETCOUNT, sizeof(SERVERBROWSE_GETCOUNT)) == 0)
+			else if(Packet.m_DataSize == sizeof(SERVERBROWSE_GETCOUNT) &&
+				mem_comp(Packet.m_pData, SERVERBROWSE_GETCOUNT, sizeof(SERVERBROWSE_GETCOUNT)) == 0)
 			{
-				dbg_msg("mastersrv", "count requested, responding with %d", num_servers);
+				dbg_msg("mastersrv", "count requested, responding with %d", m_NumServers);
 				
-				NETCHUNK p;
-				p.client_id = -1;
-				p.address = packet.address;
-				p.flags = NETSENDFLAG_CONNLESS;
-				p.data_size = sizeof(count_data);
-				p.data = &count_data;
-				count_data.high = (num_servers>>8)&0xff;
-				count_data.low = num_servers&0xff;
-				net_op.send(&p);
+				CNetChunk p;
+				p.m_ClientID = -1;
+				p.m_Address = Packet.m_Address;
+				p.m_Flags = NETSENDFLAG_CONNLESS;
+				p.m_DataSize = sizeof(m_CountData);
+				p.m_pData = &m_CountData;
+				m_CountData.m_High = (m_NumServers>>8)&0xff;
+				m_CountData.m_Low = m_NumServers&0xff;
+				m_NetOp.Send(&p);
 			}
-			else if(packet.data_size == sizeof(SERVERBROWSE_GETLIST) &&
-				memcmp(packet.data, SERVERBROWSE_GETLIST, sizeof(SERVERBROWSE_GETLIST)) == 0)
+			else if(Packet.m_DataSize == sizeof(SERVERBROWSE_GETLIST) &&
+				mem_comp(Packet.m_pData, SERVERBROWSE_GETLIST, sizeof(SERVERBROWSE_GETLIST)) == 0)
 			{
 				// someone requested the list
-				dbg_msg("mastersrv", "requested, responding with %d servers", num_servers);
-				NETCHUNK p;
-				p.client_id = -1;
-				p.address = packet.address;
-				p.flags = NETSENDFLAG_CONNLESS;
+				dbg_msg("mastersrv", "requested, responding with %d m_aServers", m_NumServers);
+				CNetChunk p;
+				p.m_ClientID = -1;
+				p.m_Address = Packet.m_Address;
+				p.m_Flags = NETSENDFLAG_CONNLESS;
 				
-				for(int i = 0; i < num_packets; i++)
+				for(int i = 0; i < m_NumPackets; i++)
 				{
-					p.data_size = packets[i].size;
-					p.data = &packets[i].data;
-					net_op.send(&p);
+					p.m_DataSize = m_aPackets[i].m_Size;
+					p.m_pData = &m_aPackets[i].m_Data;
+					m_NetOp.Send(&p);
 				}
 			}
 		}
 
-		// process packets
-		while(net_checker.recv(&packet))
+		// process m_aPackets
+		while(m_NetChecker.Recv(&Packet))
 		{
-			if(packet.data_size == sizeof(SERVERBROWSE_FWRESPONSE) &&
-				memcmp(packet.data, SERVERBROWSE_FWRESPONSE, sizeof(SERVERBROWSE_FWRESPONSE)) == 0)
+			if(Packet.m_DataSize == sizeof(SERVERBROWSE_FWRESPONSE) &&
+				mem_comp(Packet.m_pData, SERVERBROWSE_FWRESPONSE, sizeof(SERVERBROWSE_FWRESPONSE)) == 0)
 			{
 				// remove it from checking
-				for(int i = 0; i < num_checkservers; i++)
+				for(int i = 0; i < m_NumCheckServers; i++)
 				{
-					if(net_addr_comp(&check_servers[i].address, &packet.address) == 0 ||
-						net_addr_comp(&check_servers[i].alt_address, &packet.address) == 0)
+					if(net_addr_comp(&m_aCheckServers[i].m_Address, &Packet.m_Address) == 0 ||
+						net_addr_comp(&m_aCheckServers[i].m_AltAddress, &Packet.m_Address) == 0)
 					{
-						num_checkservers--;
-						check_servers[i] = check_servers[num_checkservers];
+						m_NumCheckServers--;
+						m_aCheckServers[i] = m_aCheckServers[m_NumCheckServers];
 						break;
 					}
 				}
 				
-				add_server(&packet.address);
-				send_ok(&packet.address);
+				AddServer(&Packet.m_Address);
+				SendOk(&Packet.m_Address);
 			}
 		}
 		
-		if(time_get()-last_build > time_freq()*5)
+		if(time_get()-LastBuild > time_freq()*5)
 		{
-			last_build = time_get();
+			LastBuild = time_get();
 			
-			purge_servers();
-			update_servers();
-			build_packets();
+			PurgeServers();
+			UpdateServers();
+			BuildPackets();
 		}
 		
 		// be nice to the CPU
diff --git a/src/mastersrv/mastersrv.h b/src/mastersrv/mastersrv.h
index cfac2e71..50fea646 100644
--- a/src/mastersrv/mastersrv.h
+++ b/src/mastersrv/mastersrv.h
@@ -1,10 +1,11 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
+#ifndef MASTERSRV_MASTERSRV_H
+#define MASTERSRV_MASTERSRV_H
 static const int MASTERSERVER_PORT = 8300;
 
 typedef struct MASTERSRV_ADDR
 {
-	unsigned char ip[4];
-	unsigned char port[2];
+	unsigned char m_aIp[4];
+	unsigned char m_aPort[2];
 } MASTERSRV_ADDR;
 
 static const unsigned char SERVERBROWSE_HEARTBEAT[] = {255, 255, 255, 255, 'b', 'e', 'a', 't'};
@@ -25,3 +26,4 @@ static const unsigned char SERVERBROWSE_FWCHECK[] = {255, 255, 255, 255, 'f', 'w
 static const unsigned char SERVERBROWSE_FWRESPONSE[] = {255, 255, 255, 255, 'f', 'w', '!', '!'};
 static const unsigned char SERVERBROWSE_FWOK[] = {255, 255, 255, 255, 'f', 'w', 'o', 'k'};
 static const unsigned char SERVERBROWSE_FWERROR[] = {255, 255, 255, 255, 'f', 'w', 'e', 'r'};
+#endif
diff --git a/src/osxlaunch/client.h b/src/osxlaunch/client.h
index 4683df57..be59d0b9 100644
--- a/src/osxlaunch/client.h
+++ b/src/osxlaunch/client.h
@@ -1,3 +1,5 @@
+#ifndef OSXLAUNCH_CLIENT_H
+#define OSXLAUNCH_CLIENT_H
 /*   SDLMain.m - main entry point for our Cocoa-ized SDL app
        Initial Version: Darrell Walisser <dwaliss1@purdue.edu>
        Non-NIB-Code & other changes: Max Horn <max@quendi.de>
@@ -9,3 +11,4 @@
 
 @interface SDLMain : NSObject
 @end
+#endif
diff --git a/src/tools/crapnet.cpp b/src/tools/crapnet.cpp
index 888f3b2e..e05cc237 100644
--- a/src/tools/crapnet.cpp
+++ b/src/tools/crapnet.cpp
@@ -1,167 +1,167 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
 #include <base/system.h>
 
 #include <cstdlib>
 
-struct PACKET
+struct CPacket
 {
-	PACKET *prev;
-	PACKET *next;
+	CPacket *m_pPrev;
+	CPacket *m_pNext;
 	
-	NETADDR send_to;
-	int64 timestamp;
-	int id;
-	int data_size;
-	char data[1];
+	NETADDR m_SendTo;
+	int64 m_Timestamp;
+	int m_Id;
+	int m_DataSize;
+	char m_aData[1];
 };
 
-static PACKET *first = (PACKET *)0;
-static PACKET *last = (PACKET *)0;
-static int current_latency = 0;
+static CPacket *m_pFirst = (CPacket *)0;
+static CPacket *m_pLast = (CPacket *)0;
+static int m_CurrentLatency = 0;
 
-struct PINGCONFIG
+struct CPingConfig
 {
-	int base;
-	int flux;
-	int spike;
-	int loss;
-	int delay;
-	int delay_freq;
+	int m_Base;
+	int m_Flux;
+	int m_Spike;
+	int m_Loss;
+	int m_Delay;
+	int m_DelayFreq;
 };
 
-static PINGCONFIG config_pings[] = {
+static CPingConfig m_aConfigPings[] = {
 //		base	flux	spike	loss	delay	delayfreq
 		{0,		0,		0,		0,		0,		0},
 		{40,	20,		100,		0,		0,		0},
 		{140,	40,		200,		0,		0,		0},
 };
 
-static int config_numpingconfs = sizeof(config_pings)/sizeof(PINGCONFIG);
-static int config_interval = 10; /* seconds between different pingconfigs */
-static int config_log = 0;
-static int config_reorder = 0;
+static int m_ConfigNumpingconfs = sizeof(m_aConfigPings)/sizeof(CPingConfig);
+static int m_ConfigInterval = 10; // seconds between different pingconfigs
+static int m_ConfigLog = 0;
+static int m_ConfigReorder = 0;
 
-int run(int port, NETADDR dest)
+void Run(int Port, NETADDR Dest)
 {
-	NETADDR src = {NETTYPE_IPV4, {0,0,0,0},port};
-	NETSOCKET socket = net_udp_create(src);
+	NETADDR Src = {NETTYPE_IPV4, {0,0,0,0}, Port};
+	NETSOCKET Socket = net_udp_create(Src);
 	
-	char buffer[1024*2];
-	int id = 0;
-	int delaycounter = 0;
+	char aBuffer[1024*2];
+	int Id = 0;
+	int Delaycounter = 0;
 	
 	while(1)
 	{
-		static int lastcfg = 0;
-		int n = ((time_get()/time_freq())/config_interval) % config_numpingconfs;
-		PINGCONFIG ping = config_pings[n];
+		static int Lastcfg = 0;
+		int n = ((time_get()/time_freq())/m_ConfigInterval) % m_ConfigNumpingconfs;
+		CPingConfig Ping = m_aConfigPings[n];
 		
-		if(n != lastcfg)
+		if(n != Lastcfg)
 			dbg_msg("crapnet", "cfg = %d", n);
-		lastcfg = n;
+		Lastcfg = n;
 		
 		// handle incomming packets
 		while(1)
 		{
 			// fetch data
-			int data_trash = 0;
-			NETADDR from;
-			int bytes = net_udp_recv(socket, &from, buffer, 1024*2);
-			if(bytes <= 0)
+			int DataTrash = 0;
+			NETADDR From;
+			int Bytes = net_udp_recv(Socket, &From, aBuffer, 1024*2);
+			if(Bytes <= 0)
 				break;
 				
-			if((rand()%100) < ping.loss) // drop the packet
+			if((rand()%100) < Ping.m_Loss) // drop the packet
 			{
-				if(config_log)
+				if(m_ConfigLog)
 					dbg_msg("crapnet", "dropped packet");
 				continue;
 			}
 
 			// create new packet				
-			PACKET *p = (PACKET *)mem_alloc(sizeof(PACKET)+bytes, 1);
+			CPacket *p = (CPacket *)mem_alloc(sizeof(CPacket)+Bytes, 1);
 
-			if(net_addr_comp(&from, &dest) == 0)
-				p->send_to = src; // from the server
+			if(net_addr_comp(&From, &Dest) == 0)
+				p->m_SendTo = Src; // from the server
 			else
 			{
-				src = from; // from the client
-				p->send_to = dest;
+				Src = From; // from the client
+				p->m_SendTo = Dest;
 			}
 
 			// queue packet
-			p->prev = last;
-			p->next = 0;
-			if(last)
-				last->next = p;
+			p->m_pPrev = m_pLast;
+			p->m_pNext = 0;
+			if(m_pLast)
+				m_pLast->m_pNext = p;
 			else
 			{
-				first = p;
-				last = p;
+				m_pFirst = p;
+				m_pLast = p;
 			}
-			last = p;
+			m_pLast = p;
 
 			// set data in packet
-			p->timestamp = time_get();
-			p->data_size = bytes;
-			p->id = id++;
-			mem_copy(p->data, buffer, bytes);
+			p->m_Timestamp = time_get();
+			p->m_DataSize = Bytes;
+			p->m_Id = Id++;
+			mem_copy(p->m_aData, aBuffer, Bytes);
 			
-			if(id > 20 && bytes > 6 && data_trash)
+			if(Id > 20 && Bytes > 6 && DataTrash)
 			{
-				p->data[6+(rand()%(bytes-6))] = rand()&255; // modify a byte
+				p->m_aData[6+(rand()%(Bytes-6))] = rand()&255; // modify a byte
 				if((rand()%10) == 0)
 				{
-					p->data_size -= rand()%32;
-					if(p->data_size < 6)
-						p->data_size = 6;
+					p->m_DataSize -= rand()%32;
+					if(p->m_DataSize < 6)
+						p->m_DataSize = 6;
 				}
 			}
 			
-			if(delaycounter <= 0)
+			if(Delaycounter <= 0)
 			{
-				if(ping.delay)
-					p->timestamp += (time_freq()*1000)/ping.delay;
-				delaycounter = ping.delay_freq;
+				if(Ping.m_Delay)
+					p->m_Timestamp += (time_freq()*1000)/Ping.m_Delay;
+				Delaycounter = Ping.m_DelayFreq;
 			}
-			delaycounter--;
+			Delaycounter--;
 	
-			if(config_log)
-				dbg_msg("crapnet", "<< %08d %d.%d.%d.%d:%5d (%d)", p->id, from.ip[0], from.ip[1], from.ip[2], from.ip[3], from.port, p->data_size);
+			if(m_ConfigLog)
+				dbg_msg("crapnet", "<< %08d %d.%d.%d.%d:%5d (%d)", p->m_Id, From.ip[0], From.ip[1], From.ip[2], From.ip[3], From.port, p->m_DataSize);
 		}
 		
 		//
 		/*while(1)
 		{*/
-		PACKET *p = 0;
-		PACKET *next = first;
+		CPacket *p = 0;
+		CPacket *pNext = m_pFirst;
 		while(1)
 		{
-			p = next;
+			p = pNext;
 			if(!p)
 				break;
-			next = p->next;
+			pNext = p->m_pNext;
 				
-			if((time_get()-p->timestamp) > current_latency)
+			if((time_get()-p->m_Timestamp) > m_CurrentLatency)
 			{
-				char flags[] = "  ";
+				char aFlags[] = "  ";
 
-				if(config_reorder && (rand()%2) == 0 && p->next)
+				if(m_ConfigReorder && (rand()%2) == 0 && p->m_pNext)
 				{
-					flags[0] = 'R';
-					p = first->next;
+					aFlags[0] = 'R';
+					p = m_pFirst->m_pNext;
 				}
 				
-				if(p->next)
-					p->next->prev = p->prev;
+				if(p->m_pNext)
+					p->m_pNext->m_pPrev = p->m_pPrev;
 				else
-					last = p->prev;
+					m_pLast = p->m_pPrev;
 					
-				if(p->prev)
-					p->prev->next = p->next;
+				if(p->m_pPrev)
+					p->m_pPrev->m_pNext = p->m_pNext;
 				else
-					first = p->next;
+					m_pFirst = p->m_pNext;
 					
-				/*PACKET *cur = first;
+				/*CPacket *cur = first;
 				while(cur)
 				{
 					dbg_assert(cur != p, "p still in list");
@@ -170,27 +170,27 @@ int run(int port, NETADDR dest)
 					
 				// send and remove packet
 				//if((rand()%20) != 0) // heavy packetloss
-				net_udp_send(socket, &p->send_to, p->data, p->data_size);
+				net_udp_send(Socket, &p->m_SendTo, p->m_aData, p->m_DataSize);
 				
 				// update lag
-				double flux = rand()/(double)RAND_MAX;
-				int ms_spike = ping.spike;
-				int ms_flux = ping.flux;
-				int ms_ping = ping.base;
-				current_latency = ((time_freq()*ms_ping)/1000) + (int64)(((time_freq()*ms_flux)/1000)*flux); // 50ms
+				double Flux = rand()/(double)RAND_MAX;
+				int MsSpike = Ping.m_Spike;
+				int MsFlux = Ping.m_Flux;
+				int MsPing = Ping.m_Base;
+				m_CurrentLatency = ((time_freq()*MsPing)/1000) + (int64)(((time_freq()*MsFlux)/1000)*Flux); // 50ms
 				
-				if(ms_spike && (p->id%100) == 0)
+				if(MsSpike && (p->m_Id%100) == 0)
 				{
-					current_latency += (time_freq()*ms_spike)/1000;
-					flags[1] = 'S';
+					m_CurrentLatency += (time_freq()*MsSpike)/1000;
+					aFlags[1] = 'S';
 				}
 
-				if(config_log)
+				if(m_ConfigLog)
 				{
-					dbg_msg("crapnet", ">> %08d %d.%d.%d.%d:%5d (%d) %s", p->id,
-						p->send_to.ip[0], p->send_to.ip[1],
-						p->send_to.ip[2], p->send_to.ip[3],
-						p->send_to.port, p->data_size, flags);
+					dbg_msg("crapnet", ">> %08d %d.%d.%d.%d:%5d (%d) %s", p->m_Id,
+						p->m_SendTo.ip[0], p->m_SendTo.ip[1],
+						p->m_SendTo.ip[2], p->m_SendTo.ip[3],
+						p->m_SendTo.port, p->m_DataSize, aFlags);
 				}
 				
 
@@ -202,10 +202,10 @@ int run(int port, NETADDR dest)
 	}
 }
 
-int main(int argc, char **argv)
+int main(int argc, char **argv) // ignore_convention
 {
-	NETADDR a = {NETTYPE_IPV4, {127,0,0,1},8303};
+	NETADDR Addr = {NETTYPE_IPV4, {127,0,0,1},8303};
 	dbg_logger_stdout();
-	run(8302, a);
+	Run(8302, Addr);
 	return 0;
 }
diff --git a/src/tools/dilate.c b/src/tools/dilate.c
index 57dce705..a8b28fc4 100644
--- a/src/tools/dilate.c
+++ b/src/tools/dilate.c
@@ -1,6 +1,6 @@
 /* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
 
-#include "../engine/external/pnglite/pnglite.c"
+#include "./engine/external/pnglite/pnglite.c"
 
 typedef struct pixel_t
 {
diff --git a/src/tools/fake_server.c b/src/tools/fake_server.c
deleted file mode 100644
index 04eeac4d..00000000
--- a/src/tools/fake_server.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <base/system.h>
-#include <engine/e_config.h>
-#include <engine/e_network.h>
-#include <mastersrv/mastersrv.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-/*
- 32 version
- 64 servername
- 32 mapname
-  2 gametype
-  2 flags
-  4 progression
-  3 num players
-  3 max players
-  {
-  	48 name
-     6 score
-  } * players
-
-         111111111122222222223333333333444444444
-123456789012345678901234567890123456789012345678
-0.3 2d82e361de24cb25
-my own private little server
-magnus.auvinen@teeworlds.somehost-strage-host.com
-*/
-
-NETSERVER *net;
-
-int progression = 50;
-int game_type = 0;
-int flags = 0;
-
-const char *version = "0.3.0 2d82e361de24cb25";
-const char *map = "somemap";
-const char *server_name = "unnamed server";
-NETADDR master_servers[16] = {{0,{0},0}};
-int num_masters = 0;
-
-const char *player_names[16] = {0};
-int player_scores[16] = {0};
-int num_players = 0;
-int max_players = 0;
-
-
-
-static void send_heartbeats()
-{
-	static unsigned char data[sizeof(SERVERBROWSE_HEARTBEAT) + 2];
-	NETCHUNK packet;
-	int i;
-	
-	mem_copy(data, SERVERBROWSE_HEARTBEAT, sizeof(SERVERBROWSE_HEARTBEAT));
-	
-	packet.client_id = -1;
-	packet.flags = NETSENDFLAG_CONNLESS;
-	packet.data_size = sizeof(SERVERBROWSE_HEARTBEAT) + 2;
-	packet.data = &data;
-
-	/* supply the set port that the master can use if it has problems */	
-	data[sizeof(SERVERBROWSE_HEARTBEAT)] = 0;
-	data[sizeof(SERVERBROWSE_HEARTBEAT)+1] = 0;
-	
-	for(i = 0; i < num_masters; i++)
-	{
-		packet.address = master_servers[i];
-		netserver_send(net, &packet);
-	}
-}
-
-char infomsg[1024];
-int infomsg_size;
-
-static void writestr(const char *str)
-{
-	int l = strlen(str)+1;
-	memcpy(&infomsg[infomsg_size], str, l);
-	infomsg_size += l;
-}
-
-static void writeint(int i)
-{
-	char buf[64];
-	sprintf(buf, "%d", i);
-	writestr(buf);
-}
-
-static void build_infomessage()
-{
-	int i;
-	infomsg_size = sizeof(SERVERBROWSE_OLD_INFO);
-	memcpy(infomsg, SERVERBROWSE_OLD_INFO, infomsg_size);
-	
-	writestr(version);
-	writestr(server_name);
-	writestr(map);
-	writeint(game_type);
-	writeint(flags);
-	writeint(progression);
-	writeint(num_players);
-	writeint(max_players);
-	for(i = 0; i < num_players; i++)
-	{
-		writestr(player_names[i]);
-		writeint(player_scores[i]);
-	}
-}
-
-static void send_serverinfo(NETADDR *addr)
-{
-	NETCHUNK p;
-	p.client_id = -1;
-	p.address = *addr;
-	p.flags = NETSENDFLAG_CONNLESS;
-	p.data_size = infomsg_size;
-	p.data = infomsg;
-	netserver_send(net, &p);
-}
-
-static void send_fwcheckresponse(NETADDR *addr)
-{
-	NETCHUNK p;
-	p.client_id = -1;
-	p.address = *addr;
-	p.flags = NETSENDFLAG_CONNLESS;
-	p.data_size = sizeof(SERVERBROWSE_FWRESPONSE);
-	p.data = SERVERBROWSE_FWRESPONSE;
-	netserver_send(net, &p);
-}
-
-static int run()
-{
-	int64 next_heartbeat = 0;
-	NETADDR bindaddr = {NETTYPE_IPV4, {0},0};
-	net = netserver_open(bindaddr, 0, 0);
-	if(!net)
-		return -1;
-	
-	while(1)
-	{
-		NETCHUNK p;
-		netserver_update(net);
-		while(netserver_recv(net, &p))
-		{
-			if(p.client_id == -1)
-			{
-				if(p.data_size == sizeof(SERVERBROWSE_OLD_GETINFO) &&
-					memcmp(p.data, SERVERBROWSE_OLD_GETINFO, sizeof(SERVERBROWSE_OLD_GETINFO)) == 0)
-				{
-					send_serverinfo(&p.address);
-				}
-				else if(p.data_size == sizeof(SERVERBROWSE_FWCHECK) &&
-					memcmp(p.data, SERVERBROWSE_FWCHECK, sizeof(SERVERBROWSE_FWCHECK)) == 0)
-				{
-					send_fwcheckresponse(&p.address);
-				}
-			}
-		}
-		
-		/* send heartbeats if needed */
-		if(next_heartbeat < time_get())
-		{
-			next_heartbeat = time_get()+time_freq()*(15+(rand()%15));
-			send_heartbeats();
-		}
-		
-		thread_sleep(100);
-	}
-}
-
-int main(int argc, char **argv)
-{
-	net_init();
-	
-	while(argc)
-	{
-		if(strcmp(*argv, "-m") == 0)
-		{
-			argc--; argv++;
-			net_host_lookup(*argv, &master_servers[num_masters], NETTYPE_IPV4);
-			argc--; argv++;
-			master_servers[num_masters].port = atoi(*argv);
-			num_masters++;
-		}
-		else if(strcmp(*argv, "-p") == 0)
-		{
-			argc--; argv++;
-			player_names[num_players++] = *argv;
-			argc--; argv++;
-			player_scores[num_players] = atoi(*argv);
-		}
-		else if(strcmp(*argv, "-a") == 0)
-		{
-			argc--; argv++;
-			map = *argv;
-		}
-		else if(strcmp(*argv, "-x") == 0)
-		{
-			argc--; argv++;
-			max_players = atoi(*argv);
-		}
-		else if(strcmp(*argv, "-t") == 0)
-		{
-			argc--; argv++;
-			game_type = atoi(*argv);
-		}
-		else if(strcmp(*argv, "-g") == 0)
-		{
-			argc--; argv++;
-			progression = atoi(*argv);
-		}
-		else if(strcmp(*argv, "-f") == 0)
-		{
-			argc--; argv++;
-			flags = atoi(*argv);
-		}
-		else if(strcmp(*argv, "-n") == 0)
-		{
-			argc--; argv++;
-			server_name = *argv;
-		}
-		
-		argc--; argv++;
-	}
-	
-	build_infomessage();
-	return run();
-}
-
diff --git a/src/tools/fake_server.cpp b/src/tools/fake_server.cpp
new file mode 100644
index 00000000..b833c1b1
--- /dev/null
+++ b/src/tools/fake_server.cpp
@@ -0,0 +1,211 @@
+/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
+#include <stdlib.h> //rand
+#include <base/system.h>
+#include <engine/shared/config.h>
+#include <engine/shared/network.h>
+#include <mastersrv/mastersrv.h>
+
+CNetServer *pNet;
+
+int Progression = 50;
+int GameType = 0;
+int Flags = 0;
+
+const char *pVersion = "trunk";
+const char *pMap = "somemap";
+const char *pServerName = "unnamed server";
+
+NETADDR aMasterServers[16] = {{0,{0},0}};
+int NumMasters = 0;
+
+const char *PlayerNames[16] = {0};
+int PlayerScores[16] = {0};
+int NumPlayers = 0;
+int MaxPlayers = 0;
+
+char aInfoMsg[1024];
+int aInfoMsgSize;
+
+static void SendHeartBeats()
+{
+	static unsigned char aData[sizeof(SERVERBROWSE_HEARTBEAT) + 2];
+	CNetChunk Packet;
+	
+	mem_copy(aData, SERVERBROWSE_HEARTBEAT, sizeof(SERVERBROWSE_HEARTBEAT));
+	
+	Packet.m_ClientID = -1;
+	Packet.m_Flags = NETSENDFLAG_CONNLESS;
+	Packet.m_DataSize = sizeof(SERVERBROWSE_HEARTBEAT) + 2;
+	Packet.m_pData = &aData;
+
+	/* supply the set port that the master can use if it has problems */	
+	aData[sizeof(SERVERBROWSE_HEARTBEAT)] = 0;
+	aData[sizeof(SERVERBROWSE_HEARTBEAT)+1] = 0;
+	
+	for(int i = 0; i < NumMasters; i++)
+	{
+		Packet.m_Address = aMasterServers[i];
+		pNet->Send(&Packet);
+	}
+}
+
+static void WriteStr(const char *pStr)
+{
+	int l = str_length(pStr)+1;
+	mem_copy(&aInfoMsg[aInfoMsgSize], pStr, l);
+	aInfoMsgSize += l;
+}
+
+static void WriteInt(int i)
+{
+	char aBuf[64];
+	str_format(aBuf, sizeof(aBuf), "%d", i);
+	WriteStr(aBuf);
+}
+
+static void BuildInfoMsg()
+{
+	aInfoMsgSize = sizeof(SERVERBROWSE_OLD_INFO);
+	mem_copy(aInfoMsg, SERVERBROWSE_OLD_INFO, aInfoMsgSize);
+	
+	WriteStr(pVersion);
+	WriteStr(pServerName);
+	WriteStr(pMap);
+	WriteInt(GameType);
+	WriteInt(Flags);
+	WriteInt(Progression);
+	WriteInt(NumPlayers);
+	WriteInt(MaxPlayers);
+	
+	for(int i = 0; i < NumPlayers; i++)
+	{
+		WriteStr(PlayerNames[i]);
+		WriteInt(PlayerScores[i]);
+	}
+}
+
+static void SendServerInfo(NETADDR *pAddr)
+{
+	CNetChunk p;
+	p.m_ClientID = -1;
+	p.m_Address = *pAddr;
+	p.m_Flags = NETSENDFLAG_CONNLESS;
+	p.m_DataSize = aInfoMsgSize;
+	p.m_pData = aInfoMsg;
+	pNet->Send(&p);
+}
+
+static void SendFWCheckResponse(NETADDR *pAddr)
+{
+	CNetChunk p;
+	p.m_ClientID = -1;
+	p.m_Address = *pAddr;
+	p.m_Flags = NETSENDFLAG_CONNLESS;
+	p.m_DataSize = sizeof(SERVERBROWSE_FWRESPONSE);
+	p.m_pData = SERVERBROWSE_FWRESPONSE;
+	pNet->Send(&p);
+}
+
+static int Run()
+{
+	int64 NextHeartBeat = 0;
+	NETADDR BindAddr = {NETTYPE_IPV4, {0},0};
+	
+	if(!pNet->Open(BindAddr, 0, 0))
+		return 0;
+	
+	while(1)
+	{
+		CNetChunk p;
+		pNet->Update();
+		while(pNet->Recv(&p))
+		{
+			if(p.m_ClientID == -1)
+			{
+				if(p.m_DataSize == sizeof(SERVERBROWSE_OLD_GETINFO) &&
+					mem_comp(p.m_pData, SERVERBROWSE_OLD_GETINFO, sizeof(SERVERBROWSE_OLD_GETINFO)) == 0)
+				{
+					SendServerInfo(&p.m_Address);
+				}
+				else if(p.m_DataSize == sizeof(SERVERBROWSE_FWCHECK) &&
+					mem_comp(p.m_pData, SERVERBROWSE_FWCHECK, sizeof(SERVERBROWSE_FWCHECK)) == 0)
+				{
+					SendFWCheckResponse(&p.m_Address);
+				}
+			}
+		}
+		
+		/* send heartbeats if needed */
+		if(NextHeartBeat < time_get())
+		{
+			NextHeartBeat = time_get()+time_freq()*(15+(rand()%15));
+			SendHeartBeats();
+		}
+		
+		thread_sleep(100);
+	}
+}
+
+int main(int argc, char **argv)
+{
+	pNet = new CNetServer;
+	
+	while(argc)
+	{
+		// ?
+		/*if(str_comp(*argv, "-m") == 0)
+		{
+			argc--; argv++;
+			net_host_lookup(*argv, &aMasterServers[NumMasters], NETTYPE_IPV4);
+			argc--; argv++;
+			aMasterServers[NumMasters].port = str_toint(*argv);
+			NumMasters++;
+		}
+		else */if(str_comp(*argv, "-p") == 0)
+		{
+			argc--; argv++;
+			PlayerNames[NumPlayers++] = *argv;
+			argc--; argv++;
+			PlayerScores[NumPlayers] = str_toint(*argv);
+		}
+		else if(str_comp(*argv, "-a") == 0)
+		{
+			argc--; argv++;
+			pMap = *argv;
+		}
+		else if(str_comp(*argv, "-x") == 0)
+		{
+			argc--; argv++;
+			MaxPlayers = str_toint(*argv);
+		}
+		else if(str_comp(*argv, "-t") == 0)
+		{
+			argc--; argv++;
+			GameType = str_toint(*argv);
+		}
+		else if(str_comp(*argv, "-g") == 0)
+		{
+			argc--; argv++;
+			Progression = str_toint(*argv);
+		}
+		else if(str_comp(*argv, "-f") == 0)
+		{
+			argc--; argv++;
+			Flags = str_toint(*argv);
+		}
+		else if(str_comp(*argv, "-n") == 0)
+		{
+			argc--; argv++;
+			pServerName = *argv;
+		}
+		
+		argc--; argv++;
+	}
+	
+	BuildInfoMsg();
+	int RunReturn = Run();
+	
+	delete pNet;
+	return RunReturn;
+}
+
diff --git a/src/tools/map_resave.c b/src/tools/map_resave.c
deleted file mode 100644
index 37e00904..00000000
--- a/src/tools/map_resave.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-#include <engine/e_datafile.h>
-
-int main(int argc, char **argv)
-{
-	int i, id, type, size;
-	void *ptr;
-	DATAFILE *df;
-	DATAFILE_OUT *df_out;
-
-	if(argc != 3)
-		return -1;
-
-	df = datafile_load(argv[1]);
-	df_out = datafile_create(argv[2]);
-
-	/* add all items */
-	for(i = 0; i < datafile_num_items(df); i++)
-	{
-		ptr = datafile_get_item(df, i, &type, &id);
-		size = datafile_get_itemsize(df, i);
-		datafile_add_item(df_out, type, id, size, ptr);
-	}
-
-	/* add all data */
-	for(i = 0; i < datafile_num_data(df); i++)
-	{
-		ptr = datafile_get_data(df, i);
-		size = datafile_get_datasize(df, i);
-		datafile_add_data(df_out, size, ptr);
-	}
-
-	datafile_unload(df);
-	datafile_finish(df_out);
-	return 0;
-}
diff --git a/src/tools/map_resave.cpp b/src/tools/map_resave.cpp
new file mode 100644
index 00000000..a6c55c43
--- /dev/null
+++ b/src/tools/map_resave.cpp
@@ -0,0 +1,44 @@
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+#include <base/system.h>
+#include <engine/shared/datafile.h>
+#include <engine/storage.h>
+
+int main(int argc, const char **argv)
+{
+	IStorage *pStorage = CreateStorage("Teeworlds", argv[0]);
+	int Index, Id = 0, Type = 0, Size;
+	void *pPtr;
+	char aFileName[1024];
+	CDataFileReader DataFile;
+	CDataFileWriter df;
+
+	if(argc != 3)
+		return -1;
+
+	str_format(aFileName, sizeof(aFileName), "maps/%s", argv[2]);
+
+	if(!DataFile.Open(pStorage, argv[1]))
+		return -1;
+	if(!df.Open(pStorage, aFileName))
+		return -1;
+
+	// add all items
+	for(Index = 0; Index < DataFile.NumItems(); Index++)
+	{	
+		pPtr = DataFile.GetItem(Index, &Type, &Id);
+		Size = DataFile.GetItemSize(Index);
+		df.AddItem(Type, Id, Size, pPtr);
+	}
+
+	// add all data
+	for(Index = 0; Index < DataFile.NumData(); Index++)
+	{
+		pPtr = DataFile.GetData(Index);
+		Size = DataFile.GetDataSize(Index);
+		df.AddData(Size, pPtr);
+	}
+
+	DataFile.Close();
+	df.Finish();
+	return 0;
+}
diff --git a/src/tools/tileset_borderfix.c b/src/tools/tileset_borderfix.c
index 945f2832..90e512eb 100644
--- a/src/tools/tileset_borderfix.c
+++ b/src/tools/tileset_borderfix.c
@@ -1,6 +1,6 @@
 /* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
 
-#include "../engine/external/pnglite/pnglite.c"
+#include "./engine/external/pnglite/pnglite.c"
 
 typedef struct pixel_t
 {
diff --git a/src/versionsrv/versionsrv.cpp b/src/versionsrv/versionsrv.cpp
index ed96023f..8c0801e7 100644
--- a/src/versionsrv/versionsrv.cpp
+++ b/src/versionsrv/versionsrv.cpp
@@ -1,57 +1,54 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */

-#include <string.h>

+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
 #include <base/system.h>

 

-extern "C" {

-	#include <engine/e_network.h>

-}

+#include <engine/shared/network.h>

 

 #include "versionsrv.h"

 

-static net_client net_op; // main

+static CNetClient g_NetOp; // main

 

-void send_ver(NETADDR *addr)

+void SendVer(NETADDR *pAddr)

 {

-	NETCHUNK p;

-	unsigned char data[sizeof(VERSIONSRV_VERSION) + sizeof(VERSION_DATA)];

+	CNetChunk p;

+	unsigned char aData[sizeof(VERSIONSRV_VERSION) + sizeof(VERSION_DATA)];

 	

-	memcpy(data, VERSIONSRV_VERSION, sizeof(VERSIONSRV_VERSION));

-	memcpy(data + sizeof(VERSIONSRV_VERSION), VERSION_DATA, sizeof(VERSION_DATA));

+	mem_copy(aData, VERSIONSRV_VERSION, sizeof(VERSIONSRV_VERSION));

+	mem_copy(aData + sizeof(VERSIONSRV_VERSION), VERSION_DATA, sizeof(VERSION_DATA));

 	

-	p.client_id = -1;

-	p.address = *addr;

-	p.flags = NETSENDFLAG_CONNLESS;

-	p.data = data;

-	p.data_size = sizeof(data);

+	p.m_ClientID = -1;

+	p.m_Address = *pAddr;

+	p.m_Flags = NETSENDFLAG_CONNLESS;

+	p.m_pData = aData;

+	p.m_DataSize = sizeof(aData);

 

-	net_op.send(&p);

+	g_NetOp.Send(&p);

 }

 

-int main(int argc, char **argv)

+int main(int argc, char **argv) // ignore_convention

 {

-	NETADDR bindaddr;

+	NETADDR BindAddr;

 

 	dbg_logger_stdout();

 	net_init();

 

-	mem_zero(&bindaddr, sizeof(bindaddr));

-	bindaddr.port = VERSIONSRV_PORT;

-	net_op.open(bindaddr, 0);

+	mem_zero(&BindAddr, sizeof(BindAddr));

+	BindAddr.port = VERSIONSRV_PORT;

+	g_NetOp.Open(BindAddr, 0);

 	

 	dbg_msg("versionsrv", "started");

 	

 	while(1)

 	{

-		net_op.update();

+		g_NetOp.Update();

 		

 		// process packets

-		NETCHUNK packet;

-		while(net_op.recv(&packet))

+		CNetChunk Packet;

+		while(g_NetOp.Recv(&Packet))

 		{

-			if(packet.data_size == sizeof(VERSIONSRV_GETVERSION) &&

-				memcmp(packet.data, VERSIONSRV_GETVERSION, sizeof(VERSIONSRV_GETVERSION)) == 0)

+			if(Packet.m_DataSize == sizeof(VERSIONSRV_GETVERSION) &&

+				mem_comp(Packet.m_pData, VERSIONSRV_GETVERSION, sizeof(VERSIONSRV_GETVERSION)) == 0)

 			{

-				send_ver(&packet.address);

+				SendVer(&Packet.m_Address);

 			}

 		}

 		

diff --git a/src/versionsrv/versionsrv.h b/src/versionsrv/versionsrv.h
index 298f6c27..d458a54c 100644
--- a/src/versionsrv/versionsrv.h
+++ b/src/versionsrv/versionsrv.h
@@ -1,7 +1,9 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */

+#ifndef VERSIONSRV_VERSIONSRV_H
+#define VERSIONSRV_VERSIONSRV_H
 static const int VERSIONSRV_PORT = 8302;

 

 static const unsigned char VERSION_DATA[] = {0x00, 0, 5, 1};

 

 static const unsigned char VERSIONSRV_GETVERSION[] = {255, 255, 255, 255, 'v', 'e', 'r', 'g'};

 static const unsigned char VERSIONSRV_VERSION[] = {255, 255, 255, 255, 'v', 'e', 'r', 's'};

+#endif