For gathering the info you could create a subsystem inherited from game instance and use:
// Listens when world starts.
FWorldDelegates::OnPostWorldInitialization.AddUObject();
// Listens when actor is added to world.
FWorldDelegates::OnWorldInitializedActors.AddUObject();
// For async levels (have not personally tested this)
FWorldDelegates::LevelAddedToWorld.AddUObject();
On each callback check if the actor has UMyGatherComponent (the custom base component I mentioned above) to capture their pointers to then gather the info.
For more info on this check out Serialization Best Practices and Techniques | Talks and demos. Includes Github link of the project. This seems to be exactly what you are after.
I cant help with replication, though. I would assume this custom subsystem will have all the logic since its created before the level and persists until the program is closed.