Quick answer: On a listen server the local player is both client and server. Server RPCs from the local host on non-owned actors are dropped. Check HasAuthority before calling Server RPCs, and always send Multicasts from the server only. Test every replication path on listen server, not just dedicated server.

You ship a multiplayer prototype. Dedicated server tests work perfectly: client fires, server handles, everyone sees the effect. Then a player hosts a listen server game for their friends and half your replication breaks. Effects fire for the other players but not the host, or vice versa. The bug is almost always in the same place: code that assumes “client” and “server” are different processes.

Dedicated vs. Listen Server

Unreal supports two multiplayer topologies. A dedicated server is a headless process with no local player — every player is a remote client. A listen server is a player who is also hosting: the same process is both the authoritative server and one of the clients.

Listen server is where replication bugs hide. On dedicated, any code you write is either on the client OR on the server, cleanly separated. On listen server, the host is both, and code like “check if we are the server, then call a Server RPC” behaves differently than on dedicated.

The Symptom

A replicated action works on remote clients but not on the listen server host (or the reverse):

The Three Common Bugs

Bug 1: Server RPC called when HasAuthority is already true.

On a listen server, the host’s PlayerController has authority because it is the server. When the host calls Server_Fire(), the RPC machinery recognizes it is already on the server and calls the function directly — which is fine — but only if the actor is the host’s owned actor. If the actor is not owned by the host, the RPC may be silently dropped.

Fix: check HasAuthority before sending the RPC, and if true, call the server function directly instead.

void APlayerPawn::Fire()
{
    if (HasAuthority())
    {
        Server_Fire_Implementation(); // already on server, call directly
    }
    else
    {
        Server_Fire(); // client sends RPC to server
    }
}

Bug 2: Multicast called from a client.

NetMulticast only runs on every machine when called from the server. Calling it from a client is a no-op — the client runs its local copy but no one else sees it. On dedicated server this usually works because clients call a Server RPC first, which then calls the Multicast. On listen server, the host who is “already on the server” sometimes skips that hop.

Always validate HasAuthority before calling a Multicast:

void APlayerPawn::Server_Fire_Implementation()
{
    check(HasAuthority());
    Multicast_PlayFireEffects();
}

void APlayerPawn::Multicast_PlayFireEffects_Implementation()
{
    // runs on every machine including the listen server host
    SpawnMuzzleFlash();
}

Bug 3: Actor ownership.

Server RPCs are routed through actor ownership. The actor must be owned by the calling client’s PlayerController, or the RPC is dropped. PlayerController itself is always owned by its player. Pawn is owned automatically while the player is possessing it. Any other actor needs SetOwner called explicitly if clients should be able to send Server RPCs on it.

Role Checks

Use GetLocalRole and GetRemoteRole for fine-grained checks. The possible values are:

On a listen server host, the host’s own pawn has LocalRole = ROLE_Authority. On a dedicated server client, the player’s own pawn has LocalRole = ROLE_AutonomousProxy. Test your code on both topologies to catch the differences.

Testing Listen Server in the Editor

In the editor, set Play dropdown to Listen Server mode. Add 2 or 3 clients. The first client is the listen server host; subsequent clients are remote. Alt-tab between them and test each action from each perspective:

Each of the four directions is a separate code path. All four must work before the feature is done.

Verifying the Fix

Add a UE_LOG at the start of each RPC implementation that prints GetLocalRole, HasAuthority, and the actor name. Run a listen server session with 2 clients and watch the logs. Every RPC should print on the right machines: Server RPCs on the authority, Client RPCs on the target client, Multicasts on everyone.

“Dedicated server is the easy case. Listen server is where you find the assumptions you made without realizing it. Test on both topologies every time or ship bugs to every P2P session.”

Related Issues

For dedicated server crashes, see how to debug dedicated server crashes in multiplayer games. For replicated variables specifically, see Unreal replicated variable not syncing. For client connection problems, see Unreal dedicated server client not connecting.

Always test the “host plays too” path. Listen server bugs that slip through dedicated testing are the ones that ship and frustrate the only player who matters — the one hosting.