Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tooltip related extension methods for Attribute & Attribute related tooltip fix #1371

Open
wants to merge 2 commits into
base: 1.21.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--- a/net/minecraft/world/entity/ai/attributes/Attribute.java
+++ b/net/minecraft/world/entity/ai/attributes/Attribute.java
@@ -9,7 +_,7 @@
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;

-public class Attribute {
+public class Attribute implements net.neoforged.neoforge.common.extensions.IAttributeExtension {
public static final Codec<Holder<Attribute>> CODEC = BuiltInRegistries.ATTRIBUTE.holderByNameCodec();
public static final StreamCodec<RegistryFriendlyByteBuf, Holder<Attribute>> STREAM_CODEC = ByteBufCodecs.holderRegistry(Registries.ATTRIBUTE);
private final double defaultValue;
41 changes: 40 additions & 1 deletion patches/net/minecraft/world/item/ItemStack.java.patch
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,51 @@
}
}

private void addAttributeTooltips(Consumer<Component> p_330796_, @Nullable Player p_330530_) {
- private void addAttributeTooltips(Consumer<Component> p_330796_, @Nullable Player p_330530_) {
+ private void addAttributeTooltips(Consumer<Component> p_330796_, @Nullable Player p_330530_, TooltipFlag tooltipFlag) {
ItemAttributeModifiers itemattributemodifiers = this.getOrDefault(DataComponents.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.EMPTY);
+ // Neo: We don't need to call IItemStackExtension#getAttributeModifiers here, since it will be done in forEachModifier.
if (itemattributemodifiers.showInTooltip()) {
for (EquipmentSlotGroup equipmentslotgroup : EquipmentSlotGroup.values()) {
MutableBoolean mutableboolean = new MutableBoolean(true);
@@ -800,13 +_,13 @@
mutableboolean.setFalse();
}

- this.addModifierTooltip(p_330796_, p_330530_, p_348379_, p_348380_);
+ this.addModifierTooltip(p_330796_, p_330530_, p_348379_, p_348380_, tooltipFlag);
});
}
}
}

- private void addModifierTooltip(Consumer<Component> p_331062_, @Nullable Player p_330317_, Holder<Attribute> p_330626_, AttributeModifier p_331252_) {
+ private void addModifierTooltip(Consumer<Component> p_331062_, @Nullable Player p_330317_, Holder<Attribute> p_330626_, AttributeModifier p_331252_, TooltipFlag tooltipFlag) {
double d0 = p_331252_.amount();
boolean flag = false;
if (p_330317_ != null) {
@@ -819,15 +_,13 @@
}
}

- double d1;
- if (p_331252_.operation() == AttributeModifier.Operation.ADD_MULTIPLIED_BASE
- || p_331252_.operation() == AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL) {
- d1 = d0 * 100.0;
- } else if (p_330626_.is(Attributes.KNOCKBACK_RESISTANCE)) {
- d1 = d0 * 10.0;
- } else {
- d1 = d0;
+ Attribute attribute = p_330626_.value();
+ Component description = attribute.getModifierDescription(p_330317_, p_331252_, tooltipFlag);
+ if (description != null) {
+ p_331062_.accept(description);
+ return;
}
+ double d1 = flag ? d0 : attribute.getAmountForDisplay(p_331252_, tooltipFlag);

if (flag) {
p_331062_.accept(
@@ -897,6 +_,17 @@
return !this.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY).isEmpty();
}
Expand Down
11 changes: 11 additions & 0 deletions patches/net/minecraft/world/item/LingeringPotionItem.java.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--- a/net/minecraft/world/item/LingeringPotionItem.java
+++ b/net/minecraft/world/item/LingeringPotionItem.java
@@ -19,7 +_,7 @@
@Override
public void appendHoverText(ItemStack p_42838_, Item.TooltipContext p_339607_, List<Component> p_42840_, TooltipFlag p_42841_) {
PotionContents potioncontents = p_42838_.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY);
- potioncontents.addPotionTooltip(p_42840_::add, 0.25F, p_339607_.tickRate());
+ potioncontents.addPotionTooltip(p_42840_::add, 0.25F, p_339607_.tickRate(), p_42841_);
}

@Override
10 changes: 10 additions & 0 deletions patches/net/minecraft/world/item/OminousBottleItem.java.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--- a/net/minecraft/world/item/OminousBottleItem.java
+++ b/net/minecraft/world/item/OminousBottleItem.java
@@ -63,6 +_,6 @@
super.appendHoverText(p_338470_, p_339656_, p_338463_, p_338317_);
Integer integer = p_338470_.getOrDefault(DataComponents.OMINOUS_BOTTLE_AMPLIFIER, Integer.valueOf(0));
List<MobEffectInstance> list = List.of(new MobEffectInstance(MobEffects.BAD_OMEN, 120000, integer, false, false, true));
- PotionContents.addPotionTooltip(list, p_338463_::add, 1.0F, p_339656_.tickRate());
+ PotionContents.addPotionTooltip(list, p_338463_::add, 1.0F, p_339656_.tickRate(), p_338317_);
}
}
11 changes: 11 additions & 0 deletions patches/net/minecraft/world/item/PotionItem.java.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--- a/net/minecraft/world/item/PotionItem.java
+++ b/net/minecraft/world/item/PotionItem.java
@@ -142,7 +_,7 @@
public void appendHoverText(ItemStack p_42988_, Item.TooltipContext p_339608_, List<Component> p_42990_, TooltipFlag p_42991_) {
PotionContents potioncontents = p_42988_.get(DataComponents.POTION_CONTENTS);
if (potioncontents != null) {
- potioncontents.addPotionTooltip(p_42990_::add, 1.0F, p_339608_.tickRate());
+ potioncontents.addPotionTooltip(p_42990_::add, 1.0F, p_339608_.tickRate(), p_42991_);
}
}
}
11 changes: 11 additions & 0 deletions patches/net/minecraft/world/item/SuspiciousStewItem.java.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--- a/net/minecraft/world/item/SuspiciousStewItem.java
+++ b/net/minecraft/world/item/SuspiciousStewItem.java
@@ -28,7 +_,7 @@
list.add(suspicioussteweffects$entry.createEffectInstance());
}

