How to manipulate a player's inventory?

I am creating a lobby plugin for my personal server and I want to learn how to manipulate a player’s inventory. There would be menus for customization and other purposes. I have a instance of ItemStackBuilder, but I do not know how to use it. I also have a instance of the players inventory in the first snippet. Let’s say I want a door, named “Return to hub” in the 9th slot of the player. How would I do this? I am quite new to Sponge plugin creation, and Sponge Documenters, you should add the Item api to the SpongeDocs. I would like to thank the Sponge community, especially @TBotV63 and @FerusGrim and @BitByte for answering COUNTLESS questions that I asked.

 @Subscribe
    public void onPlayerJoin(PlayerJoinEvent event) {
        Player player = event.getPlayer();
        Location location = player.getLocation();
        World world = player.getWorld();
        Inventory inventory = player.getInventory();
        setWelcomeMessage(event, of(player.getName() + " has joined this server!").builder().color(TextColors.GREEN).build(), createWW1Prefix());
    }
@Inject
    private Game game;

    private Server server;
    private Plugin plugin;

    protected GameRegistry registry = game.getRegistry();
    protected CommandService cmdService = game.getCommandDispatcher();
    protected ItemStackBuilder itemBuilder = registry.getItemBuilder();
1 Like

You’ll want to take a look at @mumfrey’s great pull request for the inventory API

It’s an incredibly large thing to add to the documentation but it’s on the TODO

I’m not completely sure on how to use the inventory API myself, but I think you do something like this:
ItemStack itemStack = player.getInventory().query(Hotbar.class).query(new SlotIndex(8)).peek().get();

ItemStackBuilder is just a builder, see Builder Pattern:

To make an ItemStack of 64 diamonds, you do
ItemStack diamondStack = builder.itemType(ItemTypes.DIAMOND).quantity(64).build();

To do something when a player uses an item, you create an event handler for the appropriate event.
I think the event is PlayerInteractEvent but I’m not completely sure on that.

Hope this helps

1 Like

So I created my item, exitDoor.

ItemStack exitDoor = itemBuilder.itemType(ItemTypes.WOODEN_DOOR).quantity(1).build();

I need to set the name of my item as Exit to Hub and place it in slot #8 of the HotBar. How do I do that. I tried reading the source code, with no success. How does the code you suggested work together with this?

I dont think ItemMeta is implemented yet.

1 Like

As @DotDash has pointed out, it’s not currently in the API.
@gabizou has created a major pull request for redesigning the Item API

The actual item display data is in the proposal, see DisplayNameData

1 Like

Well, hopefully @gabizou’s pull request will be implemented. For now, I will pause this part and focus on other aspects instead.

Update: @gabizou’s pull request has been had and accepted.

Mind you that the API doesn’t have implementation… yet

1 Like

?? I thought your pull request was accepted!

Ok, so I created two items. I want playerStatsAndAcheivements to be a custom player head. How would I do this? Also, @gabizou, how does your implementation fit in with Hotbar.class? I want my items to be specific slots of the player.

ItemStack exitDoor = itemBuilder.itemType(ItemTypes.WOODEN_DOOR).quantity(1).build();
        DisplayNameData exitDoorDisp = exitDoor.getData(DisplayNameData.class).get();
        exitDoorDisp.setDisplayName(Messages.builder("Exit to Hub").color(TextColors.DARK_BLUE).build());

        ItemStack playerStatsAndAcheivements = itemBuilder.itemType(ItemTypes.SKULL).quantity(1).build();
        DisplayNameData playerStatsAndAcheivementsDisp = playerStatsAndAcheivements.getData(DisplayNameData.class).get();
        playerStatsAndAcheivementsDisp.setDisplayName(Messages.of(player.getName() + " ").builder().color(TextColors.RED)
                .append(Messages.builder("stats").color(TextColors.DARK_PURPLE)
                        .build())
                .build());


        exitDoor.setItemData(exitDoorDisp);
        playerStatsAndAcheivements.setItemData(playerStatsAndAcheivementsDisp);

I would tell you how but that wouldn’t be providing you with a service. You’ll have to read the documentation and/or the javadocs.

How would I query for the first open slot in a player’s inventory? I assume I need to query for a null ItemStack or something like that, but I have had no luck thus far. I’m thinking something like:?

Inventory firstSlot = p.getInventory().query(Hotbar.class).query(NULL);

@soccer66

p.getInventory().query(Hotbar.class).query(EmptyInventory.class)

How would I get every item in a player’s inventory in a List (or another way to do a for loop) and edit them?

I would also like to know this

@Bammerbom @TrenTech

// All possible slots in the player's inventory (includes armor etc)
Iterable<Slot> slotIter = player.getInventory().slots();

for (Slot slot : slotIter) {
    // Do something with the slot here. Random example:
    if (slot.isEmpty()) {
        slot.set(someItemStack);
   } else {
        slot.clear();
    }
}
1 Like

OK, next question is how can I turn Iterable<Slot> back to an Inventory object, if that makes sense?

Using CustomInventory, here’s what I think you can do

Iterable<Slot> slots = functionToGetSlots();
List<Slot> slotsList = Lists.newArrayList(slots);

CustomInventory inventory = Inventories.customInventoryBuilder()
        .name(someName)
        .size(slotsList.size())
        .build();

for (int i = 0, len = slotsList.size(); i < len; i++) {
    Optional<ItemStack> optStack = slotsList.get(i).peek();
    if (optStack.isPresent()) {
        inventory.set(new SlotIndex(i), optStack.get());
    }
}

Also, looking at my previous post to get all slots, I’m not sure if slots() will return all slots in sub inventories. If not, here’s a recursive function to get all slots:


private Iterable<Slot> getSlots(Inventory inventory) {
    if (inventory instanceof Slot) {
        return Collections.emptyList();
    }
    Iterable<Slot> slots = inventory.slots();
    for (Inventory subInventory : inventory) {
        Iterables.concat(slots, getSlots(subInventory));
    }
    return slots;
}