Get Player Controller on Listen Servers

Hello,

I’m trying to get the player controller on a listen server. Sadly, the IsLocalPlayerController() function returns true for every controller in the server, since it owns them all, so I’m having a hard time searching for the listen server.

I’m trying to use this code to get the hud of each player (and show some info on screen to help in debugging):

	AMyHUD* hud = NULL;
	APlayerController* pc = NULL;
	for (FConstPlayerControllerIterator Iterator = GetWorld()->GetPlayerControllerIterator(); Iterator; ++Iterator)
	{
		pc = Iterator->Get();
		if (pc->IsLocalPlayerController())
		{
			hud = Cast<AMyHUD>(pc->GetHUD());
			break;
		}
	}

	if (!hud)
		return;

That works for the clients, but it’s failing for the listen server.
After some research, I started to try this variation:

	AMyHUD* hud = NULL;
	APlayerController* pc = NULL;
	pc = UGameplayStatics::GetPlayerController(GetWorld(), 0);

	if (pc->IsLocalPlayerController())
	{
		hud = Cast<AMyHUD>(pc->GetHUD());
	}
	else
	{
		for (FConstPlayerControllerIterator Iterator = GetWorld()->GetPlayerControllerIterator(); Iterator; ++Iterator)
		{
			pc = Iterator->Get();
			if (pc->IsLocalPlayerController())
			{
				hud = Cast<AMyHUD>(pc->GetHUD());
				break;
			}
		}
	}
	if (!hud)
		return;

Since I found searching that the player with index 0 would be the listen server, but apparently that’s wrong.

Can you, please, help me with this issue?

Thanks in advance!

#What I do

In this code below, the Listen server’s player controller will always be the first one that is found by ObjectIterator and returned to you!

#It Gets Even Better
This is also true for clients! The first found PC will always be the local client’s PC!

#The C++ Code

FORCEINLINE AYourPC* GetPC()
{
   TObjectIterator<AYourPC> Itr; //Not looping, just want the first entry
   if(!Itr) return nullptr;  //This can happen while PIE is exiting
   return *Itr;
}

#Thoroughly Tested

I’ve used this code since the Beta in over 10 different major UE4 projects and it has worked as I describe all the way from pre 4.0 to 4.7.5

#Regarding Your Actual Question

You do know that HUDs are not replicated right? I dont see how you are going to iterate over all the HUDs? There should only ever be 1 HUD actor, and it will only exist on the local machine, right?

#To Try

If you do this:

for(TObjectIterator<AHUD> Itr; Itr; ++Itr)
{
   UE_LOG(yourlog,Warning,TEXT("found a hud %s"), *Itr->GetName());
}

how many huds do you find?

#:heart:

Rama

Hello @Rama,

Thank for your support and help!

Yeah, you got it right, I want to make each client set their information on their own. After re-reading my question, it wasn’t that clear.

Sadly, the function you suggested didn’t work.
I added it to a library with static functions (as you recommended in one of your tutorials). Please, tell me if this might be the issue.

With the way I suggested in the initial post, each client gets their own HUD and the listen servers get the HUD of one of the players (apparently, the last one to connect.). It’s important to remember that, here, I’m treating the editor as the listen server (aka: I’m not running a standalone version of the game as the listen server).
Using the function you suggested, only the listen server shows the HUD, and it shows the data of one of the players (again, apparently the last one to connect. Didn’t try enough times to tell if it’s random or always the last one).

The code with your function looks like this:

	APlayerController* pc = UMyLib::GetPC();
	AMyHUD* hud = nullptr;
	if (pc)
		hud = Cast<AMyHUD>(pc->GetHUD());
	if (!hud)
		return;

By running the for loop you requested, I get this, multiple times, for 1 client and 1 listen server (the editor):

MyLog:Warning: found a hud MyHUD_2

MyLog:Warning: found a hud MyHUD_3

and trying right after, 2 clients and 1 listen server:

MyBuildingLog:Warning: found a hud MyHUD_7

MyBuildingLog:Warning: found a hud MyHUD_6

MyBuildingLog:Warning: found a hud MyHUD_8

Thank you again for looking into this issue! Hopefully, with your help, I’ll be able to find a solution! :smiley:

Cheers!

Adding for clarity:

When I run the function you provided, there are no HUDs displayed on any of the clients, but the listen server displays the HUD. The data contained there has the player location among other stuff:

FString::Printf(TEXT("Player Location - X: %5.4f Y: %5.4f Z: %5.4f "), GetActorLocation().X, GetActorLocation().Y, GetActorLocation().Z)

So it’s easy to see from who is the data by moving the character around.

Did you find a solution to this?

This is a very old question, and I don’t recall how I solved this.
I think I started from scratch and changed the way I implemented this feature.

Is this similar to any issue you’re having?

Open a answer hub question and link it here and I’ll try to help :slight_smile: