diff --git a/core/CDataPack.cpp b/core/CDataPack.cpp
index 59352c92..59b0bbc0 100644
--- a/core/CDataPack.cpp
+++ b/core/CDataPack.cpp
@@ -76,9 +76,12 @@ void CDataPack::ResetSize()
 
 size_t CDataPack::CreateMemory(size_t size, void **addr)
 {
-	CheckSize(sizeof(size_t) + size);
+	CheckSize(sizeof(char) + sizeof(size_t) + size);
 	size_t pos = m_curptr - m_pBase;
 
+	*(char *)m_curptr = Raw;
+	m_curptr += sizeof(char);
+
 	*(size_t *)m_curptr = size;
 	m_curptr += sizeof(size_t);
 
@@ -88,14 +91,17 @@ size_t CDataPack::CreateMemory(size_t size, void **addr)
 	}
 
 	m_curptr += size;
-	m_size += sizeof(size_t) + size;
+	m_size += sizeof(char) + sizeof(size_t) + size;
 
 	return pos;
 }
 
 void CDataPack::PackCell(cell_t cell)
 {
-	CheckSize(sizeof(size_t) + sizeof(cell_t));
+	CheckSize(sizeof(char) + sizeof(size_t) + sizeof(cell_t));
+
+	*(char *)m_curptr = Cell;
+	m_curptr += sizeof(char);
 
 	*(size_t *)m_curptr = sizeof(cell_t);
 	m_curptr += sizeof(size_t);
@@ -103,12 +109,15 @@ void CDataPack::PackCell(cell_t cell)
 	*(cell_t *)m_curptr = cell;
 	m_curptr += sizeof(cell_t);
 
-	m_size += sizeof(size_t) + sizeof(cell_t);
+	m_size += sizeof(char) + sizeof(size_t) + sizeof(cell_t);
 }
 
 void CDataPack::PackFloat(float val)
 {
-	CheckSize(sizeof(size_t) + sizeof(float));
+	CheckSize(sizeof(char) + sizeof(size_t) + sizeof(float));
+
+	*(char *)m_curptr = Float;
+	m_curptr += sizeof(char);
 
 	*(size_t *)m_curptr = sizeof(float);
 	m_curptr += sizeof(size_t);
@@ -116,15 +125,18 @@ void CDataPack::PackFloat(float val)
 	*(float *)m_curptr = val;
 	m_curptr += sizeof(float);
 
-	m_size += sizeof(size_t) + sizeof(float);
+	m_size += sizeof(char) + sizeof(size_t) + sizeof(float);
 }
 
 void CDataPack::PackString(const char *string)
 {
 	size_t len = strlen(string);
-	size_t maxsize = sizeof(size_t) + len + 1;
+	size_t maxsize = sizeof(char) + sizeof(size_t) + len + 1;
 	CheckSize(maxsize);
 
+	*(char *)m_curptr = String;
+	m_curptr += sizeof(char);
+
 	// Pack the string length first for buffer overrun checking.
 	*(size_t *)m_curptr = len;
 	m_curptr += sizeof(size_t);
@@ -160,10 +172,16 @@ bool CDataPack::SetPosition(size_t pos) const
 
 cell_t CDataPack::ReadCell() const
 {
-	if (!IsReadable(sizeof(size_t) + sizeof(cell_t)))
+	if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
 	{
 		return 0;
 	}
+	if (*reinterpret_cast<char *>(m_curptr) != Cell)
+	{
+		return 0;
+	}
+	m_curptr += sizeof(char);
+
 	if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(cell_t))
 	{
 		return 0;
@@ -178,10 +196,16 @@ cell_t CDataPack::ReadCell() const
 
 float CDataPack::ReadFloat() const
 {
-	if (!IsReadable(sizeof(size_t) + sizeof(float)))
+	if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(float)))
 	{
 		return 0;
 	}
+	if (*reinterpret_cast<char *>(m_curptr) != Float)
+	{
+		return 0;
+	}
+	m_curptr += sizeof(char);
+
 	if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(float))
 	{
 		return 0;
@@ -201,10 +225,15 @@ bool CDataPack::IsReadable(size_t bytes) const
 
 const char *CDataPack::ReadString(size_t *len) const
 {
-	if (!IsReadable(sizeof(size_t)))
+	if (!IsReadable(sizeof(char) + sizeof(size_t)))
 	{
 		return NULL;
 	}
+	if (*reinterpret_cast<char *>(m_curptr) != String)
+	{
+		return NULL;
+	}
+	m_curptr += sizeof(char);
 
 	size_t real_len = *(size_t *)m_curptr;
 
@@ -237,6 +266,11 @@ void *CDataPack::ReadMemory(size_t *size) const
 	{
 		return NULL;
 	}
+	if (*reinterpret_cast<char *>(m_curptr) != Raw)
+	{
+		return NULL;
+	}
+	m_curptr += sizeof(char);
 
 	size_t bytecount = *(size_t *)m_curptr;
 	m_curptr += sizeof(size_t);
@@ -257,3 +291,43 @@ void *CDataPack::ReadMemory(size_t *size) const
 
 	return ptr;
 }
+
+void CDataPack::PackFunction(cell_t function)
+{
+	CheckSize(sizeof(char) + sizeof(size_t) + sizeof(cell_t));
+
+	*(char *)m_curptr = Function;
+	m_curptr += sizeof(char);
+
+	*(size_t *)m_curptr = sizeof(cell_t);
+	m_curptr += sizeof(size_t);
+
+	*(cell_t *)m_curptr = function;
+	m_curptr += sizeof(cell_t);
+
+	m_size += sizeof(char) + sizeof(size_t) + sizeof(cell_t);
+}
+
+cell_t CDataPack::ReadFunction() const
+{
+	if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
+	{
+		return 0;
+	}
+	if (*reinterpret_cast<char *>(m_curptr) != Function)
+	{
+		return 0;
+	}
+	m_curptr += sizeof(char);
+
+	if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(cell_t))
+	{
+		return 0;
+	}
+
+	m_curptr += sizeof(size_t);
+
+	cell_t val = *reinterpret_cast<cell_t *>(m_curptr);
+	m_curptr += sizeof(cell_t);
+	return val;
+}
\ No newline at end of file
diff --git a/core/CDataPack.h b/core/CDataPack.h
index 83a53539..48883f0d 100644
--- a/core/CDataPack.h
+++ b/core/CDataPack.h
@@ -51,12 +51,14 @@ public: //IDataReader
 	const char *ReadString(size_t *len) const;
 	void *GetMemory() const;
 	void *ReadMemory(size_t *size) const;
