如何使用 Fabric 制作不死图腾之类的物品?

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

我是 Minecraft Fabric Modding 的新手,我正在尝试制作像不死图腾这样的物品,但我找不到图腾代码!

没有像 TotemOfUndyingItem 这样的东西 class 谁能告诉我不死图腾在哪里!

不死图腾只是一个普通物品,这就是为什么没有自定义物品 class 的原因。它的特殊能力来自实体在受到伤害时对拥有该物品的反应。

自 minecraft 1.18.1 起,不死物品图腾由活体处理 class。 class包含处理实体受到伤害的函数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);
        }
    }

如果实体已死,它会运行函数 tryUseTotem。这是应用不死图腾状态效果的地方。

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;
}

最后,sendEntityStatus 函数被调用。这由各种 classes 通过称为 handleStatusonEntityStatus 的函数处理。特别是,发送字节 35 由 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());
        }
    }
}