Search code examples
javaintellij-ideaminecraft-fabric

How do I make a Totem of Undying like item with Fabric?


I am new to Minecraft Fabric Modding and I am trying to make a Item like the Totem of Undying but I can't find the Totem code!

no Totem

There is nothing lika a TotemOfUndyingItem class can Somebodytell me where the totem of undying is handeld!


Solution

  • The totem of undying is just a regular item, which is why there is no custom item class for it. Its special abilities come from how entities respond to having the item when they take damage.

    As of minecraft 1.18.1, the totem of undying item is handled by the Living Entity class. This class contains the function damage which handles an entity takes damage.

        if (this.isDead()) {
            if (!this.tryUseTotem(source)) {
                SoundEvent soundEvent = this.getDeathSound();
                if (bl2 && soundEvent != null) {
                    this.playSound(soundEvent, this.getSoundVolume(), this.getSoundPitch());
                }
                this.onDeath(source);
            }
        }
    

    If the entity is dead, it runs the function tryUseTotem. This is where the status effects for the totem of undying are applied.

    private boolean tryUseTotem(DamageSource source) {
        if (source.isOutOfWorld()) {
            return false;
        }
        ItemStack itemStack = null;
        for (Hand hand : Hand.values()) {
            ItemStack itemStack2 = this.getStackInHand(hand);
            if (!itemStack2.isOf(Items.TOTEM_OF_UNDYING)) continue;
            itemStack = itemStack2.copy();
            itemStack2.decrement(1);
            break;
        }
        if (itemStack != null) {
            if (this instanceof ServerPlayerEntity) {
                ServerPlayerEntity serverPlayerEntity = (ServerPlayerEntity)this;
                serverPlayerEntity.incrementStat(Stats.USED.getOrCreateStat(Items.TOTEM_OF_UNDYING));
                Criteria.USED_TOTEM.trigger(serverPlayerEntity, itemStack);
            }
            this.setHealth(1.0f);
            this.clearStatusEffects();
            this.addStatusEffect(new StatusEffectInstance(StatusEffects.REGENERATION, 900, 1));
            this.addStatusEffect(new StatusEffectInstance(StatusEffects.ABSORPTION, 100, 1));
            this.addStatusEffect(new StatusEffectInstance(StatusEffects.FIRE_RESISTANCE, 800, 0));
            this.world.sendEntityStatus(this, (byte)35);
        }
        return itemStack != null;
    }
    

    Finally, the sendEntityStatus function is called. This is handled by a variety of classes by functions called handleStatus or onEntityStatus. In particular, sending the byte 35 is handled by the ClientPlayNetworkHandler class.

    @Override
    public void onEntityStatus(EntityStatusS2CPacket packet) {
        NetworkThreadUtils.forceMainThread(packet, this, this.client);
        Entity entity = packet.getEntity(this.world);
        if (entity != null) {
            if (packet.getStatus() == 21) {
                this.client.getSoundManager().play(new GuardianAttackSoundInstance((GuardianEntity)entity));
            } else if (packet.getStatus() == 35) {
                int i = 40;
                this.client.particleManager.addEmitter(entity, ParticleTypes.TOTEM_OF_UNDYING, 30);
                this.world.playSound(entity.getX(), entity.getY(), entity.getZ(), SoundEvents.ITEM_TOTEM_USE, entity.getSoundCategory(), 1.0f, 1.0f, false);
                if (entity == this.client.player) {
                    this.client.gameRenderer.showFloatingItem(ClientPlayNetworkHandler.getActiveTotemOfUndying(this.client.player));
                }
            } else {
                entity.handleStatus(packet.getStatus());
            }
        }
    }