JigSaw Multiplayer Component

There are two ways you can use Jigsaw Inventory System, the first option is to use the Multiplayer Component and let Jigsaw handle all of you inventory interactions, of course you will still be able to customize the layout of your inventory and handle equipment yourself.
The other options is to use Jigsaw widgets to build your own system, Jigsaw widgets provide many built in functions such as adding, removing items etc. the only difference is you have to control the flow of your inventor yourself and also handle replication.

Today we will take a look at how to utilize the power of Jigsaw Multiplayer Component to easily get your inventory up and running in few minutes, although this component does handle multiplayer it is absolutely fine to use it in a single player game.

We are going to set everything up from scratch to achieve something similar to what we have in the demo map, for that I will be working with an empty map and a character and player controller, these blueprints have nothing in them expect for movement logic in the character blueprint

Video Tutorial

Creating Jigsaw Equipment containers

The first thing we’re going to do is create a new widget blueprint, right click in your content browser and go to User Interface > Widget Blueprint, I’m going to name my widget BP_MainInventoryWidget inside this widget is where I’m going to add my main containers such as Weapon, Armor, pants etc these are your main equipment containers where you will be able to equip something.
Open BP_MainInventoryWidget and use the palette to add JSIContainers, this is what we will use as equipment slots for our inventory.

As you can see in this image I added 6 JSIContainers, and changed the following settings:
Container Type: EquipToSlot
SlotSize: It depends on the type of equipped items for example a helmet I would do 120×120 basically X=Y, for a rifle I would either make X bigger or Y bigger depending on the orientation of the equipped weapon.
Equipped Item Slot Size: this is by default 60×60 regardless of the container size, this indicates the slot size of non EquipTo containers.
Supported Item Types: this is where you indicate what item types the container will support, alternatively you can use the only support these IDs to specifically indicate what item IDs are supported.
Rotate Equipped Image: If you container size is oriented differently than the equipped item then go ahead and enable this option for the equipped item to be oriented to match the container shape.
Container Name: if you wish to display a container name in the top left then indicate it, you can see below I have HELMET set.
Feel free to play around with the rest of the settings, they’re generally based on your preference, and also make sure you name your JSIContainer properly so we can work with them easily in the Graph section of the widget.

Next search for DropItemBackGwidget in the palette and add it to your widget, I named mine JSI_DroppingItems as you can see in the above image, and also placed it right bellow the canvas panel so it’s below everything else and changed the anchor settings so it takes the entire widget space, this widget is used to handle dropping items when you drag and drop on an empty space.

Next let’s go to the graph section of our inventory widget, then click on Class Settings and add JSISpecialWidgetInterface to the interface section.

Once you do that you should now have a couple functions added to your inventory widgets and we need to handle some of them. First let’s handle GetListOfContainers this function is used to return all of your JSI containers, and the order here matters so remember it for later when we setup our Multiplayer Component.

Next function is Get JSIContainer By Player Slots this function is used to return a specific container reference by providing a player slot enum value. This is how my function looks like you can handle it however you want, we can use the GetEquippedItemRef function to return the equipped item JSI_Slot reference and of course return the main JSIContainer itself.

Finally we will handle Get Drop Widget, remember the DropItemBackGwidget we added earlier to handle dropping items ? we named it JSI_DroppingItems all we need to do here is return that reference as shown below.

Finally one last thing we need to do in our inventory widget is to show the content of equipped items, for example when we equip a backpack we need to see the content of that backpack somewhere and when the backpack is unequipped we need to remove that content, this let’s us access backpack items and move them around etc. Below is how I handled the backpack but it should be the same process for any container that can equip items with content such as pants with pockets etc

I used the Event On Initialized of our inventory widget in order to bind the event dispatcher, DropInfo_OnItemEquippedChange is an event dispatcher that gets called when an item is equipped or unequipped to a JSIContainer, as you can see below I used the backpack JSIContainer reference to bind this event, an easy trick to bind any event is to first drag a pin from JSIContainer reference and look for assign not bind, when you do assign it will create the bind and add the event automatically whereas bind will only add the bind and you will have to create the event yourself, so drag a pin from JSI Backpack in my case and look for Assign On Item Equipped Change and it should show up.

