diff --git a/core/CPlayerManager.cpp b/core/CPlayerManager.cpp
new file mode 100644
index 00000000..968e18af
--- /dev/null
+++ b/core/CPlayerManager.cpp
@@ -0,0 +1,101 @@
+#include "CPlayerManager.h"
+#include "ForwardSys.h"
+
+SH_DECL_HOOK5(IServerGameClients, ClientConnect, SH_NOATTRIB, 0, bool, edict_t *, const char *, const char *, char *, int);
+SH_DECL_HOOK2_void(IServerGameClients, ClientPutInServer, SH_NOATTRIB, 0, edict_t *, const char *);
+SH_DECL_HOOK1_void(IServerGameClients, ClientDisconnect, SH_NOATTRIB, 0, edict_t *);
+SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *);
+
+void CPlayerManager::OnSourceModAllInitialized()
+{
+	SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientConnect, serverClients, this, &CPlayerManager::OnClientConnect, false);
+	SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, serverClients, this, &CPlayerManager::OnClientPutInServer, true);
+	SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &CPlayerManager::OnClientDisconnect, false);
+	SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &CPlayerManager::OnClientDisconnect_Post, true);
+	SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientCommand, serverClients, this, &CPlayerManager::OnClientCommand, false);
+
+	/* Register OnClientConnect */
+	ParamType p1[] = {Param_Cell, Param_String, Param_Cell};
+	m_clconnect = g_Forwards.CreateForward("OnClientConnect", ET_Event, 3, p1);
+
+	/* Register OnClientPutInServer */
+	ParamType p2[] = {Param_Cell};
+	m_clputinserver = g_Forwards.CreateForward("OnClientPutInServer", ET_Ignore, 1, p2);
+
+	/* Register OnClientDisconnect */
+	m_cldisconnect = g_Forwards.CreateForward("OnClientDisconnect", ET_Ignore, 1, p2);
+
+	/* Register OnClientDisconnect_Post */
+	m_cldisconnect_post = g_Forwards.CreateForward("OnClientDisconnect_Post", ET_Ignore, 1, p2);
+
+	/* Register OnClientCommand */
+	m_clcommand = g_Forwards.CreateForward("OnClientCommand", ET_Hook, 1, p2);
+
+	/* Register OnClientAuthorized */
+	//:TODO:
+}
+
+void CPlayerManager::OnSourceModShutdown()
+{
+	SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientConnect, serverClients, this, &CPlayerManager::OnClientConnect, false);
+	SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, serverClients, this, &CPlayerManager::OnClientPutInServer, true);
+	SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &CPlayerManager::OnClientDisconnect, false);
+	SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &CPlayerManager::OnClientDisconnect_Post, true);
+	SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientCommand, serverClients, this, &CPlayerManager::OnClientCommand, false);
+
+	/* Release forwards */
+	g_Forwards.ReleaseForward(m_clconnect);
+	g_Forwards.ReleaseForward(m_clputinserver);
+	g_Forwards.ReleaseForward(m_cldisconnect);
+	g_Forwards.ReleaseForward(m_cldisconnect_post);
+	g_Forwards.ReleaseForward(m_clcommand);
+}
+
+bool CPlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen)
+{
+	cell_t res = 1;
+
+	m_clconnect->PushCell(engine->IndexOfEdict(pEntity));
+	m_clconnect->PushStringEx(reject, maxrejectlen, SM_PARAM_STRING_UTF8, SM_PARAM_COPYBACK);
+	m_clconnect->PushCell(maxrejectlen);
+	m_clconnect->Execute(&res, NULL);
+
+	return (res) ? true : false;
+}
+
+void CPlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername)
+{
+	cell_t res;
+
+	m_clputinserver->PushCell(engine->IndexOfEdict(pEntity));
+	m_clputinserver->Execute(&res, NULL);
+}
+
+void CPlayerManager::OnClientAuthorized()
+{
+	//:TODO:
+}
+
+void CPlayerManager::OnClientDisconnect(edict_t *pEntity)
+{
+	cell_t res;
+
+	m_cldisconnect->PushCell(engine->IndexOfEdict(pEntity));
+	m_cldisconnect->Execute(&res, NULL);
+}
+
+void CPlayerManager::OnClientDisconnect_Post(edict_t *pEntity)
+{
+	cell_t res;
+
+	m_cldisconnect_post->PushCell(engine->IndexOfEdict(pEntity));
+	m_cldisconnect_post->Execute(&res, NULL);
+}
+
+void CPlayerManager::OnClientCommand(edict_t *pEntity)
+{
+	cell_t res;
+
+	m_clcommand->PushCell(engine->IndexOfEdict(pEntity));
+	m_clcommand->Execute(&res, NULL);
+}
\ No newline at end of file
diff --git a/core/CPlayerManager.h b/core/CPlayerManager.h
new file mode 100644
index 00000000..b11b233c
--- /dev/null
+++ b/core/CPlayerManager.h
@@ -0,0 +1,29 @@
+#ifndef _INCLUDE_SOURCEMOD_CPLAYERMANAGER_H_
+#define _INCLUDE_SOURCEMOD_CPLAYERMANAGER_H_
+
+#include "sourcemod.h"
+#include <eiface.h>
+#include "sourcemm_api.h"
+#include <IForwardSys.h>
+
+class CPlayerManager : public SMGlobalClass
+{
+public: //SMGlobalClass
+	virtual void OnSourceModAllInitialized();
+	virtual void OnSourceModShutdown();
+public:
+	bool OnClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
+	void OnClientPutInServer(edict_t *pEntity, char const *playername);
+	void OnClientDisconnect(edict_t *pEntity);
+	void OnClientDisconnect_Post(edict_t *pEntity);
+	void OnClientAuthorized(); //:TODO: any args needed?
+	void OnClientCommand(edict_t *pEntity);
+private:
+	IForward *m_clconnect;
+	IForward *m_cldisconnect;
+	IForward *m_cldisconnect_post;
+	IForward *m_clputinserver;
+	IForward *m_clcommand;
+};
+
+#endif //_INCLUDE_SOURCEMOD_CPLAYERMANAGER_H_
\ No newline at end of file
diff --git a/core/msvc8/sourcemod_mm.vcproj b/core/msvc8/sourcemod_mm.vcproj
index f729f595..79ece72c 100644
--- a/core/msvc8/sourcemod_mm.vcproj
+++ b/core/msvc8/sourcemod_mm.vcproj
@@ -178,6 +178,10 @@
 			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
 			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
 			>
