Only Replicate When Requested? (C++)

Is there a way to replicate an array only when a player opens an inventory? I don’t think it’s necessary to replicate every inventory to every client all the time; currently how my system is working. Basically, the client shouldn’t know or care what a storage box or loot crate has until the player accesses its inventory.

Relevancy already does this to some degree, ie if the player is too far away it wont replicate.

Thanks, Auran13. I’ve been playing with the IsNetRelevantFor function with some success. It seems once I return True from the IsNetRelevantFor override for any PlayerController it’s stuck in replication and I can’t seem to stop it.

I’ve tested this running as a client in PIE. The server would add 14,000 items to the array. I’d have the client check and see 0, which I expected since I’m not replicating. Then I’d return True from the IsNetRelevantFor override and check again to see 14,000. So far so good. I’d then return False from IsNetRelevantFor. I’d have the server then add another 500 and while still returning False check again and now see 14,500, which I wasn’t expecting as the inventory shouldn’t, or so I thought, be replicating.

The reason for so many elements in an array is because players can place down storage boxes, workbenches, drop bags, etc, and store various resources. The problem is, with everything replicating I often run into “Attempted to send bunch exceeding max allowed size”. This doesn’t strictly happen with one massive inventory. This also happens if too many smaller inventories are replicating to a client, hence the need to only replicate on request.

The code is nothing fancy. Regarding DOREPLIFETIME, I’ve tried both and got the same result.

// UInventoryComponent : ActorComponent
//H
UPROPERTY(Replicated) TArray<UWorldItem*> Collection;


//CPP
void UInventoryComponent::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);
	//DOREPLIFETIME(UInventoryComponent, Collection);
	DOREPLIFETIME_CONDITION(UInventoryComponent, Collection, COND_Custom);
}



// AStorageActor : AActor
//H
UPROPERTY(Replicated) UInventoryComponent* Inventory;


//CPP
void AStorageActor::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);
	//DOREPLIFETIME(AStorageActor, Inventory);
	DOREPLIFETIME_CONDITION(AStorageActor, Inventory, COND_Custom);
}

bool AStorageActor::IsNetRelevantFor(const AActor* RealViewer, const AActor* ViewTarget, const FVector& SrcLocation) const
{
	if (const ASonaController* PlayerController = Cast<ASonaController>(RealViewer))
		return AccessedBy.Contains(PlayerController);
	return false;
}

void AStorageActor::ToggleInventory(ASonaController* PlayerController)
{
	if(HasAuthority()) Internal_ToggleInventory(PlayerController);
	else Server_ToggleInventory(PlayerController);
}

void AStorageActor::Server_ToggleInventory_Implementation(ASonaController* PlayerController)
{
	Internal_ToggleInventory(PlayerController);
}

void AStorageActor::Internal_ToggleInventory(ASonaController* PlayerController)
{
	if(PlayerController)
	{
		if(AccessedBy.Contains(PlayerController))
			AccessedBy.Remove(PlayerController);
		else AccessedBy.AddUnique(PlayerController);

		ForceNetUpdate();
	}
}

AStorageActor replication details

It will probably suit you DOREPLIFETIME_ACTIVE_OVERRIDE

The second option is to send an RPC event request to the server and receive the result via a client event.
In this case, the variable should not be replicated on its own.

Thanks for the guidance. I may have been over complicating things a bit. After a little more tinkering and testing I believe I have it working. I’m just using DOREPLIFETIME for both the storage actor and inventory component. In my character class I have a null inventory component pointer marked as replicated, also using DOREPLIFETIME. When I need to access a specific inventory, I’ll call a server RPC from the character to set the inventory pointer I want to access. After that, client side sees all the items. I also don’t get that “Attempted to send bunch exceeding max allowed size” error running the same 14,000 item test, even with switching to another inventory.