Each time I start to think I finally have UE Networking figured out, I’m swiftly reminded otherwise.
To keep things simple, I have a replicated actor that contains an inventory system that is based on a UObject. In the BeginPlay() method of the Actor, I create the InventorySystem inside of HasAuthority()
void ALootableActor::BeginPlay()
{
Super::BeginPlay();
if (HasAuthority() && LootTable)
{
// Test inventory
Inventory = NewObject<UInventorySystem>(this);
Inventory->InitializeInventory(EInventoryType::IT_Backpack_00);
}
The above code creates the inventory and replicates it correctly to all other clients.
Inside of a Widget Blueprint, when the user moves an item within the same inventory, I call my Character’s MoveItemSameInventory()
function. I do this because I have read that I am unable to use RPC from inside UObjects, so I do it here, ensure I am on the server, then call into my UInventorySystem::MoveItem()
void ANoNameCharacter::MoveItemSameInventory(UItem* SourceItem, UItem* EmptyItem)
{
// running here because we can't call rpc from uobject (inventorysystem)
if(!HasAuthority() && SourceItem && EmptyItem)
{
ServerMoveItemSameInventory(SourceItem, EmptyItem);
}
if(HasAuthority() && SourceItem && EmptyItem)
{
SourceItem->OwningInventory->MoveItem(SourceItem, EmptyItem);
}
}
However, inventory changes made within UInventorySystem::MoveItem()
are only modified for the current Client.
For debugging within my UInventorySystem::MoveItem()
I traverse up the tree to find the Owning Actor so that I can add logging statements to see if I am on the Client or Server. It is ALWAYS reporting back as if the code is running on the client - even though I am clearly calling into the function from the Server on my Character.
void UInventorySystem::MoveItem(UItem* Item, UItem* EmptyItem)
{
// should only be called from server
if(GetOwner()->HasAuthority())
{
UE_LOG(LogTemp, Warning, TEXT("SERVER"))
// Never makes it here
}
else
{
UE_LOG(LogTemp, Warning, TEXT("CLIENT"))
// Always makes it here
}
// other inventory logic here that needs to be run with Authority...
}
Notice that GetOwner()
inside of my UObject above is created by me. It simply finds the outer Actor and returns it. I have confirmed this is the owning actor I was expecting to see.
What am I missing?