TShock for Terraria

TShock for Terraria

Stuff

Get Started    Questions

Inventory Slot Indexes

By @ggggg243.

Accessing the Player's Inventory from Code

"Item" is the class that represents an item in Terraria. There is no "Inventory" class. The player's inventory is made up of arrays of items for the different sections.

NetItem is a class with helpful static constants to assist in accessing/editing the player's maze of item arrays. It may seem confusing, but once you've got the right functions in place it's a piece of cake.

Below is a table of said arrays.

Inventory section

Array name

Array length

Inventory -> Ammo -> Coins -> Cursor

TPlayer.inventory[]

NetItem.InventorySlots

Armor -> Accessories -> Vanity -> Social Accessories

TPlayer.armor[]

NetItem.ArmorSlots

Dyes: Social -> Accessories

TPlayer.dye[]

NetItem.DyeSlots

Equipment

TPlayer.miscEquip[]

NetItem.MiscEquipSlots

Dyes: Equipment

TPlayer.miscDye[]

NetItem.MiscDyeSlots

The length of all the arrays added together can be retrieved using NetItem.MaxInventory.

To access the player's inventory you must refer to the correct array using the correct index.

TSPlayer player = args.Player;
Item firstItemOnHotbar = player.TPlayer.inventory[0];
Item headArmor = player.TPlayer.armor[0];
Item headDye = player.TPlayer.dye[0];
Item petSlot = player.TPlayer.miscEquip[0];
Item petDye = player.TPlayer.miscDye[0];

Other slots that aren't in an array include:

Item trashItem = player.TPlayer.trashItem; //Item in the player's trash.
Chest piggyBank = player.TPlayer.bank; //Piggy bank
Chest safe = player.TPlayer.bank2; //Safe
Chest defenders_forge = player.TPlayer.bank3; //Defender's forge.

Editing the Player's Inventory from Code

🚧

Server-side characters only

This method only works when SSC is enabled on the server.

Editing the player's inventory from code is done by using all 5 arrays and the multiplayer packet. Below is an image showing all the indexes for each slot as if they were part of one big item array.

For most cases you might want to just update the inventory array (the main inventory of the player). This can be done simply by just using the TPlayer.inventory[] array and NetMessage as seen in the code example below:

🚧

Warning

This specific method will only work with the TPlayer.inventory[] array. Look further down for a method that works with ALL arrays.

player.TPlayer.inventory[0] = TShock.Utils.GetItemById(5); //Set the first slot of the inventory to a mushroom.

//Send the packet to update the player's inventory on the server
NetMessage.SendData((int)PacketTypes.PlayerSlot, -1, -1, plr.TPlayer.inventory[0].name, player.Index, 0, player.plr.TPlayer.inventory[0].prefix);
NetMessage.SendData((int)PacketTypes.PlayerSlot, player.Index, -1, player.TPlayer.inventory[0].name, player.Index, 0, player.TPlayer.inventory[0].prefix);

The best way to update the player's inventory (not just the main inventory) is to use the NetItem constants to check against the slot you want to change - using the Terraria screenshot above as a reference and the code below.

The code finds which array the slot chosen falls under, then updates that array with the item. This code example could easily be converted into a function if you made the arguments: the player, the item, and the slot.

TSPlayer player = args.Player; //The player.
int slot = 50; //The slot index (range: 0 - NetItem.MaxInventory)
int index; //A variable that will be used to find the index for the needed array (inventory[], armor[], dye[], etc.)
Item item = TShock.Utils.GetItemById(5); //The item (mushroom) we will set the slot to.

//Inventory slots
if (slot < NetItem.InventorySlots)
{
    index = slot;
    player.TPlayer.inventory[slot] = item;

    NetMessage.SendData((int)PacketTypes.PlayerSlot, -1, -1, player.TPlayer.inventory[index].name, player.Index, slot, player.TPlayer.inventory[index].prefix);
    NetMessage.SendData((int)PacketTypes.PlayerSlot, player.Index, -1, player.TPlayer.inventory[index].name, player.Index, slot, player.TPlayer.inventory[index].prefix);
}

