Download

How to get struct from client to server?

I have a struct in a client’s GameInstance which I’ll call “CharacterDetails”, which contains purely cosmetic information about a user’s character. The game in question works for single player, multiplayer, and LAN. I understand that a PlayerState exists on both client and server, so I want to set CharacterDetails in the PlayerState from the server, so the value is replicated to all clients.

When I prototyped this in Blueprint, it seemed to work. Users connecting to the server would have all the details they input beforehand be replicated. Here are some images of what I was doing within BP:



I went to remake this in C++, but I don’t seem to be getting the same result. I’ve stripped this down to just what I’ve done to try and achieve the above:

GameModeRoot.h



#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "PlayerStates/PlayerStateBase.h"
#include "GameModeRoot.generated.h"

/**
 *
 */
UCLASS()
class FORUMPOST_API AGameModeRoot : public AGameModeBase
{
    GENERATED_BODY()

protected:

    AGameModeRoot();

    virtual void PostLogin(APlayerController * NewPlayer);
};


GameModeRoot.cpp



#include "GameModeRoot.h"

AGameModeRoot::AGameModeRoot()
{
    PlayerStateClass = APlayerStateBase::StaticClass();
}

void AGameModeRoot::PostLogin(APlayerController * NewPlayer)
{
    NewPlayer->GetPlayerState<APlayerStateBase>()->ClientGetCharacterDetails();
}


PlayerStateBase.h



#pragma once

#include "CoreMinimal.h"
#include "GameFramework/PlayerState.h"
#include "Variables/Structures.h"
#include "Net/UnrealNetwork.h"
#include "GameInstanceBase.h"
#include "PlayerStateBase.generated.h"

/**
 *
 */
UCLASS()
class FORUMPOST_API APlayerStateBase : public APlayerState
{
    GENERATED_BODY()

protected:

    virtual void GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const;

public:

    // Structure containing all the details of a character.
    UPROPERTY(Replicated, EditAnywhere, BlueprintReadWrite, Category = "Character Information")
    FFullCharacterDetails FullCharacterDetails;

    // Gets FullCharacterDetails from client's GameInstance
    UFUNCTION(Client, Reliable)
    void ClientGetCharacterDetails();

    // Sets FullCharacterDetails on Server to replicate to clients.
    UFUNCTION(Server, Reliable)
    void ServerSetCharacterDetails(FFullCharacterDetails InCharacterDetails);
};


PlayerStateBase.cpp




#include "PlayerStateBase.h"

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

    DOREPLIFETIME(APlayerStateBase, FullCharacterDetails);
}

void APlayerStateBase::ClientGetCharacterDetails_Implementation()
{
    ServerSetCharacterDetails( Cast<UGameInstanceBase>(GetGameInstance())->FullCharacterDetails );
}

void APlayerStateBase::ServerSetCharacterDetails_Implementation(FFullCharacterDetails InCharacterDetails)
{
    FullCharacterDetails = InCharacterDetails;
}


A bit gross, but I’m attempting to execute “ClientGetCharacterDetails” on the client, which calls ServerSetCharacterDetails with the intention of the server running it instead. I couldn’t make ClientGetCharacterDetails return the CharacterDetails struct because I’m using the Server specifier. I also can’t run the ClientGetCharacterDetails function on the server, since I need the CharacterDetails struct from the client’s GameInstance.

I am under the impression that perhaps “UFUNCTION(Server, Reliable)” and “UFUNCTION(Client, Reliable)” may not work exactly the same way as I think it does in BP. If someone could tell me what I’m missing, I’d really appreciate it!

It seems you are calling it in a wrong manner.

Make sure your calls goes from player controller to server and then you send this character structure values in that RPC. And then the Game mode class which is present only on server, updates this character structure value and in this manner it will get replicated to all the clients

I went from working with the player state, to working with the player controller. The character structure is brought from the client and set on the server which replicated to the client this time. Thank you for pointing me in that direction, I appreciate the help!

I believe now that the character information is present on the server, I can have the server work off of that and have cosmetic things work as intended.