I’m not sure if you need any more advice but I just spent the last few hours going through this so I 100% know what I’m doing is right.
It seems I was incorrect when I said OnConstruction isn’t called on Clients. However, it should still be avoided because it will only ever be called for Actors that weren’t originally part of the level (i.e. created from SpawnActor()). There is a version for Actors that were originally part of the level called OnPostLoad, however, at this point in the lifecycle, the Actor isn’t aware of its NetRole (whether it’s a server or a client).
Ultimately, both should be avoided for anything other than what it was designed for (which is adding components and setting initial values).
Replication and thus RepNotifies do indeed always seem to be triggered before BeginPlay. Alternatively, you can also use PostNetInit but that only works for clients and doesn’t work for Actors that were originally part of the level.
If you want to do stuff before any replication (i.e. subscribe to certain events before any RepNotifies which will later trigger them), then your best (and basically only choice) is to use PostInitializeComponents. However, when using this method, you will have to add an if (IsValid(GetWorld()) && GetWorld()->IsGameWorld())
check since it is also called when opening a Blueprint in the Editor (under certain circumstances, this can cause crashes).
The same idea applies to Components too, with OnRegister being the Component version of PostInitializeComponents.
In conclusion, BeginPlay is basically OnStart (as in, the Actor is completely ready and the game has started, but I assume most of us already knew that), then PostInitializeComponents and OnRegister is basically OnReady (as in, the Actor is ready to be started; the only thing left is replication).
I would have called OnReady OnCreated instead but UE4’s definition of ‘created’ doesn’t include objects that were instantiated from a serialized file (i.e. a level).