We will use the Equipped? input to show or remove the content of our backpack, SlotRef is the equipped/unequipped item JSI_Slot reference, in order to get the content of an item we can use GetContainerOneRef the return value is either a special container or a regular JSIContainer, we will talk about special container later, for now I added a vertical box to my widget (named Equip Content) and there I will add the content of my backpack when equipped, feel free to add this content however you want but in my case I created a BP_EquipToContent widget and setup the content, this widget can handle showing the weight and also collapse the content widget like in the demo map.

With this we’re pretty much done with our inventory widget, as you can see you can create any kind of inventory widget layout you like, add as many containers as you need and they all should work as intended and be replicated later using the multiplayer component.
Note: The main JSI containers we added don’t have to be EquipTo types they can be a regular inventory as well, in the demo our secure container is a regular container (5×2)

Adding & Handling The Multiplayer Component

In your character blueprint click on Add Component and add BP_JigMultiplayer, this is the component that will handle all of our inventory interactions such as equipping, removing and moving items across other containers, this component also exist in loot containers, AI, pickups etc this is how it’s able to communicate between multiple actors types.
Select the BP_JigMultiplayer and change the following settings:
MPContainerType: MainCharacter
InventoryWidgetClass: Select the inventory widget we just created
AllowDroppingItems: True
Container Settings: this is where we need to let the component know how our inventory widget looks like, since I created 6 JSIContainer I’m going to add 6 elements. In container name select a name this will be used later to know what container triggered a certain action, Colums and Rows if the JSIContainer is an EquipTo type then set columns and rows both -1 however if the container is an inventory type then indicate the columns and rows.
Note: The order here should be the same order you returned your containers when we handled the GetListOfContainers inside the inventory widget. Starting items we will discuss it later.

Also add JigContextMenuComp in order for the right click context menu to work properly.

In your character blueprint click on class settings and add these 3 interfaces.
BP Jig MPComponent: The Multiplayer component uses this interface to communicate actions that have happened in your inventory for example after equipping something from another container, a pickup is equipped etc, this interface function will be later be used in order to equip pickups and items to our character and similar functionalities.
BP Jig Character Interface: contains some functions that get executed when you save, load the game, interacting successfully with a pickup etc
BP MP Interact Interface: Mainly used for interacting with a player’s dead body in order to loot it, this same interface also exists in loot containers, AI, pickups etc basically anything we can interact with.
We will handle these functions as we go on.

Let’s talk about the important functions that you can utilize to handle equipment, the first thing we’ll handle is picking up items off the ground, like I’ve previously mentioned Pickups also implement the Interact interface so we can use the interface to communicate with pickups.
When it comes to pickups these are the 3 interfaces you can execute on a pickup, I’m not going to cover how to setup a trace or overlap in order to interact with pickups but you can watch my video tutorial to see how I did it, or check out the demo character.
On Begin Interact: this is used to show the name of the pickup, mainly used for visual purposes only.
On End Interact: Hides the name of the pickup.
Execute Interact: this is the important function, you need to use this when you actually want to attempt to pickup the item, for example after pressing F.
Jig Can Interact: checks if the item is something we can or able to interact with, this should also be used before begin interact.

When you call On Execute Interact on a pickup, the pickup class calls another interface on your character, that’s where you can handle the logic for picking up the item, mainly asking the server to do it.
The interface in your character class is called On Pickup Interact Executed basically the pickup is telling you to go ahead and pick me up.
If you open my Jig character in the demo and look inside this function you should be able to see how we handled it.

When we receive the pickup actor reference first using the BP Jig Multiplayer we call the JSI Try Equip to Main, this function will check if we can equip the pickup to one of our main containers such as helmet or backpack, this check is client side so we can only send a server request if we have an empty spot for that item. If the function returns a valid JSI container reference then we can equip the item but since this is server authoritative system we need to ask the server to do it, the server in the other hand we also check if it’s possible before committing to equipping the item, same goes for any operation.

If Not valid then it means either we don’t have an empty spot or the item cannot be equipped, in that case we can see if we can stack the item, if that fails finally we check if we can add the item in our inventory for example if we have a backpack then attempt to add it there.

The above function should let you equip and add items to your inventory, however equipping items visually is where you need to handle that yourself, for example equipping a rifle or helmet etc.