- PotionContents.addPotionTooltip(list, p_259700_::add, 1.0F, p_339691_.tickRate());
+ PotionContents.addPotionTooltip(list, p_259700_::add, 1.0F, p_339691_.tickRate(), p_260021_);
}
}

11 changes: 11 additions & 0 deletions patches/net/minecraft/world/item/TippedArrowItem.java.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--- a/net/minecraft/world/item/TippedArrowItem.java
+++ b/net/minecraft/world/item/TippedArrowItem.java
@@ -23,7 +_,7 @@
public void appendHoverText(ItemStack p_43359_, Item.TooltipContext p_339681_, List<Component> p_43361_, TooltipFlag p_43362_) {
PotionContents potioncontents = p_43359_.get(DataComponents.POTION_CONTENTS);
if (potioncontents != null) {
- potioncontents.addPotionTooltip(p_43361_::add, 0.125F, p_339681_.tickRate());
+ potioncontents.addPotionTooltip(p_43361_::add, 0.125F, p_339681_.tickRate(), p_43362_);
}
}

85 changes: 85 additions & 0 deletions patches/net/minecraft/world/item/alchemy/PotionContents.java.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
--- a/net/minecraft/world/item/alchemy/PotionContents.java
+++ b/net/minecraft/world/item/alchemy/PotionContents.java
@@ -137,11 +_,35 @@
return Lists.transform(this.customEffects, MobEffectInstance::new);
}

+ /**
+ * Neo: use {@link net.minecraft.world.item.TooltipFlag} sensitive overloads.
+ */
+ @Deprecated
public void addPotionTooltip(Consumer<Component> p_331688_, float p_330466_, float p_332190_) {
addPotionTooltip(this.getAllEffects(), p_331688_, p_330466_, p_332190_);
}