+	cell_t ReadFunction() const;
 public: //IDataPack
 	void ResetSize();
 	void PackCell(cell_t cell);
 	void PackFloat(float val);
 	void PackString(const char *string);
 	size_t CreateMemory(size_t size, void **addr);
+	void PackFunction(cell_t function);
 public:
 	void Initialize();
 private:
@@ -66,6 +68,14 @@ private:
 	mutable char *m_curptr;
 	size_t m_capacity;
 	size_t m_size;
+
+	enum DataPackType {
+		Raw,
+		Cell,
+		Float,
+		String,
+		Function
+	};
 };
 
 #endif //_INCLUDE_SOURCEMOD_CDATAPACK_H_
diff --git a/core/logic/smn_datapacks.cpp b/core/logic/smn_datapacks.cpp
index 21d7e7d6..2612abbc 100644
--- a/core/logic/smn_datapacks.cpp
+++ b/core/logic/smn_datapacks.cpp
@@ -148,6 +148,27 @@ static cell_t smn_WritePackString(IPluginContext *pContext, const cell_t *params
 	return 1;
 }
 
+static cell_t smn_WritePackFunction(IPluginContext *pContext, const cell_t *params)
+{
+	Handle_t hndl = static_cast<Handle_t>(params[1]);
+	HandleError herr;
+	HandleSecurity sec;
+	IDataPack *pDataPack;
+
+	sec.pOwner = pContext->GetIdentity();
+	sec.pIdentity = g_pCoreIdent;
+
+	if ((herr = handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
+		!= HandleError_None)
+	{
+		return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
+	}
+
+	pDataPack->PackFunction(params[2]);
+
+	return 1;
+}
+
 static cell_t smn_ReadPackCell(IPluginContext *pContext, const cell_t *params)
 {
 	Handle_t hndl = static_cast<Handle_t>(params[1]);
@@ -164,7 +185,7 @@ static cell_t smn_ReadPackCell(IPluginContext *pContext, const cell_t *params)
 		return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
 	}
 
-	if (!pDataPack->IsReadable(sizeof(size_t) + sizeof(cell_t)))
+	if (!pDataPack->IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
 	{
 		return pContext->ThrowNativeError("DataPack operation is out of bounds.");
 	}
@@ -188,7 +209,7 @@ static cell_t smn_ReadPackFloat(IPluginContext *pContext, const cell_t *params)
 		return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
 	}
 
-	if (!pDataPack->IsReadable(sizeof(size_t) + sizeof(float)))
+	if (!pDataPack->IsReadable(sizeof(char) + sizeof(size_t) + sizeof(float)))
 	{
 		return pContext->ThrowNativeError("DataPack operation is out of bounds.");
 	}
@@ -223,6 +244,30 @@ static cell_t smn_ReadPackString(IPluginContext *pContext, const cell_t *params)
 	return 1;
 }
 
+static cell_t smn_ReadPackFunction(IPluginContext *pContext, const cell_t *params)
+{
+	Handle_t hndl = static_cast<Handle_t>(params[1]);
+	HandleError herr;
+	HandleSecurity sec;
+	IDataPack *pDataPack;
+
+	sec.pOwner = pContext->GetIdentity();
+	sec.pIdentity = g_pCoreIdent;
+
+	if ((herr = handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
+		!= HandleError_None)
+	{
+		return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
+	}
+
+	if (!pDataPack->IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
+	{
+		return pContext->ThrowNativeError("DataPack operation is out of bounds.");
+	}
+
+	return pDataPack->ReadFunction();
+}
+
 static cell_t smn_ResetPack(IPluginContext *pContext, const cell_t *params)
 {
 	Handle_t hndl = static_cast<Handle_t>(params[1]);
@@ -318,9 +363,11 @@ REGISTER_NATIVES(datapacknatives)
 	{"WritePackCell",			smn_WritePackCell},
 	{"WritePackFloat",			smn_WritePackFloat},
 	{"WritePackString",			smn_WritePackString},
+	{"WritePackFunction",		smn_WritePackFunction},
 	{"ReadPackCell",			smn_ReadPackCell},
 	{"ReadPackFloat",			smn_ReadPackFloat},
 	{"ReadPackString",			smn_ReadPackString},
+	{"ReadPackFunction",		smn_ReadPackFunction},
 	{"ResetPack",				smn_ResetPack},
 	{"GetPackPosition",			smn_GetPackPosition},
 	{"SetPackPosition",			smn_SetPackPosition},
diff --git a/plugins/include/datapack.inc b/plugins/include/datapack.inc
index 73c66ff6..8c3ab0e9 100644
--- a/plugins/include/datapack.inc
+++ b/plugins/include/datapack.inc
@@ -72,6 +72,16 @@ native WritePackFloat(Handle:pack, Float:val);
  */
 native WritePackString(Handle:pack, const String:str[]);
 
+/**
+ * Packs a function pointer into a data pack.
+ *
+ * @param pack		Handle to the data pack.
+ * @param fktptr	Function pointer to add.
+ * @noreturn
+ * @error			Invalid handle.
+ */
+native WritePackFunction(Handle:pack, Function:fktptr);
+
 /**
  * Reads a cell from a data pack.
  *
@@ -101,6 +111,15 @@ native Float:ReadPackFloat(Handle:pack);
  */
 native ReadPackString(Handle:pack, String:buffer[], maxlen);
 
+/**
+ * Reads a function pointer from a data pack.
+ *
+ * @param pack		Handle to the data pack.
+ * @return			Function pointer.
+ * @error			Invalid handle, or bounds error.
+ */
+native Function ReadPackFunction(Handle:pack);
+
 /**
  * Resets the position in a data pack.
  *
diff --git a/public/IDataPack.h b/public/IDataPack.h
index a84a4416..e069bff0 100644
--- a/public/IDataPack.h
+++ b/public/IDataPack.h
@@ -113,6 +113,13 @@ namespace SourceMod
 		* @return			Pointer to the data, or NULL if out of bounds.
 		*/
 		virtual void *ReadMemory(size_t *size) const =0;
+
+		/**
+		 * @brief Reads a function pointer from the data stream.
+		 *
+		 * @return			A function pointer read from the current position.
+		 */
+		virtual cell_t ReadFunction() const =0;
 	};
 
 	/**
@@ -160,6 +167,13 @@ namespace SourceMod
 		 * @return			Current position of the stream beforehand.
 		 */
 		virtual size_t CreateMemory(size_t size, void **addr) =0;
+
+		/**
+		 * @brief Packs one function pointer into the data stream.
+		 *
+		 * @param function	The function pointer to write.
+		 */
+		virtual void PackFunction(cell_t function) =0;
 	};
 }