Download

Inventory Replication optimization question regarding RPCs

I’ve built a plugin which, among other things, contains an inventory system. It’s component based and (so far) networked by using NetMulticast RPCs that update clients when something changes in the inventory so that it stays current on all clients as much as possible, and allows multiple people interacting with an inventory at the same time for i.e. chests, boxes, what have you.

This is all fine and splendid but I can’t figure out how to send the initial update. I can have a client request a broadcast update when they open the inventory the first time but of course that means that all clients get updated with the entire inventory of the object when that happens. This can potentially get really messy if you i.e. have 9 clients and a 10th connects and opens the box, and all those 9 get the update etc.

Of course I can’t call client functions on the box inventory because nobody owns it and client RPCs only work on client-owned objects. I could have functions in the player controller, character, etc that asks for an updated inventory when opening something that is empty but I would prefer to have it decoupled from these systems so that users are free to use whichever controllers and characters that they like. I would also prefer to use a broadcast approach so that inventories are updated across all players as needed.

The inventory is stored in a TMap<FGuid, FInventorySlot> to avoid having to search an array every time something happens.

So here we are between a rock and a hard place. Have I missed something? Any suggestions would be helpful.

Edit:

I am quite happy to do this on a per-client basis too I suppose if I can somehow get around the problem of having to have actions for this in the controller. I don’t think there’s ever going to be any way around this of course since you can’t call RPCs on objects you don’t own. Could also change the NetOwner of the parent object of course, when the inventory is being interacted with.

This is where a FastArray would be beneficial. The actor only has to update when something is removed. Fast array sends client side notification when an item in that array changes. As you can’t replicate a TMap you should use a FastArray. As is used in games like Fortnite, and many other big games. I find Fast Arrays to be the best for this kind of thing. Open NetSerialization.h for an example on how a FastArray works.

Thanks for your help! Sorry it took a while to reply, been a hectic week.

I ended up doing something similar on my own with a system that figures out delta changes to an acceleration map I use for the inventory and then sends the updates to all clients that have asked to receive them rather than everyone. In the end I figured this would be a better option than having everything synced all the time. Clients can subscribe to getting updates for an inventory until they request to unsubscribe. This lets you keep your own inventory synced all the time, for example, while chests and stuff only sync while you’re looking in them.