+ public void addPotionTooltip(Consumer<Component> p_331688_, float p_330466_, float p_332190_, net.minecraft.world.item.TooltipFlag tooltipFlag) {
+ addPotionTooltip(this.getAllEffects(), p_331688_, p_330466_, p_332190_, tooltipFlag);
+ }
+
+ public void addPotionTooltip(Consumer<Component> p_331688_, float p_330466_, float p_332190_, net.minecraft.world.item.TooltipFlag tooltipFlag, Component consumeDesciption) {
+ addPotionTooltip(this.getAllEffects(), p_331688_, p_330466_, p_332190_, tooltipFlag, consumeDesciption);
+ }
+
+ /**
+ * Neo: use {@link net.minecraft.world.item.TooltipFlag} sensitive overloads.
+ */
+ @Deprecated
public static void addPotionTooltip(Iterable<MobEffectInstance> p_331825_, Consumer<Component> p_331296_, float p_332038_, float p_332014_) {
+ addPotionTooltip(p_331825_, p_331296_, p_332038_, p_332014_, net.minecraft.world.item.TooltipFlag.NORMAL);
+ }
+
+ public static void addPotionTooltip(Iterable<MobEffectInstance> p_331825_, Consumer<Component> p_331296_, float p_332038_, float p_332014_, net.minecraft.world.item.TooltipFlag tooltipFlag) {
+ addPotionTooltip(p_331825_, p_331296_, p_332038_, p_332014_, tooltipFlag, Component.translatable("potion.whenDrank").withStyle(ChatFormatting.DARK_PURPLE));
+ }
+
+ public static void addPotionTooltip(Iterable<MobEffectInstance> p_331825_, Consumer<Component> p_331296_, float p_332038_, float p_332014_, net.minecraft.world.item.TooltipFlag tooltipFlag, Component consumeDescription) {
List<Pair<Holder<Attribute>, AttributeModifier>> list = Lists.newArrayList();
boolean flag = true;

@@ -171,18 +_,18 @@

if (!list.isEmpty()) {
p_331296_.accept(CommonComponents.EMPTY);
- p_331296_.accept(Component.translatable("potion.whenDrank").withStyle(ChatFormatting.DARK_PURPLE));
+ p_331296_.accept(consumeDescription);

for (Pair<Holder<Attribute>, AttributeModifier> pair : list) {
AttributeModifier attributemodifier = pair.getSecond();
- double d1 = attributemodifier.amount();
- double d0;
- if (attributemodifier.operation() != AttributeModifier.Operation.ADD_MULTIPLIED_BASE
- && attributemodifier.operation() != AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL) {
- d0 = attributemodifier.amount();
- } else {
- d0 = attributemodifier.amount() * 100.0;
+ Attribute attribute = pair.getFirst().value();
+ Component description = attribute.getModifierDescription(net.neoforged.neoforge.common.CommonHooks.getPlayer(), attributemodifier, tooltipFlag);
+ if (description != null) {
+ p_331296_.accept(description);
+ continue;
}
+ double d1 = attributemodifier.amount();
+ double d0 = attribute.getAmountForDisplay(attributemodifier, tooltipFlag);

if (d1 > 0.0) {
p_331296_.accept(
@@ -191,7 +_,8 @@
ItemAttributeModifiers.ATTRIBUTE_MODIFIER_FORMAT.format(d0),
Component.translatable(pair.getFirst().value().getDescriptionId())
)
- .withStyle(ChatFormatting.BLUE)
+ .withStyle(attribute.getStyle(true))
+ //Neo: use Attribute#getStyle for consistency
);
} else if (d1 < 0.0) {
d0 *= -1.0;
@@ -201,7 +_,8 @@
ItemAttributeModifiers.ATTRIBUTE_MODIFIER_FORMAT.format(d0),
Component.translatable(pair.getFirst().value().getDescriptionId())
)
- .withStyle(ChatFormatting.RED)
+ .withStyle(attribute.getStyle(false))
+ //Neo: use Attribute#getStyle for consistency
);
}
}
8 changes: 8 additions & 0 deletions src/main/java/net/neoforged/neoforge/client/ClientHooks.java
Original file line number Diff line number Diff line change
Expand Up @@ -1113,4 +1113,12 @@ public static RecipeBookType[] getFilteredRecipeBookTypeValues() {
}
return RECIPE_BOOK_TYPES;
}

/**
* @return the current local player.
*/
@Nullable
public static Player getPlayer() {
return Minecraft.getInstance().player;
}
}
20 changes: 20 additions & 0 deletions src/main/java/net/neoforged/neoforge/common/BooleanAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@

package net.neoforged.neoforge.common;

import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.ai.attributes.Attribute;
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.TooltipFlag;
import org.jetbrains.annotations.Nullable;

