-
-
Save SiverDX/d09f4568b23f13ceddc0e19f1d1be5b4 to your computer and use it in GitHub Desktop.
apoth curios tooltips
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package de.cadentem.trialanderror.core.mods.apotheosis; | |
import com.google.common.collect.Multimap; | |
import de.cadentem.trialanderror.mixin.apotheosis.AttributesLibClientAccess; | |
import net.minecraft.ChatFormatting; | |
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.item.ItemStack; | |
import net.minecraftforge.common.MinecraftForge; | |
import net.minecraftforge.event.entity.player.ItemTooltipEvent; | |
import shadows.apotheosis.adventure.AdventureModule; | |
import shadows.apotheosis.core.attributeslib.api.AddAttributeTooltipsEvent; | |
import shadows.apotheosis.core.attributeslib.api.AttributeHelper; | |
import top.theillusivec4.curios.api.CuriosApi; | |
import top.theillusivec4.curios.api.SlotContext; | |
import top.theillusivec4.curios.common.CuriosHelper; | |
import java.util.*; | |
import static net.minecraft.world.item.ItemStack.ATTRIBUTE_MODIFIER_FORMAT; | |
public class ApothCuriosTooltipHandler { | |
public record StoredData(ItemTooltipEvent event, List<String> slots, List<Component> attributeTooltip, int firstIndex, int secondIndex) { } | |
public static void handleTooltip(final StoredData storedData) { | |
ItemTooltipEvent event = storedData.event(); | |
ItemStack stack = event.getItemStack(); | |
if (!(stack.getItem() instanceof ICurioItem)) { | |
return; | |
} | |
List<Component> list = event.getToolTip(); | |
int markIdx1 = storedData.firstIndex(); | |
int markIdx2 = storedData.secondIndex(); | |
if (markIdx2 > list.size()) { | |
// Mod provided attribute list is not empty and differs from the curios gathered attribute list | |
markIdx1 = -1; | |
markIdx2 = -1; | |
} | |
if (markIdx1 != -1 && markIdx2 != -1) { | |
ListIterator<Component> it = list.listIterator(markIdx1); | |
for (int i = markIdx1; i < markIdx2 + 1; ++i) { | |
it.next(); | |
it.remove(); | |
} | |
if (AttributesLibClientAccess.shouldShowInTooltip(AttributesLibClientAccess.getHideFlags(stack), ItemStack.TooltipPart.MODIFIERS)) { | |
// TODO :: check if this causes duplicates if the slot can be equipped on an apotheosis-considered slot as well (e.g. armor slot) | |
AttributesLibClientAccess.applyModifierTooltips(event.getEntity(), stack, it::add, event.getFlags()); | |
List<String> slots = storedData.slots(); | |
if (slots != null) { | |
for (String slot : slots) { | |
Multimap<Attribute, AttributeModifier> unsorted = CuriosApi.getCuriosHelper().getAttributeModifiers(new SlotContext(slot, event.getEntity(), 0, false, true), UUID.randomUUID(), stack); | |
Multimap<Attribute, AttributeModifier> map = AttributeHelper.sortedMap(); | |
List<Component> slotModifierTooltips = new ArrayList<>(); | |
for (Map.Entry<Attribute, AttributeModifier> ent : unsorted.entries()) { | |
if (ent.getKey() != null && ent.getValue() != null) { | |
if (ent.getKey() instanceof CuriosHelper.SlotAttributeWrapper wrapper) { | |
// Curios slot modifiers are not part of the attribute registry | |
Component slotModifierTooltip = getSlotModifierTooltip(ent.getValue(), wrapper); | |
if (slotModifierTooltip != null) { | |
slotModifierTooltips.add(slotModifierTooltip); | |
} | |
continue; | |
} | |
map.put(ent.getKey(), ent.getValue()); | |
} else { | |
AdventureModule.LOGGER.debug("Detected broken attribute modifier entry on item {}. Attr={}, Modif={}", stack, ent.getKey(), ent.getValue()); | |
} | |
} | |
AttributesLibClientAccess.applyTextFor(event.getEntity(), stack, it::add, map, "ignore:" + slot, new HashSet<>(), event.getFlags()); | |
for (Component slotModifier : slotModifierTooltips) { | |
it.add(slotModifier); | |
} | |
} | |
} | |
} | |
MinecraftForge.EVENT_BUS.post(new AddAttributeTooltipsEvent(stack, event.getEntity(), list, it, event.getFlags())); | |
} | |
} | |
private static Component getSlotModifierTooltip(final AttributeModifier modifier, CuriosHelper.SlotAttributeWrapper wrapper) { | |
Component component = null; | |
if (modifier.getAmount() > 0) { | |
component = Component.translatable( | |
"curios.modifiers.slots.plus." + | |
AttributeModifier.Operation.ADDITION.toValue(), | |
ATTRIBUTE_MODIFIER_FORMAT.format(modifier.getAmount()), | |
Component.translatable("curios.identifier." + wrapper.identifier)) | |
.withStyle(ChatFormatting.BLUE); | |
} else if (modifier.getAmount() < 0) { | |
component = Component.translatable( | |
"curios.modifiers.slots.take." + | |
AttributeModifier.Operation.ADDITION.toValue(), | |
ATTRIBUTE_MODIFIER_FORMAT.format(modifier.getAmount()), | |
Component.translatable("curios.identifier." + wrapper.identifier)) | |
.withStyle(ChatFormatting.RED); | |
} | |
return component; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package de.cadentem.trialanderror.mixin.apotheosis; | |
import com.llamalad7.mixinextras.sugar.Local; | |
import net.minecraft.ChatFormatting; | |
import net.minecraft.network.chat.Component; | |
import org.spongepowered.asm.mixin.Mixin; | |
import org.spongepowered.asm.mixin.injection.At; | |
import org.spongepowered.asm.mixin.injection.ModifyArg; | |
import shadows.apotheosis.core.attributeslib.client.AttributesLibClient; | |
@Mixin(value = AttributesLibClient.class, remap = false) | |
public class AttributesLibClientMixin { | |
@SuppressWarnings("unchecked") | |
@ModifyArg(method = "applyTextFor", at = @At(value = "INVOKE", target = "Ljava/util/function/Consumer;accept(Ljava/lang/Object;)V", ordinal = 1)) | |
private static <T> T trialanderror$addCuriosGroupTooltip(final T component, @Local(argsOnly = true) final String group) { | |
if (group.startsWith("ignore:")) { | |
return (T) Component.translatable("curios.modifiers." + group.substring(group.indexOf(":") + 1)).withStyle(ChatFormatting.GOLD); | |
} | |
return component; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package de.cadentem.trialanderror.mixin.apotheosis; | |
import com.google.common.collect.Multimap; | |
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.ItemStack; | |
import net.minecraft.world.item.TooltipFlag; | |
import org.spongepowered.asm.mixin.Mixin; | |
import org.spongepowered.asm.mixin.gen.Invoker; | |
import shadows.apotheosis.core.attributeslib.client.AttributesLibClient; | |
import javax.annotation.Nullable; | |
import java.util.Set; | |
import java.util.UUID; | |
import java.util.function.Consumer; | |
@Mixin(value = AttributesLibClient.class, remap = false) | |
public interface AttributesLibClientAccess { | |
@Invoker("getHideFlags") | |
static int getHideFlags(final ItemStack stack) { | |
throw new AssertionError(); | |
} | |
@Invoker("shouldShowInTooltip") | |
static boolean shouldShowInTooltip(int hideFlags, final ItemStack.TooltipPart part) { | |
throw new AssertionError(); | |
} | |
@Invoker("applyModifierTooltips") | |
static void applyModifierTooltips(@Nullable final Player player, final ItemStack stack, final Consumer<Component> tooltip, final TooltipFlag flag) { | |
throw new AssertionError(); | |
} | |
@Invoker("applyTextFor") | |
static void applyTextFor(@Nullable final Player player, final ItemStack stack, final Consumer<Component> tooltip, final Multimap<Attribute, AttributeModifier> modifierMap, final String group, final Set<UUID> skips, final TooltipFlag flag) { | |
throw new AssertionError(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package de.cadentem.trialanderror.mixin.curios; | |
import com.llamalad7.mixinextras.sugar.Local; | |
import de.cadentem.trialanderror.core.mods.apotheosis.ApothCuriosTooltipHandler; | |
import net.minecraft.network.chat.Component; | |
import net.minecraftforge.event.entity.player.ItemTooltipEvent; | |
import org.spongepowered.asm.mixin.Mixin; | |
import org.spongepowered.asm.mixin.Unique; | |
import org.spongepowered.asm.mixin.injection.At; | |
import org.spongepowered.asm.mixin.injection.Inject; | |
import org.spongepowered.asm.mixin.injection.ModifyVariable; | |
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; | |
import shadows.apotheosis.adventure.AdventureModule; | |
import top.theillusivec4.curios.client.ClientEventHandler; | |
import java.util.ArrayList; | |
import java.util.List; | |
/** Better tooltip handling for Apothic Curios */ | |
@Mixin(value = ClientEventHandler.class, remap = false) | |
public class ClientEventHandlerMixin { | |
@Unique | |
private static final ThreadLocal<ApothCuriosTooltipHandler.StoredData> trialanderror$storedData = new ThreadLocal<>(); | |
@Inject(method = "onTooltip", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/common/util/LazyOptional;ifPresent(Lnet/minecraftforge/common/util/NonNullConsumer;)V", ordinal = 1, shift = At.Shift.BEFORE)) | |
private void trialanderror$storeData(final ItemTooltipEvent event, final CallbackInfo callback, @Local(name = "slots") final List<String> slots, @Local(name = "attributeTooltip") final List<Component> attributeTooltip) { | |
int currentIndex = event.getToolTip().size() - 1; | |
int nextIndex = currentIndex + attributeTooltip.size(); | |
if (attributeTooltip.isEmpty() || nextIndex < currentIndex) { | |
currentIndex = -1; | |
nextIndex = -1; | |
} | |
// Some mods seem to clear the attribute list when receiving it | |
trialanderror$storedData.set(new ApothCuriosTooltipHandler.StoredData(event, slots, new ArrayList<>(attributeTooltip), currentIndex, nextIndex)); | |
} | |
/** Some items don't return all attributes */ | |
@ModifyVariable(method = "lambda$onTooltip$1", at = @At("STORE"), ordinal = 2) | |
private static List<Component> trialanderror$setActualAttributeList(final List<Component> tooltips) { | |
List<Component> attributeTooltip = trialanderror$storedData.get().attributeTooltip(); | |
if (tooltips.isEmpty() && !attributeTooltip.isEmpty()) { | |
return attributeTooltip; | |
} else if (tooltips.size() != attributeTooltip.size()) { | |
// FIXME :: Only for dev (due to spam) | |
AdventureModule.LOGGER.debug("Attribute list sizes do not match:\n- Vanilla: [{}]\n- Mod: [{}]", attributeTooltip, tooltips); | |
} | |
return tooltips; | |
} | |
@Inject(method = "onTooltip", at = @At(value = "TAIL")) | |
private void trialanderror$handleTooltip(final ItemTooltipEvent event, final CallbackInfo callback) { | |
ApothCuriosTooltipHandler.StoredData storedData = trialanderror$storedData.get(); | |
if (storedData != null) { | |
ApothCuriosTooltipHandler.handleTooltip(storedData); | |
} | |
trialanderror$storedData.remove(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment