diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 74f97048b3f5332070a14b05cf6f167f79267797..ae3e4b751b080325e955a956fa725b7aa70aa834 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -12,6 +12,7 @@ set(SRB2_CORE_SOURCES
 	d_net.c
 	d_netcmd.c
 	d_netfil.c
+	d_netmobj.c
 	dehacked.c
 	f_finale.c
 	f_wipe.c
@@ -84,6 +85,7 @@ set(SRB2_CORE_HEADERS
 	d_net.h
 	d_netcmd.h
 	d_netfil.h
+	d_netmobj.h
 	d_player.h
 	d_think.h
 	d_ticcmd.h
diff --git a/src/d_netmobj.c b/src/d_netmobj.c
new file mode 100644
index 0000000000000000000000000000000000000000..167e4044cca58246c410eeaaa09ea03759989823
--- /dev/null
+++ b/src/d_netmobj.c
@@ -0,0 +1,32 @@
+// SONIC ROBO BLAST 2
+//-----------------------------------------------------------------------------
+// Copyright (C) 2015 by Sonic Team Junior.
+//
+// This program is free software distributed under the
+// terms of the GNU General Public License, version 2.
+// See the 'LICENSE' file for more details.
+//-----------------------------------------------------------------------------
+/// \file  d_netmobj.c
+/// \brief Network handling for MObj.
+
+#include "d_netmobj.h"
+
+// Send a new mobj to clients.
+void Net_AddMobj(mobj_t *mo)
+{
+}
+
+// Send mobj updates to clients.
+void Net_WriteMobj(mobj_t *mo)
+{
+}
+
+// Spawn a new mobj from a server message.
+mobj_t *Net_ReadMobj(void *p)
+{
+}
+
+// Update mobj from server message.
+void Net_UpdateMobj(mobj_t *mo, void *p)
+{
+}
diff --git a/src/d_netmobj.h b/src/d_netmobj.h
new file mode 100644
index 0000000000000000000000000000000000000000..e5fde73d56a1b9d31060488412de83e48f35c975
--- /dev/null
+++ b/src/d_netmobj.h
@@ -0,0 +1,43 @@
+// SONIC ROBO BLAST 2
+//-----------------------------------------------------------------------------
+// Copyright (C) 2015 by Sonic Team Junior.
+//
+// This program is free software distributed under the
+// terms of the GNU General Public License, version 2.
+// See the 'LICENSE' file for more details.
+//-----------------------------------------------------------------------------
+/// \file  d_netmobj.h
+/// \brief Network handling for MObj.
+
+#ifndef __D_NETMOBJ__
+#define __D_NETMOBJ__
+/// \todo Fix NONET...
+
+#include "p_mobj.h"
+
+struct net_mobj_s
+{
+	UINT16 id;
+
+	fixed_t x, y, z;
+	fixed_t momx, momy, momz;
+	fixed_t radius, height;
+
+	angle_t angle;
+	spritenum_t sprite;
+	UINT8 sprite2;
+	UINT32 frame;
+
+	INT32 tics;
+	state_t *state;
+};
+
+// Server.
+void Net_AddMobj(mobj_t *mo); // Send a new mobj to clients.
+void Net_WriteMobj(mobj_t *mo); // Send mobj updates to clients.
+
+// Client.
+mobj_t *Net_ReadMobj(void *p); // Spawn a new mobj from a server message.
+void Net_UpdateMobj(mobj_t *mo, void *p); // Update mobj from server message.
+
+#endif
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 9565648c2ccfeb31d157010b2df59e4871f11ac9..cf71137741e8ab1fff685ce683b09a87571e0a95 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -5477,6 +5477,14 @@ void P_MobjThinker(mobj_t *mobj)
 	I_Assert(mobj != NULL);
 	I_Assert(!P_MobjWasRemoved(mobj));
 
+	// Network ghost mobjs don't think on their own.
+	if (netgame && !server && mobj->netData)
+	{
+		mobj->z += mobj->momz;
+		P_TryMove(mobj, mobj->x + mobj->momx, mobj->y + mobj->momy, true);
+		return;
+	}
+
 	if (mobj->flags & MF_NOTHINK)
 		return;
 
diff --git a/src/p_mobj.h b/src/p_mobj.h
index 8e782b92e5062db77f17a6d395783bece9d39c1d..3cec49fad5a98a2d1cb7d3fb9a17ccd95d6152df 100644
--- a/src/p_mobj.h
+++ b/src/p_mobj.h
@@ -257,6 +257,9 @@ typedef struct mobj_s
 	// List: thinker links.
 	thinker_t thinker;
 
+	// Last network transmission about this mobj.
+	struct net_mobj_s *netData;
+
 	// Info for drawing: position.
 	fixed_t x, y, z;