/**
* A boolean attribute only has two states, on or off, represented by a value of 0 (false) or 1 (true).
Expand Down Expand Up @@ -34,4 +38,20 @@ public double sanitizeValue(double value) {
}
return value > 0 ? 1 : 0;
}

@Override
@Nullable
public Component getModifierDescription(@Nullable Player player, AttributeModifier modifier, TooltipFlag flag) {
double amount = modifier.amount();
AttributeModifier.Operation op = modifier.operation();
if (amount == 1 && op == AttributeModifier.Operation.ADD_VALUE) {
return Component.translatable("neoforge.attribute.modifier.enable", Component.translatable(this.getDescriptionId()))
.withStyle(this.getStyle(true));
}
if (amount == -1 && op == AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL) {
return Component.translatable("neoforge.attribute.modifier.disable", Component.translatable(this.getDescriptionId()))
.withStyle(this.getStyle(false));
}
return super.getModifierDescription(player, modifier, flag);
}
}
12 changes: 12 additions & 0 deletions src/main/java/net/neoforged/neoforge/common/CommonHooks.java
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.fml.ModList;
import net.neoforged.fml.ModLoader;
import net.neoforged.fml.common.asm.enumextension.ExtensionInfo;
Expand Down Expand Up @@ -1565,4 +1566,15 @@ public static RecipeBookType[] getFilteredRecipeBookTypeValues() {
}
return RecipeBookType.values();
}

/**
* @return the current local player in {@link Dist#CLIENT}, or null in {@link Dist#DEDICATED_SERVER}.
*/
@Nullable
public static Player getPlayer() {
if (FMLEnvironment.dist == Dist.CLIENT) {
return ClientHooks.getPlayer();
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ public class NeoForgeMod {
SingletonArgumentInfo.contextFree(ModIdArgument::modIdArgument)));

public static final Holder<Attribute> SWIM_SPEED = ATTRIBUTES.register("swim_speed", () -> new RangedAttribute("neoforge.swim_speed", 1.0D, 0.0D, 1024.0D).setSyncable(true));
public static final Holder<Attribute> NAMETAG_DISTANCE = ATTRIBUTES.register("nametag_distance", () -> new RangedAttribute("neoforge.name_tag_distance", 64.0D, 0.0D, 64.0).setSyncable(true));
public static final Holder<Attribute> NAMETAG_DISTANCE = ATTRIBUTES.register("nametag_distance", () -> new RangedAttribute("neoforge.name_tag_distance", 64.0D, 0.0D, 64.0).setSyncable(true).setSentiment(Attribute.Sentiment.NEUTRAL));

/**
* This attribute controls if the player may use creative flight when not in creative mode.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright (c) NeoForged and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/

package net.neoforged.neoforge.common.extensions;

import java.util.function.Consumer;
import net.minecraft.core.Holder;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.TooltipFlag;
import net.neoforged.neoforge.common.BooleanAttribute;
import org.jetbrains.annotations.Nullable;

public interface IAttributeExtension {
/**
* Returns the amount for display in tooltip.
* <p>
* With vanilla default, this returns {@code modifier.amount() * 100} for
* {@link net.minecraft.world.entity.ai.attributes.AttributeModifier.Operation#ADD_MULTIPLIED_BASE} and
* {@link net.minecraft.world.entity.ai.attributes.AttributeModifier.Operation#ADD_MULTIPLIED_TOTAL}
* representing the percentage value, and return {@code modifier.amount()} for
* {@link net.minecraft.world.entity.ai.attributes.AttributeModifier.Operation#ADD_VALUE}
* representing the absolute value.<br>
* Especially, {@link Attributes#KNOCKBACK_RESISTANCE} overrides the
* {@link net.minecraft.world.entity.ai.attributes.AttributeModifier.Operation#ADD_VALUE}
* case, returning {@code modifier.amount() * 10} for a more user-friendly value.
* <p>
* For a full control over the attribute modifier description,
* override the {@link #getModifierDescription(Player, AttributeModifier, TooltipFlag)} instead.
*
* @param modifier the attribute modifier
* @return the amount for display
* @see net.minecraft.world.item.ItemStack#addModifierTooltip(Consumer, Player, Holder, AttributeModifier, TooltipFlag)
* @see net.minecraft.world.item.alchemy.PotionContents#addPotionTooltip(Iterable, Consumer, float, float, TooltipFlag, Component)
*/
default double getAmountForDisplay(AttributeModifier modifier, TooltipFlag flag) {
if (modifier.operation() == AttributeModifier.Operation.ADD_MULTIPLIED_BASE || modifier.operation() == AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL) {
return modifier.amount() * 100;
} else if (this == Attributes.KNOCKBACK_RESISTANCE.value()) {
return modifier.amount() * 10;
} else return modifier.amount();
}

/**
* Returns the custom description for the attribute modifier, or null to fall back to default description.
* <p>
* Useful for adding modifier specific description like {@link Item#BASE_ATTACK_DAMAGE_ID} and {@link Item#BASE_ATTACK_SPEED_ID}.
* <p>
* {@link BooleanAttribute} also overrides this to provide proper description showing enable/disable instead of number values.
*
* @param player the local player, might be null.
* @param modifier the attribute modifier
* @return the custom desription, or null to fall back to default description.
* @see net.minecraft.world.item.ItemStack#addModifierTooltip(Consumer, Player, Holder, AttributeModifier, TooltipFlag)
* @see net.minecraft.world.item.alchemy.PotionContents#addPotionTooltip(Iterable, Consumer, float, float, TooltipFlag, Component)
*/
@Nullable
default Component getModifierDescription(@Nullable Player player, AttributeModifier modifier, TooltipFlag flag) {
return null;
}
}
2 changes: 2 additions & 0 deletions src/main/resources/assets/neoforge/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@
"neoforge.swim_speed": "Swim Speed",
"neoforge.name_tag_distance": "Nametag Render Distance",
"neoforge.creative_flight": "Creative Flight",
"neoforge.attribute.modifier.enable": "Enables %s",
"neoforge.attribute.modifier.disable": "Disables %s",

"fluid_type.minecraft.milk": "Milk",
"fluid_type.minecraft.flowing_milk": "Milk",
Expand Down
Loading