RPC calls into UObjects losing Authority?

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?

Well, as usual I somehow make things more complicated than I need to. It turn out that inside one of my Widgets, instead of calling the Character’s MoveItemSameInventory() function, I was still calling the old MoveItem function inside my Inventory. That’s why it was only working on the client. :roll_eyes:

1 Like