diff --git a/src/p_mobj.c b/src/p_mobj.c
index 38d6e7a7e2ae469066dffe44cd2e34a2eec5e307..c14ffb251296789708b92a2dac2baffdff4d0e1e 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -11197,21 +11197,41 @@ void P_RemovePrecipMobj(precipmobj_t *mobj)
 void P_RemoveSavegameMobj(mobj_t *mobj)
 {
 	// unlink from sector and block lists
-	P_UnsetThingPosition(mobj);
+	if (((thinker_t *)mobj)->function.acp1 == (actionf_p1)P_NullPrecipThinker)
+	{
+		P_UnsetPrecipThingPosition((precipmobj_t *)mobj);
 
-	// Remove touching_sectorlist from mobj.
-	if (sector_list)
+		if (precipsector_list)
+		{
+			P_DelPrecipSeclist(precipsector_list);
+			precipsector_list = NULL;
+		}
+	}
+	else
 	{
-		P_DelSeclist(sector_list);
-		sector_list = NULL;
+		// unlink from sector and block lists
+		P_UnsetThingPosition(mobj);
+
+		// Remove touching_sectorlist from mobj.
+		if (sector_list)
+		{
+			P_DelSeclist(sector_list);
+			sector_list = NULL;
+		}
 	}
 
 	// stop any playing sound
 	S_StopSound(mobj);
+	R_RemoveMobjInterpolator(mobj);
 
 	// free block
-	P_RemoveThinker((thinker_t *)mobj);
-	R_RemoveMobjInterpolator(mobj);
+	// Here we use the same code as R_RemoveThinkerDelayed, but without reference counting (we're removing everything so it shouldn't matter) and without touching currentthinker since we aren't in P_RunThinkers
+	{
+		thinker_t *thinker = (thinker_t *)mobj;
+		thinker_t *next = thinker->next;
+		(next->prev = thinker->prev)->next = next;
+		Z_Free(thinker);
+	}
 }
 
 static CV_PossibleValue_t respawnitemtime_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}};
diff --git a/src/p_saveg.c b/src/p_saveg.c
index ce7353b95af8afaae4e4b14f707b911124a7d9f9..42125dae7c332a0689827750e3bc527266644609 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -3059,6 +3059,18 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
 			mobj->player->viewz = mobj->player->mo->z + mobj->player->viewheight;
 	}
 
+	if (mobj->type == MT_SKYBOX && mobj->spawnpoint)
+	{
+		mtag_t tag = Tag_FGet(&mobj->spawnpoint->tags);
+		if (tag >= 0 && tag <= 15)
+		{
+			if (mobj->spawnpoint->args[0])
+				skyboxcenterpnts[tag] = mobj;
+			else
+				skyboxviewpnts[tag] = mobj;
+		}
+	}
+
 	mobj->info = (mobjinfo_t *)next; // temporarily, set when leave this function
 
 	R_AddMobjInterpolator(mobj);
@@ -3680,10 +3692,14 @@ static void P_NetUnArchiveThinkers(void)
 		{
 			next = currentthinker->next;
 
-			if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
+			if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker || currentthinker->function.acp1 == (actionf_p1)P_NullPrecipThinker)
 				P_RemoveSavegameMobj((mobj_t *)currentthinker); // item isn't saved, don't remove it
 			else
+			{
+				(next->prev = currentthinker->prev)->next = next;
+				R_DestroyLevelInterpolators(currentthinker);
 				Z_Free(currentthinker);
+			}
 		}
 	}
 
@@ -3885,6 +3901,10 @@ static void P_NetUnArchiveThinkers(void)
 		CONS_Debug(DBG_NETPLAY, "%u thinkers loaded in list %d\n", numloaded, i);
 	}
 
+	// Set each skyboxmo to the first skybox (or NULL)
+	skyboxmo[0] = skyboxviewpnts[0];
+	skyboxmo[1] = skyboxcenterpnts[0];
+
 	if (restoreNum)
 	{
 		executor_t *delay = NULL;