//Armor & Accessory slots
else if (slot < NetItem.InventorySlots + NetItem.ArmorSlots)
{
    index = slot - NetItem.InventorySlots;
    player.TPlayer.armor[index] = item;

    NetMessage.SendData((int)PacketTypes.PlayerSlot, -1, -1, player.TPlayer.armor[index].name, player.Index, slot, player.TPlayer.armor[index].prefix);
    NetMessage.SendData((int)PacketTypes.PlayerSlot, player.Index, -1, player.TPlayer.armor[index].name, player.Index, slot, player.TPlayer.armor[index].prefix);
}

//Dye slots
else if (slot < NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots)
{
    index = slot - (NetItem.InventorySlots + NetItem.ArmorSlots);
    player.TPlayer.dye[index] = item;

    NetMessage.SendData((int)PacketTypes.PlayerSlot, -1, -1, player.TPlayer.dye[index].name, player.Index, slot, player.TPlayer.dye[index].prefix);
    NetMessage.SendData((int)PacketTypes.PlayerSlot, player.Index, -1, player.TPlayer.dye[index].name, player.Index, slot, player.TPlayer.dye[index].prefix);
}

//Misc Equipment slots
else if (slot < NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots)
{
    index = slot - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots);
    player.TPlayer.miscEquips[index] = item;

    NetMessage.SendData((int)PacketTypes.PlayerSlot, -1, -1, player.TPlayer.miscEquips[index].name, player.Index, slot, player.TPlayer.miscEquips[index].prefix);
    NetMessage.SendData((int)PacketTypes.PlayerSlot, player.Index, -1, player.TPlayer.miscEquips[index].name, player.Index, slot, player.TPlayer.miscEquips[index].prefix);
}

//Misc Dyes slots
else if (slot < NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots + NetItem.MiscDyeSlots)
{
    index = slot - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots);
    player.TPlayer.miscDyes[index] = item;

    NetMessage.SendData((int)PacketTypes.PlayerSlot, -1, -1, player.TPlayer.miscDyes[index].name, player.Index, slot, player.TPlayer.miscDyes[index].prefix);
    NetMessage.SendData((int)PacketTypes.PlayerSlot, player.Index, -1, player.TPlayer.miscDyes[index].name, player.Index, slot, player.TPlayer.miscDyes[index].prefix);
}

Helpful Code to Make Life Easier

The item prefix and stack can be changed before being sent to the player. This is accessed through Item.prefix and Item.stack.

The prefix is an integer value corresponding to a prefix (Legendary, Unreal, Mythical, etc). You can look in the database here on the documentation for a list of the prefixes with their IDs --- or below I have provided an Enum that you can implement in your code:

public enum ItemPrefix
{
    None, Large, Massive, Dangerous, Savage, Sharp, Pointy, Tiny, Terrible, Small, Dull, Unhappy, Bulky, Shameful, Heavy, Light, Sighted,
    Rapid, Hasty, Intimidating, Deadly, Staunch, Awful, Lethargic, Arkward, Powerful, Mystic, Adept, Masterful, Inept, Ignorant, Deranged, Intense, Taboo,
    Celestial, Furious, Keen, Superior, Forceful, Broken, Damaged, Shoddy, Quick, Deadly2, Agile, Nimble, Murderous, Slow, Sluggish, Lazy, Annoying, Nasty,
    Manic, Hurtful, Strong, Unpleasant, Weak, Ruthless, Frenzying, Godly, Demonic, Zealous, Hard, Guarding, Armored, Warding, Arcane, Precise, Lucky, Jagged,
    Spiked, Angry, Menacing, Brisk, Fleeting, Hasty2, Quick2, Wild, Rash, Intrepid, Violent, Legendary, Unreal, Mythical
};

//Example of use.
Item item = new Item();
item.prefix = (int)ItemPrefix.Unreal;

To make it a bit easier to find the slot you're after when accessing the player's inventory I have also created an Enum for each slot.

Keep in mind this cannot be used straight out of the box. You need to implement this into your code to be used. For example: Making a function that requires a slot and returns the item at that slot - using/altering the code from above. Then the Enum could be used as the argument for the function.