+			<File
+				RelativePath="..\CPlayerManager.cpp"
+				>
+			</File>
 			<File
 				RelativePath="..\CTextParsers.cpp"
 				>
@@ -216,6 +220,10 @@
 			Filter="h;hpp;hxx;hm;inl;inc;xsd"
 			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
 			>
+			<File
+				RelativePath="..\CPlayerManager.h"
+				>
+			</File>
 			<File
 				RelativePath="..\CTextParsers.h"
 				>
@@ -499,6 +507,10 @@
 					RelativePath="..\..\sourcepawn\include\sp_vm_types.h"
 					>
 				</File>
+				<File
+					RelativePath="..\..\sourcepawn\include\sp_vm_typeutil.h"
+					>
+				</File>
 			</Filter>
 		</Filter>
 	</Files>
diff --git a/core/smn_float.cpp b/core/smn_float.cpp
index cba159f9..96a4d129 100644
--- a/core/smn_float.cpp
+++ b/core/smn_float.cpp
@@ -1,20 +1,12 @@
 #include <math.h>
 #include <string.h>
 #include "sp_vm_api.h"
+#include "sp_vm_typeutil.h"
 
 using namespace SourcePawn;
 
 #define PI 3.14159265358979323846
 
-inline cell_t ftoc(float val)
-{
-	return *(cell_t *)&val;
-}
-inline float ctof(cell_t val)
-{
-	return *(float *)&val;
-}
-
 inline float AngleToRadians(float val, int mode)
 {
 	switch (mode)
diff --git a/core/smn_string.cpp b/core/smn_string.cpp
index 627d1a90..b76c485f 100644
--- a/core/smn_string.cpp
+++ b/core/smn_string.cpp
@@ -1,7 +1,9 @@
 #include "sm_platform.h"
 #include <ctype.h>
 #include <string.h>
+#include <stdlib.h>
 #include "sp_vm_api.h"
+#include "sp_vm_typeutil.h"
 
 using namespace SourcePawn;
 
@@ -43,6 +45,18 @@ inline const char *_strstr(const char *str, const char *substr)
 #endif
 }
 
