#How do I add a custom NBT tag to an item?

61 messages · Page 1 of 1 (latest)

peak aspen
#

I basically want that when the custom item gets used on a mob (or an entity), that entity is copied in some form in the item, and when the item gets used again (maybe while crouching, as an idea), an identical copy of the entity is spawned. Is there any way to do this?

misty helm
#

In what version? From 1.21 onward, nbt tags are no longer encouraged

#

But yes, you can. You can save the entities type and it's custom nbt to a component of your making and then simply create a new entity of the same type, initialize it with the saved data and call world#spawnEntity

peak aspen
misty helm
misty helm
peak aspen
misty helm
peak aspen
misty helm
peak aspen
misty helm
#

In that case though, you just need an item with useOnEntity and useOnBlock methods

misty helm
peak aspen
misty helm
#

You will create a new nbt compound, use the writeNBT method on the entity to save its data, remove it using remove and save the compound to your item

peak aspen
misty helm
misty helm
peak aspen
#

ok so a map of strings, which I guess are the nbt identifiers, and NbtElements, which are ?

misty helm
#

It should be a parameterless constructor

peak aspen
#

and I can just put whatever in it with WriteNBT?

misty helm
#

You can use the methods on the compound to save arbitrary namespaced data

peak aspen
#

oooh ok I'm going to try

#

ok I have NbtCompound.putWhatever()

misty helm
#

EntityType#loadEntityWithPassengers may be helpful to you as well

peak aspen
#
@Override
    public ActionResult useOnEntity(ItemStack stack, PlayerEntity player, LivingEntity entity, Hand hand) {
        if (!player.getWorld().isClient()) {
            // Get or create NBT for the item
            NbtCompound itemNbt = stack.getOrCreateNbt();

            // Save the entity data into the NBT
            NbtCompound entityData = new NbtCompound();
            entity.saveNbt(entityData);  // Serialize the entity to NBT

            // Save entity's class name to reconstruct the exact entity later
            entityData.putString("EntityType", EntityType.getId(entity.getType()).toString());

            // Store the entity's NBT data inside the item's NBT under the "StoredEntity" key
            itemNbt.put("StoredEntity", entityData);

            // Apply the updated NBT back to the item
            stack.setNbt(itemNbt);

            // Feedback to the player
            player.sendMessage(Text.of("Entity data stored"), true);

            return ActionResult.SUCCESS;
        }
        return ActionResult.PASS;
    }

I'm really not getting the hang of this... this doesn't store any nbt in the item

misty helm
misty helm
misty helm
peak aspen
misty helm
#

But write nbt tells the entity to save its data to the nbt. Without write nbt, you are just saving an empty compound without the entity data

#

SetNBT just saves the nbt you have to the itemstack

peak aspen
#

entity.saveNbt(entityData); // Serialize the entity to NBT

so here I should use writeNbt instead?

misty helm
#

You have most of it right, you're just not quite there

peak aspen
#
if (!player.getWorld().isClient()) {
            // Get or create NBT for the item
            NbtCompound itemNbt = stack.getOrCreateNbt();

            // Save the entity data into the NBT
            NbtCompound entityData = new NbtCompound();

            //added this
            entity.writeNbt(entityData);
            entity.saveNbt(entityData);  // Serialize the entity to NBT

            // Save entity's class name to reconstruct the exact entity later
            entityData.putString("EntityType", EntityType.getId(entity.getType()).toString());

            // Store the entity's NBT data inside the item's NBT under the "StoredEntity" key
            itemNbt.put("StoredEntity", entityData);

            
            

            // Apply the updated NBT back to the item
            stack.setNbt(itemNbt);

            // Feedback to the player
            player.sendMessage(Text.of("Entity data stored"), true);
            
        }
        return ActionResult.SUCCESS;```
like this?
misty helm
#

The saveNbt call should not be nessesary, writeNbt does it if needed.

misty helm
#

But that looks good

peak aspen
#

Ok, so I think I get it in this case, but what do all those functions actually do? like write put save set? is it all in the docs?

misty helm
#

The fabric + yarn javadocs can also be a good resource

peak aspen
#

nope, still doesn't work...

@Override
    public ActionResult useOnEntity(ItemStack stack, PlayerEntity player, LivingEntity entity, Hand hand) {
        if (!player.getWorld().isClient()) {
            // Get or create NBT for the item
            NbtCompound itemNbt = stack.getOrCreateNbt();

            // Save the entity data into the NBT
            NbtCompound entityData = new NbtCompound();

            //added this
            entity.writeNbt(entityData);
            entity.saveNbt(entityData);  // Serialize the entity to NBT

            // Save entity's class name to reconstruct the exact entity later
            entityData.putString("EntityType", EntityType.getId(entity.getType()).toString());

            // Store the entity's NBT data inside the item's NBT under the "StoredEntity" key
            itemNbt.put("StoredEntity", entityData);

            // Apply the updated NBT back to the item
            stack.setNbt(itemNbt);

            // Feedback to the player
            player.sendMessage(Text.of("Entity data stored"), true);

        }
        return ActionResult.SUCCESS;
    }

    

reposting the full code for clarity

peak aspen
misty helm
peak aspen
misty helm
peak aspen
# misty helm You may need to set the item in the players hand, it's been a bug in Minecraft f...

ok, it stores the nbt now (thanks), but now there's an issue with spawning the clone

[Server thread/WARN] (Minecraft) UUID of added entity already exists: CowEntity['Cow'/10, l='ServerLevel[New World]', x=-18.50, y=56.00, z=-25.50]

this is very funny I'm going to throw myself off a cliff

@Override
    public ActionResult useOnBlock(ItemUsageContext context) {
        ItemStack stack = context.getStack();
        PlayerEntity player = context.getPlayer();

        if (!context.getWorld().isClient()) {
            // Get the NBT from the item
            NbtCompound itemNbt = stack.getNbt();

            if (itemNbt != null && itemNbt.contains("StoredEntity")) {
                // Retrieve the stored entity data
                NbtCompound entityData = itemNbt.getCompound("StoredEntity");
                String entityTypeString = entityData.getString("EntityType");
                EntityType<?> entityType = Registries.ENTITY_TYPE.get(new Identifier(entityTypeString));
                if (entityType != null) {
                    Entity clonedEntity = entityType.create(context.getWorld());
                    if (clonedEntity != null) {
                        clonedEntity.readNbt(entityData);
                        clonedEntity.refreshPositionAndAngles(
                                context.getBlockPos().getX() + 0.5,
                                context.getBlockPos().getY() + 1,
                                context.getBlockPos().getZ() + 0.5,
                                player.getYaw(),
                                player.getPitch()
                        );
                        context.getWorld().spawnEntity(clonedEntity);
                    }
                } else {
                    player.sendMessage(Text.of("Failed to spawn entity"), true);
                }
            } else {
                player.sendMessage(Text.of("No entity stored"), true);
            }
        }
        return ActionResult.SUCCESS;
    }```
code
misty helm
#

You may wish to look into how the uuid is stored and where it comes from for new entities. It shouldn't be a problem to assign a new one to the clone

#

Are you using an llm

peak aspen
# misty helm Are you using an llm

Well, I found a gpt for fabric, and since I'm new, I figured at least it should know about some things. Usually it gets a lot things wrong though :/

misty helm
#

Do you have strong java knowledge?

peak aspen