mojira.dev
MC-187281

Function reward removing the item an advancement detected creates a ghost item

The bug

When a function reward of an advancement that triggers on inventory_changed removes the item, the advancement detected, the item is left behind has a ghost item on the client.
Presumably, that happens because of when in the tick the advancement triggers. It is likely, that the advancement triggers before the item is being send to the client, and then the inventory updates are send in the wrong order.

How to reproduce

  1. Download the example datapack:

[media]
  1. Put the datapack into your world's datapack directory

  2. Give yourself a vine

  3. Make sure you are in survival mode (in creative the ghost item will behave like a regular item)
    → ❌ You now have a ghost vine in your inventory

Linked issues

Attachments

Comments 12

I think this is the same as MC-118841, which was dubiously merged into MC-29318

Yeah, at the time that seemed to be the likely cause, I guess.

Oh actually, you found a different one. I only saw MC-135205, which was resolved as dupe of MC-41113, when I searched.

Maybe this is related to MC-146043 ?

Confirmed in 1.16 Release Candidate 1.

2 more comments

I experience the same Issue using the same advancement trigger and a reward in which the item gets switched from offhand to mainhand with the new /item command.

[media]

It seems this happens with anything in the reward block that changes the players inventory. I haven't found a workaround.

 

{
  "criteria": {
    "crafting_table": {
      "trigger": "minecraft:inventory_changed",
      "conditions": {
        "items": [
          {
            "item": "minecraft:crafting_table"
          }
        ]
      }
    }
  },
  "requirements": [
    [
      "crafting_table"
    ]
  ],
  "rewards": {
    "loot": [
      "test:diamond"
    ]
  }
}
{
  "type": "minecraft:advancement_reward",
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:diamond"
        }
      ]
    }
  ]
}

 

 

When running /give @s vine in survival with the datapack enabled the item is instantly removed without leaving behind a ghost item. Has anyone else been able to reproduce this in 1.18?

I've been testing this in 1.18.2 and I was not able to replicate this behavior. The vine disappears and there is no ghost item.

HOWEVER, I have still noticed some interesting behavior when using rewarded functions and moving items within the inventory.

My testing setup:

1. Place a shulker box in a the world at 0 -61 0 and replace the player's first inventory slot with an item (in my example it's a diamond).

2. Create an inventory_changed advancement which rewards a function which copies the player's hotbar into a shulker box:

say inventory changed
data modify block 0 -61 0 Items set from entity @s Inventory

3. Now move the diamond in the first hotbar slot to the second hotbar slot (open inventory GUI, hover over second slot, and press 1 button).

This should cause the diamond to move to the second slot and the "inventory changed" message displays in chat.

However, when you open the shulker box there will be two diamonds in the inventory spots corresponding to where the item started and where it ended. This turns out to be an intermediate inventory state that is normally not visible to the player.

If we repeat the same steps previously but this time add a command to our function file which removes the inventory_change advancement:

advancement revoke @s only [advancement]

you will notice the "inventory changed" message prints twice and the shulker inventory should accurately reflect the player's inventory.

This demonstrates that minecraft handles inventory changes in two steps:

1. The game copies the item from the initial slot to the destination slot while holding any item in the destination slot in some storage space. This change is reflected in the first inventory_changed advancement granted.

2. The game then takes the item in storage space and places it into the initial slot. This change is reflected in the second inventory_changed advancement granted.

The inventory_changed advancement returns the function so fast it is able to resolve both of these steps in-game. I am unsure whether this behavior is intended by the devs or not, hence why I am leaving this as a comment.

If you wish to avoid this behavior, one can simply remove the function reward from the advancement and run a command as every player with the advancement in a tick function:

execute as @a[advancements={[advancement]=true}] run [function]

I'd suggest making a report for that; it doesn't seem intended for that to happen.

NeunEinser

(Unassigned)

Confirmed

Platform

Normal

Advancements, Commands, Data Packs, Networking

20w22a, 1.16 Pre-release 1, 1.16 Pre-release 2, 1.16 Release Candidate 1, 1.16, ..., 1.16.5, 1.20.1, 23w40a, 1.20.4, 1.20.6

Retrieved