664 lines
29 KiB
Java
664 lines
29 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* com.google.common.annotations.VisibleForTesting
|
|
* com.google.common.collect.Maps
|
|
* com.mojang.logging.LogUtils
|
|
* com.mojang.serialization.Codec
|
|
* com.mojang.serialization.DataResult
|
|
* org.jspecify.annotations.Nullable
|
|
* org.slf4j.Logger
|
|
*/
|
|
package net.minecraft.world.item;
|
|
|
|
import com.google.common.annotations.VisibleForTesting;
|
|
import com.google.common.collect.Maps;
|
|
import com.mojang.logging.LogUtils;
|
|
import com.mojang.serialization.Codec;
|
|
import com.mojang.serialization.DataResult;
|
|
import java.util.Map;
|
|
import java.util.Objects;
|
|
import java.util.Optional;
|
|
import java.util.function.Consumer;
|
|
import net.minecraft.SharedConstants;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Holder;
|
|
import net.minecraft.core.HolderGetter;
|
|
import net.minecraft.core.HolderLookup;
|
|
import net.minecraft.core.HolderSet;
|
|
import net.minecraft.core.component.DataComponentMap;
|
|
import net.minecraft.core.component.DataComponentType;
|
|
import net.minecraft.core.component.DataComponents;
|
|
import net.minecraft.core.registries.BuiltInRegistries;
|
|
import net.minecraft.core.registries.Registries;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.network.RegistryFriendlyByteBuf;
|
|
import net.minecraft.network.chat.CommonComponents;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.network.codec.ByteBufCodecs;
|
|
import net.minecraft.network.codec.StreamCodec;
|
|
import net.minecraft.resources.DependantName;
|
|
import net.minecraft.resources.Identifier;
|
|
import net.minecraft.resources.ResourceKey;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.sounds.SoundEvents;
|
|
import net.minecraft.tags.BlockTags;
|
|
import net.minecraft.tags.DamageTypeTags;
|
|
import net.minecraft.tags.EntityTypeTags;
|
|
import net.minecraft.tags.TagKey;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.util.Util;
|
|
import net.minecraft.world.Difficulty;
|
|
import net.minecraft.world.InteractionHand;
|
|
import net.minecraft.world.InteractionResult;
|
|
import net.minecraft.world.damagesource.DamageSource;
|
|
import net.minecraft.world.damagesource.DamageType;
|
|
import net.minecraft.world.damagesource.DamageTypes;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.entity.EntityType;
|
|
import net.minecraft.world.entity.EquipmentSlot;
|
|
import net.minecraft.world.entity.EquipmentSlotGroup;
|
|
import net.minecraft.world.entity.LivingEntity;
|
|
import net.minecraft.world.entity.SlotAccess;
|
|
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
|
|
import net.minecraft.world.entity.ai.attributes.Attributes;
|
|
import net.minecraft.world.entity.item.ItemEntity;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.flag.FeatureElement;
|
|
import net.minecraft.world.flag.FeatureFlag;
|
|
import net.minecraft.world.flag.FeatureFlagSet;
|
|
import net.minecraft.world.flag.FeatureFlags;
|
|
import net.minecraft.world.food.FoodProperties;
|
|
import net.minecraft.world.inventory.ClickAction;
|
|
import net.minecraft.world.inventory.Slot;
|
|
import net.minecraft.world.inventory.tooltip.TooltipComponent;
|
|
import net.minecraft.world.item.EitherHolder;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.ItemUseAnimation;
|
|
import net.minecraft.world.item.Items;
|
|
import net.minecraft.world.item.JukeboxPlayable;
|
|
import net.minecraft.world.item.JukeboxSong;
|
|
import net.minecraft.world.item.Rarity;
|
|
import net.minecraft.world.item.SwingAnimationType;
|
|
import net.minecraft.world.item.ToolMaterial;
|
|
import net.minecraft.world.item.TooltipFlag;
|
|
import net.minecraft.world.item.component.Consumable;
|
|
import net.minecraft.world.item.component.Consumables;
|
|
import net.minecraft.world.item.component.DamageResistant;
|
|
import net.minecraft.world.item.component.ItemAttributeModifiers;
|
|
import net.minecraft.world.item.component.KineticWeapon;
|
|
import net.minecraft.world.item.component.PiercingWeapon;
|
|
import net.minecraft.world.item.component.ProvidesTrimMaterial;
|
|
import net.minecraft.world.item.component.SwingAnimation;
|
|
import net.minecraft.world.item.component.Tool;
|
|
import net.minecraft.world.item.component.TooltipDisplay;
|
|
import net.minecraft.world.item.component.TypedEntityData;
|
|
import net.minecraft.world.item.component.UseCooldown;
|
|
import net.minecraft.world.item.component.UseEffects;
|
|
import net.minecraft.world.item.component.UseRemainder;
|
|
import net.minecraft.world.item.component.Weapon;
|
|
import net.minecraft.world.item.context.UseOnContext;
|
|
import net.minecraft.world.item.enchantment.Enchantable;
|
|
import net.minecraft.world.item.enchantment.Repairable;
|
|
import net.minecraft.world.item.equipment.ArmorMaterial;
|
|
import net.minecraft.world.item.equipment.ArmorType;
|
|
import net.minecraft.world.item.equipment.Equippable;
|
|
import net.minecraft.world.item.equipment.trim.TrimMaterial;
|
|
import net.minecraft.world.level.ClipContext;
|
|
import net.minecraft.world.level.ItemLike;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.block.Block;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.saveddata.maps.MapId;
|
|
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
|
|
import net.minecraft.world.phys.BlockHitResult;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import org.jspecify.annotations.Nullable;
|
|
import org.slf4j.Logger;
|
|
|
|
public class Item
|
|
implements ItemLike,
|
|
FeatureElement {
|
|
public static final Codec<Holder<Item>> CODEC = BuiltInRegistries.ITEM.holderByNameCodec().validate(item -> item.is(Items.AIR.builtInRegistryHolder()) ? DataResult.error(() -> "Item must not be minecraft:air") : DataResult.success((Object)item));
|
|
public static final StreamCodec<RegistryFriendlyByteBuf, Holder<Item>> STREAM_CODEC = ByteBufCodecs.holderRegistry(Registries.ITEM);
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
public static final Map<Block, Item> BY_BLOCK = Maps.newHashMap();
|
|
public static final Identifier BASE_ATTACK_DAMAGE_ID = Identifier.withDefaultNamespace("base_attack_damage");
|
|
public static final Identifier BASE_ATTACK_SPEED_ID = Identifier.withDefaultNamespace("base_attack_speed");
|
|
public static final int DEFAULT_MAX_STACK_SIZE = 64;
|
|
public static final int ABSOLUTE_MAX_STACK_SIZE = 99;
|
|
public static final int MAX_BAR_WIDTH = 13;
|
|
protected static final int APPROXIMATELY_INFINITE_USE_DURATION = 72000;
|
|
private final Holder.Reference<Item> builtInRegistryHolder = BuiltInRegistries.ITEM.createIntrusiveHolder(this);
|
|
private final DataComponentMap components;
|
|
private final @Nullable Item craftingRemainingItem;
|
|
protected final String descriptionId;
|
|
private final FeatureFlagSet requiredFeatures;
|
|
|
|
public static int getId(Item item) {
|
|
return item == null ? 0 : BuiltInRegistries.ITEM.getId(item);
|
|
}
|
|
|
|
public static Item byId(int id) {
|
|
return BuiltInRegistries.ITEM.byId(id);
|
|
}
|
|
|
|
@Deprecated
|
|
public static Item byBlock(Block block) {
|
|
return BY_BLOCK.getOrDefault(block, Items.AIR);
|
|
}
|
|
|
|
public Item(Properties properties) {
|
|
String className;
|
|
this.descriptionId = properties.effectiveDescriptionId();
|
|
this.components = properties.buildAndValidateComponents(Component.translatable(this.descriptionId), properties.effectiveModel());
|
|
this.craftingRemainingItem = properties.craftingRemainingItem;
|
|
this.requiredFeatures = properties.requiredFeatures;
|
|
if (SharedConstants.IS_RUNNING_IN_IDE && !(className = this.getClass().getSimpleName()).endsWith("Item")) {
|
|
LOGGER.error("Item classes should end with Item and {} doesn't.", (Object)className);
|
|
}
|
|
}
|
|
|
|
@Deprecated
|
|
public Holder.Reference<Item> builtInRegistryHolder() {
|
|
return this.builtInRegistryHolder;
|
|
}
|
|
|
|
public DataComponentMap components() {
|
|
return this.components;
|
|
}
|
|
|
|
public int getDefaultMaxStackSize() {
|
|
return this.components.getOrDefault(DataComponents.MAX_STACK_SIZE, 1);
|
|
}
|
|
|
|
public void onUseTick(Level level, LivingEntity livingEntity, ItemStack itemStack, int ticksRemaining) {
|
|
}
|
|
|
|
public void onDestroyed(ItemEntity itemEntity) {
|
|
}
|
|
|
|
/*
|
|
* Enabled force condition propagation
|
|
* Lifted jumps to return sites
|
|
*/
|
|
public boolean canDestroyBlock(ItemStack itemStack, BlockState state, Level level, BlockPos pos, LivingEntity user) {
|
|
Tool tool = itemStack.get(DataComponents.TOOL);
|
|
if (tool == null) return true;
|
|
if (tool.canDestroyBlocksInCreative()) return true;
|
|
if (!(user instanceof Player)) return true;
|
|
Player player = (Player)user;
|
|
if (player.getAbilities().instabuild) return false;
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public Item asItem() {
|
|
return this;
|
|
}
|
|
|
|
public InteractionResult useOn(UseOnContext context) {
|
|
return InteractionResult.PASS;
|
|
}
|
|
|
|
public float getDestroySpeed(ItemStack itemStack, BlockState state) {
|
|
Tool tool = itemStack.get(DataComponents.TOOL);
|
|
return tool != null ? tool.getMiningSpeed(state) : 1.0f;
|
|
}
|
|
|
|
public InteractionResult use(Level level, Player player, InteractionHand hand) {
|
|
ItemStack stack = player.getItemInHand(hand);
|
|
Consumable consumable = stack.get(DataComponents.CONSUMABLE);
|
|
if (consumable != null) {
|
|
return consumable.startConsuming(player, stack, hand);
|
|
}
|
|
Equippable equippable = stack.get(DataComponents.EQUIPPABLE);
|
|
if (equippable != null && equippable.swappable()) {
|
|
return equippable.swapWithEquipmentSlot(stack, player);
|
|
}
|
|
if (stack.has(DataComponents.BLOCKS_ATTACKS)) {
|
|
player.startUsingItem(hand);
|
|
return InteractionResult.CONSUME;
|
|
}
|
|
KineticWeapon kineticWeapon = stack.get(DataComponents.KINETIC_WEAPON);
|
|
if (kineticWeapon != null) {
|
|
player.startUsingItem(hand);
|
|
kineticWeapon.makeSound(player);
|
|
return InteractionResult.CONSUME;
|
|
}
|
|
return InteractionResult.PASS;
|
|
}
|
|
|
|
public ItemStack finishUsingItem(ItemStack itemStack, Level level, LivingEntity entity) {
|
|
Consumable consumable = itemStack.get(DataComponents.CONSUMABLE);
|
|
if (consumable != null) {
|
|
return consumable.onConsume(level, entity, itemStack);
|
|
}
|
|
return itemStack;
|
|
}
|
|
|
|
public boolean isBarVisible(ItemStack stack) {
|
|
return stack.isDamaged();
|
|
}
|
|
|
|
public int getBarWidth(ItemStack stack) {
|
|
return Mth.clamp(Math.round(13.0f - (float)stack.getDamageValue() * 13.0f / (float)stack.getMaxDamage()), 0, 13);
|
|
}
|
|
|
|
public int getBarColor(ItemStack stack) {
|
|
int maxDamage = stack.getMaxDamage();
|
|
float healthPercentage = Math.max(0.0f, ((float)maxDamage - (float)stack.getDamageValue()) / (float)maxDamage);
|
|
return Mth.hsvToRgb(healthPercentage / 3.0f, 1.0f, 1.0f);
|
|
}
|
|
|
|
public boolean overrideStackedOnOther(ItemStack self, Slot slot, ClickAction clickAction, Player player) {
|
|
return false;
|
|
}
|
|
|
|
public boolean overrideOtherStackedOnMe(ItemStack self, ItemStack other, Slot slot, ClickAction clickAction, Player player, SlotAccess carriedItem) {
|
|
return false;
|
|
}
|
|
|
|
public float getAttackDamageBonus(Entity victim, float damage, DamageSource damageSource) {
|
|
return 0.0f;
|
|
}
|
|
|
|
@Deprecated
|
|
public @Nullable DamageSource getItemDamageSource(LivingEntity attacker) {
|
|
return null;
|
|
}
|
|
|
|
public void hurtEnemy(ItemStack itemStack, LivingEntity mob, LivingEntity attacker) {
|
|
}
|
|
|
|
public void postHurtEnemy(ItemStack itemStack, LivingEntity mob, LivingEntity attacker) {
|
|
}
|
|
|
|
public boolean mineBlock(ItemStack itemStack, Level level, BlockState state, BlockPos pos, LivingEntity owner) {
|
|
Tool tool = itemStack.get(DataComponents.TOOL);
|
|
if (tool == null) {
|
|
return false;
|
|
}
|
|
if (!level.isClientSide() && state.getDestroySpeed(level, pos) != 0.0f && tool.damagePerBlock() > 0) {
|
|
itemStack.hurtAndBreak(tool.damagePerBlock(), owner, EquipmentSlot.MAINHAND);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public boolean isCorrectToolForDrops(ItemStack itemStack, BlockState state) {
|
|
Tool tool = itemStack.get(DataComponents.TOOL);
|
|
return tool != null && tool.isCorrectForDrops(state);
|
|
}
|
|
|
|
public InteractionResult interactLivingEntity(ItemStack itemStack, Player player, LivingEntity target, InteractionHand type) {
|
|
return InteractionResult.PASS;
|
|
}
|
|
|
|
public String toString() {
|
|
return BuiltInRegistries.ITEM.wrapAsHolder(this).getRegisteredName();
|
|
}
|
|
|
|
public final ItemStack getCraftingRemainder() {
|
|
return this.craftingRemainingItem == null ? ItemStack.EMPTY : new ItemStack(this.craftingRemainingItem);
|
|
}
|
|
|
|
public void inventoryTick(ItemStack itemStack, ServerLevel level, Entity owner, @Nullable EquipmentSlot slot) {
|
|
}
|
|
|
|
public void onCraftedBy(ItemStack itemStack, Player player) {
|
|
this.onCraftedPostProcess(itemStack, player.level());
|
|
}
|
|
|
|
public void onCraftedPostProcess(ItemStack itemStack, Level level) {
|
|
}
|
|
|
|
public ItemUseAnimation getUseAnimation(ItemStack itemStack) {
|
|
Consumable consumable = itemStack.get(DataComponents.CONSUMABLE);
|
|
if (consumable != null) {
|
|
return consumable.animation();
|
|
}
|
|
if (itemStack.has(DataComponents.BLOCKS_ATTACKS)) {
|
|
return ItemUseAnimation.BLOCK;
|
|
}
|
|
if (itemStack.has(DataComponents.KINETIC_WEAPON)) {
|
|
return ItemUseAnimation.SPEAR;
|
|
}
|
|
return ItemUseAnimation.NONE;
|
|
}
|
|
|
|
public int getUseDuration(ItemStack itemStack, LivingEntity user) {
|
|
Consumable consumable = itemStack.get(DataComponents.CONSUMABLE);
|
|
if (consumable != null) {
|
|
return consumable.consumeTicks();
|
|
}
|
|
if (itemStack.has(DataComponents.BLOCKS_ATTACKS) || itemStack.has(DataComponents.KINETIC_WEAPON)) {
|
|
return 72000;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
public boolean releaseUsing(ItemStack itemStack, Level level, LivingEntity entity, int remainingTime) {
|
|
return false;
|
|
}
|
|
|
|
@Deprecated
|
|
public void appendHoverText(ItemStack itemStack, TooltipContext context, TooltipDisplay display, Consumer<Component> builder, TooltipFlag tooltipFlag) {
|
|
}
|
|
|
|
public Optional<TooltipComponent> getTooltipImage(ItemStack itemStack) {
|
|
return Optional.empty();
|
|
}
|
|
|
|
@VisibleForTesting
|
|
public final String getDescriptionId() {
|
|
return this.descriptionId;
|
|
}
|
|
|
|
public final Component getName() {
|
|
return this.components.getOrDefault(DataComponents.ITEM_NAME, CommonComponents.EMPTY);
|
|
}
|
|
|
|
public Component getName(ItemStack itemStack) {
|
|
return itemStack.getComponents().getOrDefault(DataComponents.ITEM_NAME, CommonComponents.EMPTY);
|
|
}
|
|
|
|
public boolean isFoil(ItemStack itemStack) {
|
|
return itemStack.isEnchanted();
|
|
}
|
|
|
|
protected static BlockHitResult getPlayerPOVHitResult(Level level, Player player, ClipContext.Fluid fluid) {
|
|
Vec3 from = player.getEyePosition();
|
|
Vec3 to = from.add(player.calculateViewVector(player.getXRot(), player.getYRot()).scale(player.blockInteractionRange()));
|
|
return level.clip(new ClipContext(from, to, ClipContext.Block.OUTLINE, fluid, player));
|
|
}
|
|
|
|
public boolean useOnRelease(ItemStack itemStack) {
|
|
return false;
|
|
}
|
|
|
|
public ItemStack getDefaultInstance() {
|
|
return new ItemStack(this);
|
|
}
|
|
|
|
public boolean canFitInsideContainerItems() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public FeatureFlagSet requiredFeatures() {
|
|
return this.requiredFeatures;
|
|
}
|
|
|
|
public boolean shouldPrintOpWarning(ItemStack stack, @Nullable Player player) {
|
|
return false;
|
|
}
|
|
|
|
public static class Properties {
|
|
private static final DependantName<Item, String> BLOCK_DESCRIPTION_ID = id -> Util.makeDescriptionId("block", id.identifier());
|
|
private static final DependantName<Item, String> ITEM_DESCRIPTION_ID = id -> Util.makeDescriptionId("item", id.identifier());
|
|
private final DataComponentMap.Builder components = DataComponentMap.builder().addAll(DataComponents.COMMON_ITEM_COMPONENTS);
|
|
private @Nullable Item craftingRemainingItem;
|
|
private FeatureFlagSet requiredFeatures = FeatureFlags.VANILLA_SET;
|
|
private @Nullable ResourceKey<Item> id;
|
|
private DependantName<Item, String> descriptionId = ITEM_DESCRIPTION_ID;
|
|
private final DependantName<Item, Identifier> model = ResourceKey::identifier;
|
|
|
|
public Properties food(FoodProperties foodProperties) {
|
|
return this.food(foodProperties, Consumables.DEFAULT_FOOD);
|
|
}
|
|
|
|
public Properties food(FoodProperties foodProperties, Consumable consumable) {
|
|
return this.component(DataComponents.FOOD, foodProperties).component(DataComponents.CONSUMABLE, consumable);
|
|
}
|
|
|
|
public Properties usingConvertsTo(Item item) {
|
|
return this.component(DataComponents.USE_REMAINDER, new UseRemainder(new ItemStack(item)));
|
|
}
|
|
|
|
public Properties useCooldown(float seconds) {
|
|
return this.component(DataComponents.USE_COOLDOWN, new UseCooldown(seconds));
|
|
}
|
|
|
|
public Properties stacksTo(int max) {
|
|
return this.component(DataComponents.MAX_STACK_SIZE, max);
|
|
}
|
|
|
|
public Properties durability(int maxDamage) {
|
|
this.component(DataComponents.MAX_DAMAGE, maxDamage);
|
|
this.component(DataComponents.MAX_STACK_SIZE, 1);
|
|
this.component(DataComponents.DAMAGE, 0);
|
|
return this;
|
|
}
|
|
|
|
public Properties craftRemainder(Item craftingRemainingItem) {
|
|
this.craftingRemainingItem = craftingRemainingItem;
|
|
return this;
|
|
}
|
|
|
|
public Properties rarity(Rarity rarity) {
|
|
return this.component(DataComponents.RARITY, rarity);
|
|
}
|
|
|
|
public Properties fireResistant() {
|
|
return this.component(DataComponents.DAMAGE_RESISTANT, new DamageResistant(DamageTypeTags.IS_FIRE));
|
|
}
|
|
|
|
public Properties jukeboxPlayable(ResourceKey<JukeboxSong> song) {
|
|
return this.component(DataComponents.JUKEBOX_PLAYABLE, new JukeboxPlayable(new EitherHolder<JukeboxSong>(song)));
|
|
}
|
|
|
|
public Properties enchantable(int value) {
|
|
return this.component(DataComponents.ENCHANTABLE, new Enchantable(value));
|
|
}
|
|
|
|
public Properties repairable(Item repairItem) {
|
|
return this.component(DataComponents.REPAIRABLE, new Repairable(HolderSet.direct(repairItem.builtInRegistryHolder())));
|
|
}
|
|
|
|
public Properties repairable(TagKey<Item> repairItems) {
|
|
HolderGetter<Item> registrationLookup = BuiltInRegistries.acquireBootstrapRegistrationLookup(BuiltInRegistries.ITEM);
|
|
return this.component(DataComponents.REPAIRABLE, new Repairable(registrationLookup.getOrThrow(repairItems)));
|
|
}
|
|
|
|
public Properties equippable(EquipmentSlot slot) {
|
|
return this.component(DataComponents.EQUIPPABLE, Equippable.builder(slot).build());
|
|
}
|
|
|
|
public Properties equippableUnswappable(EquipmentSlot slot) {
|
|
return this.component(DataComponents.EQUIPPABLE, Equippable.builder(slot).setSwappable(false).build());
|
|
}
|
|
|
|
public Properties tool(ToolMaterial material, TagKey<Block> minesEfficiently, float attackDamageBaseline, float attackSpeedBaseline, float disableBlockingSeconds) {
|
|
return material.applyToolProperties(this, minesEfficiently, attackDamageBaseline, attackSpeedBaseline, disableBlockingSeconds);
|
|
}
|
|
|
|
public Properties pickaxe(ToolMaterial material, float attackDamageBaseline, float attackSpeedBaseline) {
|
|
return this.tool(material, BlockTags.MINEABLE_WITH_PICKAXE, attackDamageBaseline, attackSpeedBaseline, 0.0f);
|
|
}
|
|
|
|
public Properties axe(ToolMaterial material, float attackDamageBaseline, float attackSpeedBaseline) {
|
|
return this.tool(material, BlockTags.MINEABLE_WITH_AXE, attackDamageBaseline, attackSpeedBaseline, 5.0f);
|
|
}
|
|
|
|
public Properties hoe(ToolMaterial material, float attackDamageBaseline, float attackSpeedBaseline) {
|
|
return this.tool(material, BlockTags.MINEABLE_WITH_HOE, attackDamageBaseline, attackSpeedBaseline, 0.0f);
|
|
}
|
|
|
|
public Properties shovel(ToolMaterial material, float attackDamageBaseline, float attackSpeedBaseline) {
|
|
return this.tool(material, BlockTags.MINEABLE_WITH_SHOVEL, attackDamageBaseline, attackSpeedBaseline, 0.0f);
|
|
}
|
|
|
|
public Properties sword(ToolMaterial material, float attackDamageBaseline, float attackSpeedBaseline) {
|
|
return material.applySwordProperties(this, attackDamageBaseline, attackSpeedBaseline);
|
|
}
|
|
|
|
public Properties spear(ToolMaterial material, float attackDuration, float damageMultiplier, float delay, float dismountTime, float dismountThreshold, float knockbackTime, float knockbackThreshold, float damageTime, float damageThreshold) {
|
|
return this.durability(material.durability()).repairable(material.repairItems()).enchantable(material.enchantmentValue()).component(DataComponents.DAMAGE_TYPE, new EitherHolder<DamageType>(DamageTypes.SPEAR)).component(DataComponents.KINETIC_WEAPON, new KineticWeapon(2.0f, 4.5f, 0.125f, 10, (int)(delay * 20.0f), KineticWeapon.Condition.ofAttackerSpeed((int)(dismountTime * 20.0f), dismountThreshold), KineticWeapon.Condition.ofAttackerSpeed((int)(knockbackTime * 20.0f), knockbackThreshold), KineticWeapon.Condition.ofRelativeSpeed((int)(damageTime * 20.0f), damageThreshold), 0.38f, damageMultiplier, Optional.of(material == ToolMaterial.WOOD ? SoundEvents.SPEAR_WOOD_USE : SoundEvents.SPEAR_USE), Optional.of(material == ToolMaterial.WOOD ? SoundEvents.SPEAR_WOOD_HIT : SoundEvents.SPEAR_HIT))).component(DataComponents.PIERCING_WEAPON, new PiercingWeapon(2.0f, 4.5f, 0.25f, true, false, Optional.of(material == ToolMaterial.WOOD ? SoundEvents.SPEAR_WOOD_ATTACK : SoundEvents.SPEAR_ATTACK), Optional.of(material == ToolMaterial.WOOD ? SoundEvents.SPEAR_WOOD_HIT : SoundEvents.SPEAR_HIT))).component(DataComponents.MINIMUM_ATTACK_CHARGE, Float.valueOf(1.0f)).component(DataComponents.SWING_ANIMATION, new SwingAnimation(SwingAnimationType.STAB, (int)(attackDuration * 20.0f))).attributes(ItemAttributeModifiers.builder().add(Attributes.ATTACK_DAMAGE, new AttributeModifier(BASE_ATTACK_DAMAGE_ID, 0.0f + material.attackDamageBonus(), AttributeModifier.Operation.ADD_VALUE), EquipmentSlotGroup.MAINHAND).add(Attributes.ATTACK_SPEED, new AttributeModifier(BASE_ATTACK_SPEED_ID, (double)(1.0f / attackDuration) - 4.0, AttributeModifier.Operation.ADD_VALUE), EquipmentSlotGroup.MAINHAND).build()).component(DataComponents.USE_EFFECTS, new UseEffects(true, 1.0f)).component(DataComponents.WEAPON, new Weapon(1));
|
|
}
|
|
|
|
public Properties spawnEgg(EntityType<?> type) {
|
|
return this.component(DataComponents.ENTITY_DATA, TypedEntityData.of(type, new CompoundTag()));
|
|
}
|
|
|
|
public Properties humanoidArmor(ArmorMaterial material, ArmorType type) {
|
|
return this.durability(type.getDurability(material.durability())).attributes(material.createAttributes(type)).enchantable(material.enchantmentValue()).component(DataComponents.EQUIPPABLE, Equippable.builder(type.getSlot()).setEquipSound(material.equipSound()).setAsset(material.assetId()).build()).repairable(material.repairIngredient());
|
|
}
|
|
|
|
public Properties wolfArmor(ArmorMaterial material) {
|
|
return this.durability(ArmorType.BODY.getDurability(material.durability())).attributes(material.createAttributes(ArmorType.BODY)).repairable(material.repairIngredient()).component(DataComponents.EQUIPPABLE, Equippable.builder(EquipmentSlot.BODY).setEquipSound(material.equipSound()).setAsset(material.assetId()).setAllowedEntities(HolderSet.direct(EntityType.WOLF.builtInRegistryHolder())).setCanBeSheared(true).setShearingSound(BuiltInRegistries.SOUND_EVENT.wrapAsHolder(SoundEvents.ARMOR_UNEQUIP_WOLF)).build()).component(DataComponents.BREAK_SOUND, SoundEvents.WOLF_ARMOR_BREAK).stacksTo(1);
|
|
}
|
|
|
|
public Properties horseArmor(ArmorMaterial material) {
|
|
HolderGetter<EntityType<?>> entityGetter = BuiltInRegistries.acquireBootstrapRegistrationLookup(BuiltInRegistries.ENTITY_TYPE);
|
|
return this.attributes(material.createAttributes(ArmorType.BODY)).component(DataComponents.EQUIPPABLE, Equippable.builder(EquipmentSlot.BODY).setEquipSound(SoundEvents.HORSE_ARMOR).setAsset(material.assetId()).setAllowedEntities(entityGetter.getOrThrow(EntityTypeTags.CAN_WEAR_HORSE_ARMOR)).setDamageOnHurt(false).setCanBeSheared(true).setShearingSound(SoundEvents.HORSE_ARMOR_UNEQUIP).build()).stacksTo(1);
|
|
}
|
|
|
|
public Properties nautilusArmor(ArmorMaterial material) {
|
|
HolderGetter<EntityType<?>> entityGetter = BuiltInRegistries.acquireBootstrapRegistrationLookup(BuiltInRegistries.ENTITY_TYPE);
|
|
return this.attributes(material.createAttributes(ArmorType.BODY)).component(DataComponents.EQUIPPABLE, Equippable.builder(EquipmentSlot.BODY).setEquipSound(SoundEvents.ARMOR_EQUIP_NAUTILUS).setAsset(material.assetId()).setAllowedEntities(entityGetter.getOrThrow(EntityTypeTags.CAN_WEAR_NAUTILUS_ARMOR)).setDamageOnHurt(false).setEquipOnInteract(true).setCanBeSheared(true).setShearingSound(SoundEvents.ARMOR_UNEQUIP_NAUTILUS).build()).stacksTo(1);
|
|
}
|
|
|
|
public Properties trimMaterial(ResourceKey<TrimMaterial> material) {
|
|
return this.component(DataComponents.PROVIDES_TRIM_MATERIAL, new ProvidesTrimMaterial(material));
|
|
}
|
|
|
|
public Properties requiredFeatures(FeatureFlag ... flags) {
|
|
this.requiredFeatures = FeatureFlags.REGISTRY.subset(flags);
|
|
return this;
|
|
}
|
|
|
|
public Properties setId(ResourceKey<Item> id) {
|
|
this.id = id;
|
|
return this;
|
|
}
|
|
|
|
public Properties overrideDescription(String descriptionId) {
|
|
this.descriptionId = DependantName.fixed(descriptionId);
|
|
return this;
|
|
}
|
|
|
|
public Properties useBlockDescriptionPrefix() {
|
|
this.descriptionId = BLOCK_DESCRIPTION_ID;
|
|
return this;
|
|
}
|
|
|
|
public Properties useItemDescriptionPrefix() {
|
|
this.descriptionId = ITEM_DESCRIPTION_ID;
|
|
return this;
|
|
}
|
|
|
|
protected String effectiveDescriptionId() {
|
|
return this.descriptionId.get(Objects.requireNonNull(this.id, "Item id not set"));
|
|
}
|
|
|
|
public Identifier effectiveModel() {
|
|
return this.model.get(Objects.requireNonNull(this.id, "Item id not set"));
|
|
}
|
|
|
|
public <T> Properties component(DataComponentType<T> type, T value) {
|
|
this.components.set(type, value);
|
|
return this;
|
|
}
|
|
|
|
public Properties attributes(ItemAttributeModifiers attributes) {
|
|
return this.component(DataComponents.ATTRIBUTE_MODIFIERS, attributes);
|
|
}
|
|
|
|
private DataComponentMap buildAndValidateComponents(Component name, Identifier model) {
|
|
DataComponentMap components = this.components.set(DataComponents.ITEM_NAME, name).set(DataComponents.ITEM_MODEL, model).build();
|
|
if (components.has(DataComponents.DAMAGE) && components.getOrDefault(DataComponents.MAX_STACK_SIZE, 1) > 1) {
|
|
throw new IllegalStateException("Item cannot have both durability and be stackable");
|
|
}
|
|
return components;
|
|
}
|
|
}
|
|
|
|
public static interface TooltipContext {
|
|
public static final TooltipContext EMPTY = new TooltipContext(){
|
|
|
|
@Override
|
|
public @Nullable HolderLookup.Provider registries() {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public float tickRate() {
|
|
return 20.0f;
|
|
}
|
|
|
|
@Override
|
|
public @Nullable MapItemSavedData mapData(MapId id) {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public boolean isPeaceful() {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
public @Nullable HolderLookup.Provider registries();
|
|
|
|
public float tickRate();
|
|
|
|
public @Nullable MapItemSavedData mapData(MapId var1);
|
|
|
|
public boolean isPeaceful();
|
|
|
|
public static TooltipContext of(final @Nullable Level level) {
|
|
if (level == null) {
|
|
return EMPTY;
|
|
}
|
|
return new TooltipContext(){
|
|
|
|
@Override
|
|
public HolderLookup.Provider registries() {
|
|
return level.registryAccess();
|
|
}
|
|
|
|
@Override
|
|
public float tickRate() {
|
|
return level.tickRateManager().tickrate();
|
|
}
|
|
|
|
@Override
|
|
public MapItemSavedData mapData(MapId id) {
|
|
return level.getMapData(id);
|
|
}
|
|
|
|
@Override
|
|
public boolean isPeaceful() {
|
|
return level.getDifficulty() == Difficulty.PEACEFUL;
|
|
}
|
|
};
|
|
}
|
|
|
|
public static TooltipContext of(final HolderLookup.Provider registries) {
|
|
return new TooltipContext(){
|
|
|
|
@Override
|
|
public HolderLookup.Provider registries() {
|
|
return registries;
|
|
}
|
|
|
|
@Override
|
|
public float tickRate() {
|
|
return 20.0f;
|
|
}
|
|
|
|
@Override
|
|
public @Nullable MapItemSavedData mapData(MapId id) {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public boolean isPeaceful() {
|
|
return false;
|
|
}
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|