Client -> Server RPC not working

Hi,
I trying to replicate a function from client to everybody. So I pass the function to the server then from the server I multicast evrybody.

.h
UFUNCTION(BlueprintCallable, Category = InteractiveObject)
void Use(AActor* actor);

	UFUNCTION(NetMulticast, WithValidation, reliable)
		void MCRPCCallUse(AActor* actor);
		void MCRPCCallUse_Implementation(AActor* actor);
		bool MCRPCCallUse_Validate(AActor* actor);
	UFUNCTION(Server, WithValidation, reliable)
		void SRPCCallUse(AActor* actor);
		void SRPCCallUse_Implementation(AActor* actor);
		bool SRPCCallUse_Validate(AActor* actor);

	UFUNCTION(BlueprintImplementableEvent, Category = InteractiveObject)
		void CallUse(AActor* actor);

.cpp

void AInteractiveObject::Use(AActor* actor)
{
	if (bReplicateUse) //Option to disable or enable the replication of the function (enable everytime)
	{
		if (Role == ROLE_Authority) //If is on server, call to all clients
		{
			MCRPCCallUse(actor);
                    //It works
		}
		else if (Role < ROLE_Authority) //else if on a client, call the multicast function on server from client
		{
			SRPCCallUse(actor);
                    //It works
		}
	}
	else
	{
		CallUse(actor);
	}
}


//RPC
void AInteractiveObject::MCRPCCallUse_Implementation(AActor* actor)
{
	CallUse(actor);
	//It works
}
bool AInteractiveObject::MCRPCCallUse_Validate(AActor* actor)
{
	return true;
}
void AInteractiveObject::SRPCCallUse_Implementation(AActor* actor)
{
   //It doesn't works       <=
	MCRPCCallUse(actor);
}
bool AInteractiveObject::SRPCCallUse_Validate(AActor* actor)
{
	return true;
}

Thanks

Not sure how you’re determining if things work or not.

But what seems strange to me was declaring the _Implementation and _Validate methods in the headers. As those don’t seem necessary.

I’m not sure if what I’m doing is the suggested way, but I would always just call the server first, regardless if I’m actually the server or not. And then in the method that only runs on server, perform a multi cast.

Also not sure if a validation is necessary for multicast calls. Since multicast when invoked from the server, gets server and clients, and when invoked from client only gets the client itself. (See here for reference: RPCs | Unreal Engine Documentation)

I have tried to remove _Implementation and _Validate in .h but it doesn’t compile.
SRPCCallUse_Implementation is not a member of ‘AInteractiveObject’
etc…

This is going to be a silly question. But you do have GENERATED_BODY() in the header right? GENERATED_BODY() ?

I wonder if they changed it being required in UE 4.12, cause I’m using that and I don’t need to declare the _Implementation in my header. Cause I know they generated that before 4.7

Either way, how are you testing if the thing works or not? Like are you using the debugger? Making log statements? Or something else entirely.

EDIT: Additional note, I noticed your ‘reliable’ is not ‘Reliable’ as indicate in https://docs.unrealengine.com/latest/INT/Programming/UnrealArchitecture/Reference/Functions/Specifiers/Reliable/index.html
Not sure if there’s a difference

I have GENERATED_BODY() in the .h and with log the call to the server is not working but multicast works

Can’t think of anything else. I wouldn’t know where else to look unless I have the project to play around and test with. Unless you can provide that such as pushing to github, I personally can’t help you :frowning:

Hopefully someone has a better clue.

Ok, I find the problem ! My AInteractiveObject was not owned by Controller and to call a server function from client, the client must “control” the actor (here my object). I think it’s for security.
So I’ve move the call of functions (Server and Multicast) in the Character who is owned by the playercontroller.

Character.cpp

//ACTION
void ADefaultCharacter::Use()
{
	FVector CamLoc;
	FRotator CamRot;
	Controller->GetPlayerViewPoint(CamLoc, CamRot);
	const FVector StartTrace = CamLoc;
	const FVector Direction = CamRot.Vector();
	const FVector EndTrace = StartTrace + Direction * UseDistance;

	FCollisionQueryParams TraceParams(FName(TEXT("Trace")), true, this);
	TraceParams.bTraceAsyncScene = true;
	TraceParams.bReturnPhysicalMaterial = true;

	FHitResult Hit(ForceInit);
	if (GetWorld()->LineTraceSingleByChannel(Hit, StartTrace, EndTrace, ECC_WorldStatic, TraceParams))
	{
		AInteractiveObject* object = Cast<AInteractiveObject>(Hit.GetActor());

		if (object != NULL)
		{
			if (Role == ROLE_Authority)
			{
				MCCallUse(object);
			}
			else if (Role < ROLE_Authority)
			{
				SCallUse(object);
			}

			//object->SetOwner(GetController());
			//object->Use(this);
		}
	}
}

void ADefaultCharacter::SCallUse_Implementation(AInteractiveObject* object)
{
	//object->CallUse(this);
	MCCallUse(object);
}
bool ADefaultCharacter::SCallUse_Validate(AInteractiveObject* object)
{
	return true;
}
void ADefaultCharacter::MCCallUse_Implementation(AInteractiveObject* object)
{
	object->CallUse(this);
}

And my AInteractiveObject.h

UFUNCTION(BlueprintImplementableEvent, Category = InteractiveObject)
		void CallUse(AActor* actor);

So here, I call the server function from the character who is owned by the playercontroller and I have to call ALL server function from the character or the playercontroller.

Thanks for your help !