Mostly Harmless
Legacy:Netcode Idioms
This is a cookbook of ways to get round some of the 'gotchas' in replication.
Contents
Targetting types of machine[edit]
There are basically 5 types of machine:
(Level.NetMode == NM_ListenServer)
– listen servers (with a local player)(Level.NetMode == NM_DedicatedServer)
– dedicated servers (no local player)(Level.NetMode == NM_Client)
– clients(Level.NetMode == NM_Client && bNetOwner)
– owner clients (special case of client where the local player is the Owner of the actor in question)(Level.NetMode == NM_Standalone)
– standalone games
You sometimes need things to happen only on certain types of machine. Here's how:
if (Level.NetMode != NM_DedicatedServer) { // This could be offline, a listen server or a client, but we know // we have a local player on this machine, someone who can see or hear things. } if (Role == ROLE_Authority) { // This is the authorative copy of this actor, it was spawned on this machine. // It is not a guarantee that we are on the server or in single player! } if (Role < ROLE_Authortity) { // This is a non-authorative copy of this actor that was replicated // from the server. In other words, we must be on a client. } // please add more!
Finding the Local PlayerPawn or PlayerController[edit]
UnrealEngine1[edit]
The usual idiom for finding the local player's PlayerPawn (UT) on a network client or a listen server is (after declaring a class-level var PlayerPawn PlayerLocal):
if (PlayerLocal == None) foreach AllActors(class 'PlayerPawn', PlayerLocal) if (Viewport(PlayerLocal.Player) != None) break; if (PlayerLocal != None) { ... } // do something with it
If you have a Canvas object handy (in engine events like RenderOverlays, for instance), there's even a more straightforward way to get hold of the local player:
PlayerLocal = Canvas.Viewport.Actor;
UnrealEngine2[edit]
UT2003 and UT2004 have a function to get the local PlayerController which actually uses the PlayerController/DynamicActors combo (and stores the local controller for later use too):
PlayerLocal = Level.GetLocalPlayerController();
Again, if you have a Canvas object handy you should use the more straight forward version like in UT:
PlayerLocal = Canvas.Viewport.Actor;
Note that the local PlayerPawn or PlayerController is always relevant (for obvious reasons) and thus always exists on its respective client.
HUD Mutators[edit]
See Useful Mutator Functions or Linked List/Existing Lists in Unreal Tournament (use the Quick Navigation menu to browse to "HUD Mutators"). You'll find a description there how to set up a HUD mutator that actually works in network games.
Replicating Config Variables[edit]
Clients load the value of config or globalconfig variables from their own .ini files. Since these values are treated as defaults they are not replicated until they are changed through code. Clients will see their own customized configuration instead of the server's.
To force replication of these variables use a second (non-config) variable:
var config string MySettings; var string ServerSettings; replication { // replicate the ServerSettings variable to all (relevant) clients reliable if ( Role == ROLE_Authority ) ServerSettings; } function PreBeginPlay() { // non-simulated PreBeginPlay() is only executed on the server - You can take away the 'if' expression below then. // simulated PreBeginPlay() is executed on both the server and the client. - You must include the 'if' expression below then. if ( Role == ROLE_Authority ) ServerSettings = MySettings; Super.PreBeginPlay(); }
Related Topics[edit]
Discussion[edit]
Matariel: Correct me if Im wrong but... doesn't Role == Role_Authority simply mean that this is the authoritative copy of the actor? What if this actor was spawned on a client? I don't think a Role == Role_Authority check qualifies the machine as a server, but simply as the owner.
Wormbo: That's correct, but usually you only do any Role checks if you intend to replicate your actor.