public enum ItemSlot
{
    InvRow1Slot1, InvRow1Slot2, InvRow1Slot3, InvRow1Slot4, InvRow1Slot5, InvRow1Slot6, InvRow1Slot7, InvRow1Slot8, InvRow1Slot9, InvRow1Slot10,
    InvRow2Slot1, InvRow2Slot2, InvRow2Slot3, InvRow2Slot4, InvRow2Slot5, InvRow2Slot6, InvRow2Slot7, InvRow2Slot8, InvRow2Slot9, InvRow2Slot10,
    InvRow3Slot1, InvRow3Slot2, InvRow3Slot3, InvRow3Slot4, InvRow3Slot5, InvRow3Slot6, InvRow3Slot7, InvRow3Slot8, InvRow3Slot9, InvRow3Slot10,
    InvRow4Slot1, InvRow4Slot2, InvRow4Slot3, InvRow4Slot4, InvRow4Slot5, InvRow4Slot6, InvRow4Slot7, InvRow4Slot8, InvRow4Slot9, InvRow4Slot10,
    InvRow5Slot1, InvRow5Slot2, InvRow5Slot3, InvRow5Slot4, InvRow5Slot5, InvRow5Slot6, InvRow5Slot7, InvRow5Slot8, InvRow5Slot9, InvRow5Slot10,
    CoinSlot1, CoinSlot2, CoinSlot3, CoinSlot4, AmmoSlot1, AmmoSlot2, AmmoSlot3, AmmoSlot4, HandSlot,
    ArmorHeadSlot, ArmorBodySlot, ArmorLeggingsSlot, AccessorySlot1, AccessorySlot2, AccessorySlot3, AccessorySlot4, AccessorySlot5, AccessorySlot6, UnknownSlot1,
    VanityHeadSlot, VanityBodySlot, VanityLeggingsSlot, SocialAccessorySlot1, SocialAccessorySlot2, SocialAccessorySlot3, SocialAccessorySlot4, SocialAccessorySlot5, SocialAccessorySlot6, UnknownSlot2,
    DyeHeadSlot, DyeBodySlot, DyeLeggingsSlot, DyeAccessorySlot1, DyeAccessorySlot2, DyeAccessorySlot3, DyeAccessorySlot4, DyeAccessorySlot5, DyeAccessorySlot6, Unknown3,
    EquipmentSlot1, EquipmentSlot2, EquipmentSlot3, EquipmentSlot4, EquipmentSlot5,
    DyeEquipmentSlot1, DyeEquipmentSlot2, DyeEquipmentSlot3, DyeEquipmentSlot4, DyeEquipmentSlot5
};

//Example of use.
player.TPlayer.inventory[(int)ItemSlot.Ammo1];
//This will not work for accessing armor[], dyes[], etc.

//Example of functions.
Item armorLeggings = GetItem((int)ItemSlot.ArmorLeggingsSlot);
UpdatePlayerInventorySlot(player, armorLeggings, (int)ItemSlot.InvRow3Slot6);

If you want to create your own inventories then apply them to a player (for a minigame or something) then you can use this code example to export your in-game inventory to the console as paste-able code.

The paste-able code will put the inventory into an array of items. You can then for-loop it and update a player's inventory with the method for editing player's inventories shown earlier.

TSPlayer TSPlayer = args.Player; //The player
string exportedCode = ""; //The variable that will hold the exported code
string arrayName = "itemArray"; //The DEFAULT name of the array that will contain the player's inventory.

if (args.Parameters.Count > 1)
{
    arrayName = args.Parameters[1];
}

exportedCode += "Item[] " + arrayName + " = new Item[NetItem.MaxInventory];";
for (int i = 0; i < NetItem.MaxInventory; ++i)
{
    Item item = GetItem(i, TSPlayer.TPlayer);

    if (item == null || item.netID == 0)
  {
    continue;
  }

    exportedCode += arrayName + "[" + i + "] = TShock.Utils.GetItemById(" + item.netID + ");";
    exportedCode += arrayName + "[" + i + "].prefix = " + item.prefix + ";";
    exportedCode += arrayName + "[" + i + "].stack = " + item.stack + ";";
  
  TSPlayer.Server.SendMessage(exportedCode, Color.Aqua);
}

Inventory Slot Indexes


Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.