+inline int StrConvInt(const char *str)
+{
+	char *dummy;
+	return strtol(str, &dummy, 10);
+}
+
+inline float StrConvFloat(const char *str)
+{
+	char *dummy;
+	return (float)strtod(str, &dummy);
+}
+
 /*********************************************
 *                                            *
 * STRING MANIPULATION NATIVE IMPLEMENTATIONS *
@@ -109,3 +123,35 @@ static cell_t sm_strcopy(IPluginContext *pCtx, const cell_t *params)
 
 	return (dest - start);
 }
+
+static cell_t sm_strtonum(IPluginContext *pCtx, const cell_t *params)
+{
+	char *str;
+	pCtx->LocalToString(params[1], &str);
+
+	return StrConvInt(str);
+}
+
+static cell_t sm_numtostr(IPluginContext *pCtx, const cell_t *params)
+{
+	char *str;
+	pCtx->LocalToString(params[2], &str);
+
+	return snprintf(str, params[3], "%d", params[1]);
+}
+
+static cell_t sm_strtofloat(IPluginContext *pCtx, const cell_t *params)
+{
+	char *str;
+	pCtx->LocalToString(params[1], &str);
+
+	return ftoc(StrConvFloat(str));
+}
+
+static cell_t sm_floattostr(IPluginContext *pCtx, const cell_t *params)
+{
+	char *str;
+	pCtx->LocalToString(params[2], &str);
+
+	return snprintf(str, params[3], "%f", ctof(params[1]));
+}
diff --git a/core/sourcemm_api.cpp b/core/sourcemm_api.cpp
index 7c701977..1b593456 100644
--- a/core/sourcemm_api.cpp
+++ b/core/sourcemm_api.cpp
@@ -6,6 +6,7 @@
 SourceMod_Core g_SourceMod_Core;
 IVEngineServer *engine = NULL;
 IServerGameDLL *gamedll = NULL;
+IServerGameClients *serverClients = NULL;
 
 PLUGIN_EXPOSE(SourceMod, g_SourceMod_Core);
 
@@ -15,11 +16,12 @@ bool SourceMod_Core::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen
 
 	GET_V_IFACE_ANY(serverFactory, gamedll, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL);
 	GET_V_IFACE_CURRENT(engineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER);
+	GET_V_IFACE_CURRENT(serverFactory, serverClients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS);
 
 	return g_SourceMod.InitializeSourceMod(error, maxlen, late);
 }
 
-bool SourceMod_Core::Unload(char	*error, size_t maxlen)
+bool SourceMod_Core::Unload(char *error, size_t maxlen)
 {
 	return true;
 }
diff --git a/core/sourcemm_api.h b/core/sourcemm_api.h
index dff0a5a8..8dea8b0b 100644
--- a/core/sourcemm_api.h
+++ b/core/sourcemm_api.h
@@ -30,6 +30,7 @@ public:
 extern SourceMod_Core g_SourceMod_Core;
 extern IVEngineServer *engine;
 extern IServerGameDLL *gamedll;
+extern IServerGameClients *serverClients;
 
 PLUGIN_GLOBALVARS();
 
diff --git a/core/systems/ForwardSys.cpp b/core/systems/ForwardSys.cpp
index d0dd7b26..0a3bb6b1 100644
--- a/core/systems/ForwardSys.cpp
+++ b/core/systems/ForwardSys.cpp
@@ -28,6 +28,9 @@ CForwardManager g_Forwards;
  * X Push vararg strings (copyback tested = :TODO:)
  */
 
+// :TODO: IMPORTANT!!! The result pointer arg in the execute function maybe invalid if the forward fails
+// so later evaluation of this result may cause problems on higher levels of abstraction. DOCUMENT OR FIX ALL FORWARDS!
+
 void CForwardManager::OnSourceModAllInitialized()
 {
 	g_PluginSys.AddPluginsListener(this);
diff --git a/sourcepawn/include/sp_vm_typeutil.h b/sourcepawn/include/sp_vm_typeutil.h
new file mode 100644
index 00000000..40987e4d
--- /dev/null
+++ b/sourcepawn/include/sp_vm_typeutil.h
@@ -0,0 +1,15 @@
+#ifndef _INCLUDE_SOURCEPAWN_VM_TYPEUTIL_H_
+#define _INCLUDE_SOURCEPAWN_VM_TYPEUTIL_H_
+
+#include "sp_vm_types.h"
+
+inline cell_t ftoc(float val)
+{
+	return *(cell_t *)&val;
+}
+inline float ctof(cell_t val)
+{
+	return *(float *)&val;
+}
+
+#endif //_INCLUDE_SOURCEPAWN_VM_TYPEUTIL_H_
\ No newline at end of file