Help to understand replication/RPC behavior!

I’ve created a CombatComponent for my character and trying to just change attack status by pressing key.
All works but not see status for Simulated proxies.
Could smbd give me a hint what I’m doing in a wrong way.

Image:
[SPOILER]

[/SPOILER]

Code of the ActorComponent:

[SPOILER]

CombatComponent.h



// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "Net/UnrealNetwork.h"
#include "CombatComponent.generated.h"

UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class MULTIPLAYER_01_API UCombatComponent : public UActorComponent
{
    GENERATED_BODY()

public:
    // Sets default values for this component's properties
    UCombatComponent();

protected:
    // Called when the game starts
    virtual void BeginPlay() override;

    void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps);

   //
   UPROPERTY(Replicated, VisibleAnywhere, Category = "ServerActionState")
   FString AttackStatus = "NONE";
   UFUNCTION(Server, Reliable, WithValidation)
   void Server_AttackStatus(const FString& _AttackStatus);
   void Server_AttackStatus_Implementation(const FString& _AttackStatus);
   bool Server_AttackStatus_Validate(const FString& _AttackStatus);

public:

   // Called every frame
   virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
   void SimulatedTick(float DeltaTime);


   void Attack01();

private:

   class ACharacter* Owner = nullptr;

};



CombatComponent.cpp



// Fill out your copyright notice in the Description page of Project Settings.


#include "CombatComponent.h"

#include "Animation/AnimInstance.h"
#include "GameFramework/Character.h"
#include "DrawDebugHelpers.h"


// Sets default values for this component's properties
UCombatComponent::UCombatComponent()
{
   // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
   // off to improve performance if you don't need them.
   PrimaryComponentTick.bCanEverTick = true;
   SetIsReplicated(true);
}


// Called when the game starts
void UCombatComponent::BeginPlay()
{
   Super::BeginPlay();
   // Set owner reference
   Owner = Cast<ACharacter>(GetOwner());
}


// Called every frame
void UCombatComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
   Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

   if (ServerActionState.bIsRolling)
   {
      Owner->AddMovementInput(Owner->GetActorForwardVector(), 1.0, true);
   }

   if (GetOwnerRole() == ROLE_Authority)
   {
      DrawDebugString(GetWorld(),
      FVector(0, 0, 150),
      AttackStatus,
      GetOwner(),
      FColor::White,
      0.1f);
   }
   //
   if (GetOwnerRole() == ROLE_AutonomousProxy)
   {
      DrawDebugString(GetWorld(),
      FVector(0, 0, 150),
      AttackStatus,
      GetOwner(),
      FColor::White,
      0.1f);
   }
   //
   if (GetOwnerRole() == ROLE_SimulatedProxy)
   {
      SimulatedTick(DeltaTime);
   }
}

void UCombatComponent::SimulatedTick(float DeltaTime)
{
   DrawDebugString(GetWorld(),
   FVector(0, 0, 150),
   AttackStatus,
   GetOwner(),
   FColor::White,
   0.1f);
}

void UCombatComponent::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps)
{
   Super::GetLifetimeReplicatedProps(OutLifetimeProps);

   DOREPLIFETIME(UCombatComponent, AttackStatus);
}

void UCombatComponent::Server_AttackStatus_Implementation(const FString& _AttackStatus)
{
   AttackStatus = _AttackStatus;
}

bool UCombatComponent::Server_AttackStatus_Validate(const FString& _AttackStatus)
{
   return true;
}

void UCombatComponent::Attack01()
{
   if (!Owner)
   {
      return;
   }

   // Update Listen-Client state on the server for simulation purposes
   if (GetOwnerRole() == ROLE_Authority && Owner->IsLocallyControlled())
   {
      UE_LOG(LogTemp, Warning, TEXT("Server Listen-Client ATTACK"))
      AttackStatus = "Attack_01";
      Server_AttackStatus("Attack_01");
   }
   //
   if (GetOwnerRole() == ROLE_AutonomousProxy)
   {
      UE_LOG(LogTemp, Warning, TEXT("Autonomous ATTACK"))
      AttackStatus = "Attack_01";
      Server_AttackStatus("Attack_01");
   }
   if (GetOwnerRole() == ROLE_SimulatedProxy)
   {
      UE_LOG(LogTemp, Warning, TEXT("Simulated ATTACK"))
      AttackStatus = "Attack_01";
      Server_AttackStatus("Attack_01");
   }
}



[/SPOILER]

PS
Replicated checkbox for the component is ON too.

pretty sure this line


Server_AttackStatus("Attack_01");

should be


"Server_AttackStatus(AttackStatus)";

For me, it doesn’t matter here, it is just passing FString to the RPC function.
I think it is a replication issue

Anyway, thnx and I try to change it

I’ve found the solution: I’ve lost “const” modifier in the end of

GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const

It’s a tricky mistake, cause this function without “const” hide a parent function and replication is not working eventually. I’ve seen this warning (not error!) in VS with successful compilation in editor at the same time.

Be careful with that guys), good luck in your projects!