Jig MP On Item Equipped is the interface function that triggers in your character when you successfully equip an item, this function gets called after asking the server to equip a pickup, this function is executed server side and that’s where you decide what to do with the pickup reference, for example you could attach the pickup if it’s a rifle, or destroy it if it’s pants because pants are a cloth type you will likely simply set a skeletal mesh and no longer need the pickup version of pants around.

Here are 2 examples of how we can handle it, you can checkout the character demo to see how we handled everything. You can see here that we’re using the To Container Name to determine where this action happened, remember when we entered all of our containers in the Multiplayer component, those names help up know what equipment container we’re talking about, I simply used a switch on name node and if the container name is primary I know that a pickup was equipped to the primary slot, in that case I want to attach the pickup to my character, I first use Jig Set Can Interact to turn off interaction and physics and simply attach the pickup, I also set the owner so client and server events work inside this pickup which is likely a firearm pickup, finally I can get the pickup attachments using the GetListOfAttachments function from the Multiplayer component and run the Jig Attachment Installed interface on my weapon.

If the equipped item is pants for example I destroy the pickup version and simply set a skeletal mesh in my pants skeletal mesh component.
This is one of many ways you can handle this, feel free to handle it however you want and also replicate it, once again check out my demo character for how I did it.

In conclusion the chain looks like this: On Execute Interact > On Pickup Interact Executed > SERVER_RequestEquipActorToContainer > Jig MP On Item Equipped.

Next: Equipping an item from a loot container or from your own inventory (example Backpack)
In this case since the item you’re trying to equip is not a pickup another function is triggered in your character instead, the function name is Jig MP On Main Container Item Added this function triggers when you manually drag an item from some other container and drop it in your main equipment containers, or if the item is a starting item, this function will also trigger if you move an item from one main container to another for example switching primary to secondary or the opposite.

Let’s see how we handled this function, once again using the To Container Name to determine where this action happened, we also have From Main and this is where you know if you’re equipping an item from somewhere else or swapping your equipment (ex: Primary to secondary)
If the container is my primary then I know it’s a weapon so I have to spawn it and attach it, and of course the same thing as before, get the weapon attachments and install them visually.
If the equipped item is pants then no need to spawn anything I can simply set some skeletal mesh.

Note: In order to know what socket to use and what skeletal mesh to equip we use a data table called DT_EquipmentMeshData if you look at the character demo you can see how it’s used. Also in the demo character we store the info of what is currently equipped which is needed to play different animation or modify your equipment such as changing durability of items etc

We also have a function that triggers when you unequip something to another inventory, for example unequipping your pants or weapon to a loot container or to your own backpack, the function is called Jig MP On Main Container Item Removed.
As you can see here if the container name is PRIMARY I know I have a weapon equipped and I have its reference saved so I simply destroy the actor, if the container is pants then I set the pants skeletal mesh to nothing.

Next: Dropping items
Jig MP On Request Drop Item is the interface function that triggers when you want to drop an equipped item or from your inventory.
If Container Name is None then that means you want to drop an item from non main containers for example from inside a backpack container.
In this example you can see that because our primary is a weapon that still exists in the world we simply detach it and drop it in from of the character, we also enable interaction and physics back.
If the item is pants then we clear the skeletal mesh component and spawn the pants pickup version in front of the character.
Note: Be sure to return the reference of the dropped item so the Multiplayer component can transfer the content of that item to it, for example dropping a backpack full of items or weapon with attachments.

Installing and removing attachments
Two functions handle this operation, Jig MP On Pickup Item Added/Removed these 2 functions trigger when installing or removing an attachment for example installing a sight on a rifle, this is not limited to firearm only as long as the pickup reference is still alive adding any items to the pickup will trigger these functions, take for example a helmet with some extra attachment slots for night vision.

Consuming/Using items
Jig MP On Item Consumed is triggered when you consume an item successfully, here’s an example of how we can request to consume an item.
Consumed items are removed from the inventory or count is updated.
You can also consume items from the right click context menu.

Jig MP On Item Added to Inventory is an interface function that triggers when an item is added to your inventory, for example from a loot container to your backpack inventory.

