diff --git a/api/src/main/java/net/momirealms/customnameplates/api/placeholder/internal/AdaptiveImageText.java b/api/src/main/java/net/momirealms/customnameplates/api/placeholder/internal/AdaptiveImageText.java index 2336b4e..4d2ad27 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/placeholder/internal/AdaptiveImageText.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/placeholder/internal/AdaptiveImageText.java @@ -19,7 +19,9 @@ package net.momirealms.customnameplates.api.placeholder.internal; import net.momirealms.customnameplates.api.CNPlayer; import net.momirealms.customnameplates.api.CustomNameplates; +import net.momirealms.customnameplates.api.CustomNameplatesAPI; import net.momirealms.customnameplates.api.feature.AdaptiveImage; +import net.momirealms.customnameplates.api.feature.OffsetFont; import net.momirealms.customnameplates.api.feature.PreParsedDynamicText; import net.momirealms.customnameplates.api.helper.AdventureHelper; import org.jetbrains.annotations.ApiStatus; @@ -99,4 +101,9 @@ public class AdaptiveImageText { public String getText(CNPlayer p1, CNPlayer p2) { return preParsedDynamicText.fastCreate(p1).render(p2); } + + @NotNull + public String getTextOffsetCharacters(CNPlayer p1, CNPlayer p2) { + return OffsetFont.createOffsets(CustomNameplatesAPI.getInstance().getTextAdvance(preParsedDynamicText.fastCreate(p1).render(p2))); + } } diff --git a/backend/src/main/java/net/momirealms/customnameplates/backend/placeholder/PlaceholderManagerImpl.java b/backend/src/main/java/net/momirealms/customnameplates/backend/placeholder/PlaceholderManagerImpl.java index 63d6ff6..cd2f8a7 100644 --- a/backend/src/main/java/net/momirealms/customnameplates/backend/placeholder/PlaceholderManagerImpl.java +++ b/backend/src/main/java/net/momirealms/customnameplates/backend/placeholder/PlaceholderManagerImpl.java @@ -512,6 +512,9 @@ public class PlaceholderManagerImpl implements PlaceholderManager { Placeholder placeholder7 = this.registerSharedPlaceholder("%shared_np_background-image_" + id + "%", () -> adaptiveImageText.getImage(null, null)); Placeholder placeholder8 = this.registerPlayerPlaceholder("%np_background-image_" + id + "%", (p) -> adaptiveImageText.getImage(p, p)); Placeholder placeholder9 = this.registerRelationalPlaceholder("%rel_np_background-image_" + id + "%", adaptiveImageText::getImage); + Placeholder placeholder40 = this.registerSharedPlaceholder("%shared_np_background-text-offset_" + id + "%", () -> adaptiveImageText.getTextOffsetCharacters(null, null)); + Placeholder placeholder50 = this.registerPlayerPlaceholder("%np_background-text-offset_" + id + "%", (p) -> adaptiveImageText.getTextOffsetCharacters(p, p)); + Placeholder placeholder60 = this.registerRelationalPlaceholder("%rel_np_background-text-offset_" + id + "%", adaptiveImageText::getTextOffsetCharacters); childrenText.put(placeholder1, list); childrenText.put(placeholder2, list); childrenText.put(placeholder3, list); @@ -521,6 +524,9 @@ public class PlaceholderManagerImpl implements PlaceholderManager { childrenText.put(placeholder7, list); childrenText.put(placeholder8, list); childrenText.put(placeholder9, list); + childrenText.put(placeholder40, list); + childrenText.put(placeholder50, list); + childrenText.put(placeholder60, list); } else { plugin.getPluginLogger().warn("Background [" + bgID + "] not exists"); } diff --git a/platforms/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/BukkitPlatform.java b/platforms/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/BukkitPlatform.java index c6a481b..f451a98 100644 --- a/platforms/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/BukkitPlatform.java +++ b/platforms/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/BukkitPlatform.java @@ -310,15 +310,46 @@ public class BukkitPlatform implements Platform { Object attributeHolder = Reflections.field$ClientboundUpdateAttributesPacket$AttributeSnapshot$attribute.get(attributeSnapshot); Object attribute = Reflections.method$Holder$value.invoke(attributeHolder); String id = (String) Reflections.field$Attribute$id.get(attribute); - if (id.equals("attribute.name.generic.scale") || id.equals("attribute.name.scale")) { + if (id.endsWith("scale")) { double baseValue = (double) Reflections.field$ClientboundUpdateAttributesPacket$AttributeSnapshot$base.get(attributeSnapshot); @SuppressWarnings("unchecked") Collection modifiers = (Collection) Reflections.field$ClientboundUpdateAttributesPacket$AttributeSnapshot$modifiers.get(attributeSnapshot); - for (Object modifier : modifiers) { - double amount = (double) Reflections.field$AttributeModifier$amount.get(modifier); - baseValue += amount; + int left = modifiers.size(); + if (left > 0) { + for (Object modifier : modifiers) { + Object operation = Reflections.field$AttributeModifier$operation.get(modifier); + if (operation == Reflections.instance$AttributeModifier$Operation$ADD_VALUE) { + double amount = (double) Reflections.field$AttributeModifier$amount.get(modifier); + baseValue += amount; + left--; + if (left == 0) break; + } + } } - CustomNameplates.getInstance().getUnlimitedTagManager().onPlayerAttributeSet(another, player, baseValue); + double finalValue = baseValue; + if (left > 0) { + for (Object modifier : modifiers) { + Object operation = Reflections.field$AttributeModifier$operation.get(modifier); + if (operation == Reflections.instance$AttributeModifier$Operation$ADD_MULTIPLIED_BASE) { + double amount = (double) Reflections.field$AttributeModifier$amount.get(modifier); + finalValue += amount * baseValue; + left--; + if (left == 0) break; + } + } + } + if (left > 0) { + for (Object modifier : modifiers) { + Object operation = Reflections.field$AttributeModifier$operation.get(modifier); + if (operation == Reflections.instance$AttributeModifier$Operation$ADD_MULTIPLIED_TOTAL) { + double amount = (double) Reflections.field$AttributeModifier$amount.get(modifier); + finalValue *= 1.0 + amount; + left--; + if (left == 0) break; + } + } + } + CustomNameplates.getInstance().getUnlimitedTagManager().onPlayerAttributeSet(another, player, finalValue); return; } } diff --git a/platforms/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/util/Reflections.java b/platforms/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/util/Reflections.java index 3f29b9e..c4c0fb2 100644 --- a/platforms/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/util/Reflections.java +++ b/platforms/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/util/Reflections.java @@ -1097,4 +1097,37 @@ public class Reflections { } field$ServerConnectionListener$channels = requireNonNull(f); } + + public static final Class clazz$AttributeModifier$Operation = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("world.entity.ai.attributes.AttributeModifier$Operation") + ) + ); + + public static final Method method$AttributeModifier$Operation$values = requireNonNull( + ReflectionUtils.getStaticMethod( + clazz$AttributeModifier$Operation, clazz$AttributeModifier$Operation.arrayType() + ) + ); + + public static final Object instance$AttributeModifier$Operation$ADD_VALUE; + public static final Object instance$AttributeModifier$Operation$ADD_MULTIPLIED_BASE; + public static final Object instance$AttributeModifier$Operation$ADD_MULTIPLIED_TOTAL; + + static { + try { + Object[] values = (Object[]) method$AttributeModifier$Operation$values.invoke(null); + instance$AttributeModifier$Operation$ADD_VALUE = values[0]; + instance$AttributeModifier$Operation$ADD_MULTIPLIED_BASE = values[1]; + instance$AttributeModifier$Operation$ADD_MULTIPLIED_TOTAL = values[2]; + } catch (ReflectiveOperationException e) { + throw new AssertionError(e); + } + } + + public static final Field field$AttributeModifier$operation = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$AttributeModifier, clazz$AttributeModifier$Operation, 0 + ) + ); }