Skip to content

Commit

Permalink
[Chat components] Implement shadowColor field (currently only used fo…
Browse files Browse the repository at this point in the history
…r converting components created using MiniMessage)
  • Loading branch information
NEZNAMY committed Feb 2, 2025
1 parent 11cc1c3 commit 79e56c6
Show file tree
Hide file tree
Showing 11 changed files with 124 additions and 101 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import org.jetbrains.annotations.NotNull;

/**
* Component converter using direct mojang-mapped code for versions 1.20.5+.
* Component converter using direct mojang-mapped code for versions 1.21.4+.
*/
@SuppressWarnings("unused") // Used via reflection
public class PaperComponentConverter extends ComponentConverter {
Expand All @@ -32,14 +32,16 @@ public Component convert(@NotNull TabComponent component) {

// Component style
ChatModifier modifier = component.getModifier();
nmsComponent.setStyle(Style.EMPTY
Style style = Style.EMPTY
.withColor(modifier.getColor() == null ? null : TextColor.fromRgb(modifier.getColor().getRgb()))
.withBold(modifier.getBold())
.withItalic(modifier.getItalic())
.withUnderlined(modifier.getUnderlined())
.withStrikethrough(modifier.getStrikethrough())
.withObfuscated(modifier.getObfuscated())
.withFont(modifier.getFont() == null ? null : ResourceLocation.tryParse(modifier.getFont())));
.withFont(modifier.getFont() == null ? null : ResourceLocation.tryParse(modifier.getFont()));
if (modifier.getShadowColor() != null) style = style.withShadowColor(modifier.getShadowColor()); // withShadowColor takes int instead of Integer, bug?
nmsComponent.setStyle(style);

// Extra
for (TabComponent extra : component.getExtra()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,12 @@
import java.util.EnumSet;

/**
* Interface for converting TAB component into NMS components (1.7+).
* Interface for converting TAB components into NMS components (1.7+).
*/
public abstract class ComponentConverter {

/** Versions supported by paper module that uses direct mojang-mapped NMS for latest MC version */
/** Versions supported by paper module that uses direct mojang-mapped NMS */
private static final EnumSet<ProtocolVersion> paperNativeVersions = EnumSet.of(
ProtocolVersion.V1_20_5,
ProtocolVersion.V1_20_6,
ProtocolVersion.V1_21,
ProtocolVersion.V1_21_1,
ProtocolVersion.V1_21_2,
ProtocolVersion.V1_21_3,
ProtocolVersion.V1_21_4
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,21 @@
import me.neznamy.tab.shared.util.ReflectionUtils;
import me.neznamy.tab.shared.util.function.FunctionWithException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.function.Function;

/**
* Class for converting TAB component into NMS components (1.7+).
* Class for converting TAB components into NMS components (1.7+).
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public class ReflectionComponentConverter extends ComponentConverter {

private final FunctionWithException<String, Object> newTextComponent;
private final FunctionWithException<String, Object> newTranslatableComponent;
private final FunctionWithException<String, Object> newKeybindComponent;
private final Function<ChatModifier, Object> convertModifier;

private final Class<?> ChatModifier = BukkitReflection.getClass("network.chat.Style", "network.chat.ChatModifier", "ChatModifier");
private final Class<Enum> EnumChatFormat = (Class<Enum>) BukkitReflection.getClass("ChatFormatting", "EnumChatFormat");
Expand All @@ -44,7 +41,7 @@ public class ReflectionComponentConverter extends ComponentConverter {
private Method ResourceLocation_tryParse;

/**
* Constructs new instance and loads all NMS classes, constructors and methods.
* Constructs new instance and loads all NMS classes, constructors, and methods.
*
* @throws ReflectiveOperationException
* If something failed
Expand Down Expand Up @@ -97,11 +94,9 @@ public ReflectionComponentConverter() throws ReflectiveOperationException {
newChatModifier = ReflectionUtils.setAccessible(ChatModifier.getDeclaredConstructor(chatHexColor, Boolean.class, Boolean.class, Boolean.class,
Boolean.class, Boolean.class, chatClickable, chatHoverable, String.class, ResourceLocation));
}
convertModifier = this::createModifierModern;
} else {
newChatModifier = ChatModifier.getConstructor();
ChatModifier_setColor = ReflectionUtils.getOnlyMethod(ChatModifier, ChatModifier, EnumChatFormat);
convertModifier = this::createModifierLegacy;
}
}

Expand All @@ -122,7 +117,7 @@ public Object convert(@NotNull TabComponent component) {
}

// Component style
Component_modifier.set(nmsComponent, convertModifier.apply(component.getModifier()));
Component_modifier.set(nmsComponent, convertStyle(component.getModifier()));

// Extra
for (TabComponent extra : component.getExtra()) {
Expand All @@ -132,63 +127,46 @@ public Object convert(@NotNull TabComponent component) {
}

@SneakyThrows
private Object createModifierModern(@NotNull ChatModifier modifier) {
return newStyleModern(
modifier.getColor() == null ? null : ChatHexColor_fromRGB.invoke(null, modifier.getColor().getRgb()),
modifier.getBold(),
modifier.getItalic(),
modifier.getUnderlined(),
modifier.getStrikethrough(),
modifier.getObfuscated(),
modifier.getFont()
);
}

@SneakyThrows
private Object createModifierLegacy(@NotNull ChatModifier modifier) {
Object nmsModifier = newChatModifier.newInstance();
if (modifier.getColor() != null) {
ChatModifier_setColor.invoke(nmsModifier, Enum.valueOf(EnumChatFormat, modifier.getColor().getLegacyColor().name()));
}
magicCodes.get(0).set(nmsModifier, modifier.getBold());
magicCodes.get(1).set(nmsModifier, modifier.getItalic());
magicCodes.get(2).set(nmsModifier, modifier.getStrikethrough());
magicCodes.get(3).set(nmsModifier, modifier.getUnderlined());
magicCodes.get(4).set(nmsModifier, modifier.getObfuscated());
return nmsModifier;
}

@SneakyThrows
@NotNull
private Object newStyleModern(@Nullable Object color, @Nullable Boolean bold, @Nullable Boolean italic, @Nullable Boolean underlined,
@Nullable Boolean strikethrough, @Nullable Boolean obfuscated, @Nullable String font) {
private Object convertStyle(@NotNull ChatModifier modifier) {
Object color = modifier.getColor() == null ? null : ChatHexColor_fromRGB.invoke(null, modifier.getColor().getRgb());
if (BukkitReflection.is1_21_4Plus()) {
return newChatModifier.newInstance(
color,
null,
bold,
italic,
underlined,
strikethrough,
obfuscated,
modifier.getShadowColor(),
modifier.getBold(),
modifier.getItalic(),
modifier.getItalic(),
modifier.getUnderlined(),
modifier.getObfuscated(),
null,
null,
null,
font == null ? null : ResourceLocation_tryParse.invoke(null, font)
modifier.getFont() == null ? null : ResourceLocation_tryParse.invoke(null, modifier.getFont())
);
} else {
} else if (BukkitReflection.getMinorVersion() >= 16) {
return newChatModifier.newInstance(
color,
bold,
italic,
underlined,
strikethrough,
obfuscated,
modifier.getBold(),
modifier.getItalic(),
modifier.getItalic(),
modifier.getUnderlined(),
modifier.getObfuscated(),
null,
null,
null,
font == null ? null : ResourceLocation_tryParse.invoke(null, font)
modifier.getFont() == null ? null : ResourceLocation_tryParse.invoke(null, modifier.getFont())
);
} else {
Object nmsModifier = newChatModifier.newInstance();
if (modifier.getColor() != null) {
ChatModifier_setColor.invoke(nmsModifier, Enum.valueOf(EnumChatFormat, modifier.getColor().getLegacyColor().name()));
}
magicCodes.get(0).set(nmsModifier, modifier.getBold());
magicCodes.get(1).set(nmsModifier, modifier.getItalic());
magicCodes.get(2).set(nmsModifier, modifier.getStrikethrough());
magicCodes.get(3).set(nmsModifier, modifier.getUnderlined());
magicCodes.get(4).set(nmsModifier, modifier.getObfuscated());
return nmsModifier;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.awt.Color;
import java.io.File;

/**
Expand Down Expand Up @@ -154,6 +155,12 @@ public BaseComponent convertComponent(@NotNull TabComponent component, boolean m
bComponent.setColor(ChatColor.of(modifier.getColor().getLegacyColor().name()));
}
}
bComponent.setShadowColor(modifier.getShadowColor() == null ? null : new Color(
(modifier.getShadowColor() >> 16) & 0xFF,
(modifier.getShadowColor() >> 8) & 0xFF,
(modifier.getShadowColor()) & 0xFF,
(modifier.getShadowColor() >> 24) & 0xFF
));
bComponent.setBold(modifier.getBold());
bComponent.setItalic(modifier.getItalic());
bComponent.setObfuscated(modifier.getObfuscated());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ public static void addSibling(@NotNull Component parent, @NotNull Component chil
*/
@NotNull
public static Style convertModifier(@NotNull ChatModifier modifier) {
if (serverVersion.getMinorVersion() >= 16) return loaderLatest.convertModifier(modifier);
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_21_4.getNetworkId()) return loaderLatest.convertModifier(modifier);
if (serverVersion.getMinorVersion() >= 16) return loader1_21_3.convertModifier(modifier);
return loader1_14_4.convertModifier(modifier);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,16 @@ public Component newKeybindComponent(@NotNull String key) {
@Override
@NotNull
public Style convertModifier(@NotNull ChatModifier modifier) {
return Style.EMPTY
Style style = Style.EMPTY
.withColor(modifier.getColor() == null ? null : TextColor.fromRgb(modifier.getColor().getRgb()))
.withBold(modifier.getBold())
.withItalic(modifier.getItalic())
.withUnderlined(modifier.getUnderlined())
.withStrikethrough(modifier.getStrikethrough())
.withObfuscated(modifier.getObfuscated())
.withFont(modifier.getFont() == null ? null : ResourceLocation.tryParse(modifier.getFont()));
if (modifier.getShadowColor() != null) style = style.withShadowColor(modifier.getShadowColor());
return style;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@
import me.neznamy.tab.platforms.fabric.FabricTabList;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.chat.ChatModifier;
import me.neznamy.tab.shared.platform.TabList;
import me.neznamy.tab.shared.platform.TabPlayer;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.Style;
import net.minecraft.network.chat.TextColor;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.GameType;
import org.jetbrains.annotations.NotNull;

Expand Down Expand Up @@ -72,6 +76,19 @@ public Packet<?> buildTabListPacket(@NotNull TabList.Action action, @NotNull Fab
return packet;
}

@Override
@NotNull
public Style convertModifier(@NotNull ChatModifier modifier) {
return Style.EMPTY
.withColor(modifier.getColor() == null ? null : TextColor.fromRgb(modifier.getColor().getRgb()))
.withBold(modifier.getBold())
.withItalic(modifier.getItalic())
.withUnderlined(modifier.getUnderlined())
.withStrikethrough(modifier.getStrikethrough())
.withObfuscated(modifier.getObfuscated())
.withFont(modifier.getFont() == null ? null : ResourceLocation.tryParse(modifier.getFont()));
}

private static class Register1_19_3 {

static final Map<TabList.Action, EnumSet<ClientboundPlayerInfoUpdatePacket.Action>> actionMap = createActionMap();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package me.neznamy.tab.shared.chat;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.jetbrains.annotations.NotNull;
Expand All @@ -10,9 +11,11 @@
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ChatModifier {

@Nullable private TextColor color;
@Nullable private Integer shadowColor; // ARGB
@Nullable private Boolean bold;
@Nullable private Boolean italic;
@Nullable private Boolean obfuscated;
Expand All @@ -21,13 +24,14 @@ public class ChatModifier {
@Nullable private String font;

/**
* Constructs a copy of provided modifier.
* Constructs a copy of the provided modifier.
*
* @param modifier
* Modifier to copy
*/
public ChatModifier(@NotNull ChatModifier modifier) {
color = modifier.color;
shadowColor = modifier.shadowColor;
bold = modifier.bold;
italic = modifier.italic;
obfuscated = modifier.obfuscated;
Expand Down
10 changes: 10 additions & 0 deletions shared/src/main/java/me/neznamy/tab/shared/chat/TextColor.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,16 @@ private TextColor(@NotNull EnumChatFormat legacyColor) {
LEGACY_COLORS.put(legacyColor.getCharacter(), this);
}

/**
* Constructs new instance with given RGB value.
*
* @param rgb
* RGB value
*/
public TextColor(int rgb) {
this.rgb = rgb;
}

/**
* Constructs new instance with red, green and blue values
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ public abstract class TabComponent {
/** Chat modifier containing color, magic codes, hover and click event */
@NotNull
@Getter
@Setter
protected ChatModifier modifier = new ChatModifier();

/** Extra components used in "extra" field */
Expand Down
Loading

0 comments on commit 79e56c6

Please sign in to comment.