Interacting with loot containers, crafting station and dead bodies and similar
These actors have their own inventory widget to be added, for example a loot container displays an inventory to be looted, we will see how to setup these actors later for now there are 2 interface functions inside our character we need to handle.
Request Server Data is an interface function that gets called when you interact with something like a loot container, this function should be handled this way, basically we’re asking for the data of that loot container, the loot container cannot execute server events that’s why our character has to do it.

Add Jig Widget to Content is an interface function that triggers after interacting with something like a loot container, in this function is where you display the content of that loot container.
This is how it’s handled in the demo character, basically we need to add this widget somewhere in our inventory widget or add it wherever you want,

On Interact Actor Over Distance this is an interface function that triggers when you walk too far from loot container, crafting station etc, basically since you’re still able to move while looting some container if you walk too far we remove the loot container widget, the function to check the distance is handled inside the actor you’re interacting with, check out the Interaction graph inside loot container, AI etc

Handling looting a dead player
When the player is dead 2 things need to be changed, the container type of the dead player goes from MainCharacter to LootContainer as shown bellow, and also a new widget class should be assigned to the Multiplayer component, you can use a multicast or rep notify to set that widget class for all players, keep in mind that we’re updating the dead player character BP and not our player.
The widget class should be BP Dead Player by default, but you should create another inventory widget and handle it the same way you handled your own inventory widget, the only difference is that this widget should be smaller and squeezed so it’s added as a loot container.
The last thing is making sure the Jig Can Interact is set to true so other players can loot this dead body, this can be controlled by health value or similar.

With all of this you’re pretty much done setting up everything, if I have missed something or you have any questions don’t hesitate to contact me.

In 4.27+ we have some new features you can use to make your life easier

Setting up loot containers

First thing you need to do is make a child class of BP_MPLootContainer this also has a Multiplayer component added by default and it also manages its inventory, the same thing apply to crafting station, pickups etc
The same way we setup our character is the same process essentially though less things to do.
First create a new widget which will contain however many JSI Containers you need, in this example I have 2 inventory type containers.

The same way as before you also need to add the JSI Special Widget Interface and we only need to handle this function the GetListOfContainers, in this function we return all of our JSI containers, once again the order here matters later when we setup our containers in the multiplayer component so it should be the same order.

Now we go back to our loot container and select the Multiplayer component.
Container type: LootContainer
Container Settings: Here I indicated both my containers and their dimensions, we’ll see later container items.
InventoryWidgetClass: is the widget hat I just created for this loot container.

In order to add items to this loot container we can expand the container settings and add new starting items in the specific container, for example in the 6×6 container I want to add a rifle called ModularRifle.
You can also indicate the spawn chance, the InContainerItems are another layer where you indicate what’s inside this item for example items inside a backpack or attachments.

In this example we will add some attachments by default to our rifle, we can simply add new items to the InContainerItems as you can see here we have Stock, Mag, and ammo added, in order to have ammo in a mag the ammo needs to be added after the mag and the type should be ammunition.

The AddToContainerIndex is the index of the container, you can determine this value by opening the special container of the rifle and look in the GetListOfContainers function and see what is the index of that container.
For example opening our modular rifle special container you can see that Mag is 0, Sight is 1 etc that’s the index.
Later we will see how to add special containers.

Setting up a Crafting Station

You can create a child class of BP_MPCraftingStation theres’s already a widget class available by default so all you need to do is indicate the items to craft.
Note: No need to indicate starting items.

Setting up Vendors

You can create a child class out of BP_MPVendor and simply indicate your starting items, it is the same concept as loot container, you can indicate the price override, if left as -1 then the price will be taken from the data table.

Setting Up AI

AI is pretty much the same thing when it comes to its inventory when looted, you can set it up the same way.

When the AI is dead we can update the ammo in its gun for cases where you want the weapon to reflect how many bullets the AI shot, for that open the main AI class checkout the event any damage for when the AI is dead, and also the begin play.

Pickups & Special Containers

Let’s take a look at the Modular rifle pickup and how it’s setup.
A special container is a widget blueprint containing multiple JSI Containers and is assigned to a JSI item, you can create a new special container or duplicate an existing one, as you can see here we have multiple containers added and we can specify the supported types and or only support specific IDs.

Once you add your containers go to the graph section and add the JSI Special Widget Interface and return all your containers, the InContainerIndex used in the multiplayer component is the array index so perhaps you want to maintain a certain practice such as mag is always index 0 so you want to always return it first.

You can open SC_Attachment widget and see how we handled attachments being installed and removed using the Equip change event dispatcher.
Once you have created your special container you can indicate it in the data table
Inside DataTable_Weapons you can check the ModularRifle and here is where we indicate our special container, there are 3 important options we need to modify.
IsContainer? must be set to true
SpecialContainersDimensions: This is where we indicate the special container configuration, this is mainly used server side, in SC_attachment we have 7 containers and as you can see below we added 7 elements and because all of our 7 containers are of type EquipTo we set the X/Y dimensions to -1 which means EquipTo.
Special container Widget: is the widget containing the JSI containers, in our case it’s SC_Attachments.

Take a look at how the backpack special container is setup, because the type of containers is not EquipTo we need to indicate the columns and rows.

Let’s take a Magazine for example, a mag doesn’t need multiple containers therefore we don’t need to create a special container, we can simply indicate the dimensions here and leave the SpecialContainersDimensions empty, this will make it so a single container is created and assigned by default from JSI_Slot so you don’t have to create anything for it.
Since it’s not a special container you will have to indicate supported items and container only supported IDs in the data table itself.

Add Items By Default to Pickups

Let’s start by having a magazine pickup have ammo in it by default.
We can simply access the Multiplayer component either inside the blueprint or in the details panel while the pickup is in the ground by selecting it in the map, if you chose the latter then the blueprint will not be modified, alternatively you can create child classes with their own configuration which is my favorite method.
Below you can see how we can simply add a starting item and we can even indicate the spawn chance and a random value between min and max.
The same thing for any similar pickup like a backpack.

For firearms the process is slightly different just so we can make things easier, in this case you don’t need to modify the multiplayer component instead click on Class Default and you should see a Default attachments settings, in there you can indicate your default attachments and once again AddToContainerIndex is the index of the returned container inside the special container in the GetListOfContainers function.
You also have a specific Default ammo in Mag if the gun has a mag.
supported Mag/Ammo used for reloading.

Items Snapshots and Inspecting

In order to setup snapshots or inspecting you need to add the item in DT_ItemInspector data table, ItemID should be the same from the pickups data table and you can indicate static or skeletal mesh and the location/rotation/FOV settings, to configure this properly after adding the itemID and selecting a mesh you can play and inspect the item then toggle the debug and try some values until you’re happy, note them down and go back to the data table and enter them.

If you want the inventory image to be used from the snapshot then make sure UseAsInventory is true if not only inspecting will be considered.
Note: I would advice leaving InspectLoc X value to 0 so orbiting around the item is smooth, you can change FOV instead.
Share Render Target: This is an optimization feature, basically if an item is not dynamic such as a backpack you can use the same render target for all backpacks, whereas a rifle is dynamic because multiple similar rifles can have different attachments in that case each one needs its own render target.

You can indicate different values specific to action bars since action bar container size can be different, however there’s a function that copies the render target of the mirrored item and adjusts it accordingly.
If I have a rifle equipped why would I generate a new render target and capture a new snapshot for the action bar when I can simply copy what my equipped rifle has and adjust it for the action bar.

In order to do that you need to open your action bar which in my case has JSIContainers, select all your JSIContainer action bars and in the permissions section disable capturing snapshots, this will make it so there will be no snapshot taken for the equipped item because we intend to copy from the main equipped item.

And here’s an example, I get my primary main JSI container and bind the equipped change event so I get notified when my main primary is equipped and if it’s the case I also equip my action bar container, then call the Adapt Image To Actionbar function which will take the render target of the equipped item and use it as well with some image adjustment but it does not affect the render target state, because both items share the same render target any attachments installed on my weapon will also show in the action bar.

Another setting for adjusting snapshots for different container sizes is in the permissions as well, for example a mag is 1×2 and it should look fine inside a normal inventory however if we equip it to a 1×1 container then the image will look weird.

Here’s the option I’m talking about after selection a JSIContainer find the permissions section

This is how it looks in a regular inventory, no issues.

This is how it looks with it turned OFF

and this how it looks when it’s turned ON, much better right ? No need to create another render target and capture another snap, simply apply some widget magic to the existing image.

More will come, for now if you have any questions contact me at trafalgamer@gmail.com