Начинающий
- Статус
- Оффлайн
- Регистрация
- 26 Янв 2025
- Сообщения
- 21
- Реакции
- 0
- Выберите загрузчик игры
- Fabric
Всем привет! Сливаю вам скорборд из своего клиента так как мне лень его дальше писать
ss
LegacyTextHelper.java:
package moscow.rockstar.utility.game;
import net.minecraft.text.MutableText;
import net.minecraft.text.Style;
import net.minecraft.text.Text;
import net.minecraft.text.TextColor;
import net.minecraft.util.Formatting;
import java.util.ArrayList;
import java.util.List;
public final class LegacyTextHelper {
private static final char LEGACY_PREFIX_SECTION = '\u00A7';
private static final char LEGACY_PREFIX_AMP = '&';
private static final char LEGACY_PREFIX_DOLLAR = '$';
public static Text resolve(Text text, int defaultColor) {
if (text == null) {
return Text.empty();
}
int baseColor = defaultColor & 0xFFFFFF;
String raw = extractRaw(text);
if (containsLegacyCodes(raw)) {
return parse(raw, baseColor);
}
if (hasExplicitColor(text)) {
return text;
}
return applyDefaultColor(text, baseColor);
}
public static List<ColoredSegment> parseSegments(String input, int defaultColor) {
List<ColoredSegment> segments = new ArrayList<>();
if (input == null || input.isEmpty()) {
return segments;
}
StringBuilder buffer = new StringBuilder();
int currentColor = 0xFF000000 | (defaultColor & 0xFFFFFF);
int baseColor = currentColor;
int length = input.length();
for (int i = 0; i < length; i++) {
char c = input.charAt(i);
if (c == '<' || c == '{') {
char end = c == '<' ? '>' : '}';
if (isWrappedHexSequence(input, i, end)) {
flushSegment(buffer, segments, currentColor);
int rgb = parseHexColorPlain(input, i + 2);
currentColor = 0xFF000000 | rgb;
i += 8;
continue;
}
}
if (isLegacyPrefix(c) && i + 1 < length) {
char code = Character.toLowerCase(input.charAt(i + 1));
if (code == 'x' && isValidHexSequence(input, i)) {
flushSegment(buffer, segments, currentColor);
int rgb = parseHexColorLegacy(input, i);
currentColor = 0xFF000000 | rgb;
i += 13;
continue;
}
if (code == '#' && isHexSequence(input, i + 2, 6)) {
flushSegment(buffer, segments, currentColor);
int rgb = parseHexColorPlain(input, i + 2);
currentColor = 0xFF000000 | rgb;
i += 7;
continue;
}
Formatting formatting = Formatting.byCode(code);
if (formatting != null) {
flushSegment(buffer, segments, currentColor);
if (formatting == Formatting.RESET) {
currentColor = baseColor;
} else if (formatting.isColor()) {
Integer rgb = formatting.getColorValue();
if (rgb != null) {
currentColor = 0xFF000000 | rgb;
}
}
i++;
continue;
}
}
buffer.append(c);
}
flushSegment(buffer, segments, currentColor);
return segments;
}
public static String extractRaw(Text text) {
if (text == null) {
return "";
}
StringBuilder visited = new StringBuilder();
text.visit((style, string) -> {
if (style != null && style.getColor() != null) {
int rgb = style.getColor().getRgb() & 0xFFFFFF;
String hex = Integer.toHexString(rgb);
visited.append("&#");
for (int i = 0; i < 6 - hex.length(); i++) {
visited.append('0');
}
visited.append(hex);
}
visited.append(string);
return java.util.Optional.empty();
}, Style.EMPTY);
return visited.toString();
}
public static boolean containsLegacyCodes(String input) {
if (input == null || input.length() < 2) {
return false;
}
int length = input.length();
for (int i = 0; i < length - 1; i++) {
char c = input.charAt(i);
if (c == '<' || c == '{') {
if (isWrappedHexSequence(input, i, c == '<' ? '>' : '}')) {
return true;
}
continue;
}
if (!isLegacyPrefix(c)) {
continue;
}
char code = Character.toLowerCase(input.charAt(i + 1));
if (isLegacyCode(code)) {
return true;
}
if (code == 'x' && isValidHexSequence(input, i)) {
return true;
}
if (code == '#' && isHexSequence(input, i + 2, 6)) {
return true;
}
}
return false;
}
public static Text parse(String input, int defaultColor) {
if (input == null || input.isEmpty()) {
return Text.empty();
}
MutableText result = Text.empty();
StringBuilder buffer = new StringBuilder();
int baseColor = defaultColor & 0xFFFFFF;
Style current = Style.EMPTY.withColor(TextColor.fromRgb(baseColor));
int length = input.length();
for (int i = 0; i < length; i++) {
char c = input.charAt(i);
if (c == '<' || c == '{') {
char end = c == '<' ? '>' : '}';
if (isWrappedHexSequence(input, i, end)) {
flush(buffer, result, current);
int rgb = parseHexColorPlain(input, i + 2);
current = current.withColor(TextColor.fromRgb(rgb));
i += 8;
continue;
}
}
if (isLegacyPrefix(c) && i + 1 < length) {
char code = Character.toLowerCase(input.charAt(i + 1));
if (code == 'x' && isValidHexSequence(input, i)) {
flush(buffer, result, current);
int rgb = parseHexColorLegacy(input, i);
current = current.withColor(TextColor.fromRgb(rgb));
i += 13;
continue;
}
if (code == '#' && isHexSequence(input, i + 2, 6)) {
flush(buffer, result, current);
int rgb = parseHexColorPlain(input, i + 2);
current = current.withColor(TextColor.fromRgb(rgb));
i += 7;
continue;
}
Formatting formatting = Formatting.byCode(code);
if (formatting != null) {
flush(buffer, result, current);
if (formatting == Formatting.RESET) {
current = Style.EMPTY.withColor(TextColor.fromRgb(baseColor));
} else if (formatting.isColor()) {
current = Style.EMPTY.withFormatting(formatting);
} else {
current = current.withFormatting(formatting);
}
i++;
continue;
}
}
buffer.append(c);
}
flush(buffer, result, current);
return result;
}
private static void flush(StringBuilder buffer, MutableText result, Style style) {
if (buffer.length() == 0) {
return;
}
result.append(Text.literal(buffer.toString()).setStyle(style));
buffer.setLength(0);
}
private static void flushSegment(StringBuilder buffer, List<ColoredSegment> segments, int color) {
if (buffer.length() == 0) {
return;
}
segments.add(new ColoredSegment(buffer.toString(), color));
buffer.setLength(0);
}
private static boolean isLegacyPrefix(char c) {
return c == LEGACY_PREFIX_SECTION || c == LEGACY_PREFIX_AMP || c == LEGACY_PREFIX_DOLLAR;
}
private static boolean isLegacyCode(char code) {
return (code >= '0' && code <= '9')
|| (code >= 'a' && code <= 'f')
|| code == 'k'
|| code == 'l'
|| code == 'm'
|| code == 'n'
|| code == 'o'
|| code == 'r';
}
private static boolean isValidHexSequence(String input, int startIndex) {
int length = input.length();
if (startIndex + 13 >= length) {
return false;
}
for (int i = 0; i < 6; i++) {
int base = startIndex + 2 + i * 2;
char prefix = input.charAt(base);
char hex = input.charAt(base + 1);
if (!isLegacyPrefix(prefix) || !isHexDigit(hex)) {
return false;
}
}
return true;
}
private static int parseHexColorLegacy(String input, int startIndex) {
StringBuilder hex = new StringBuilder(6);
for (int i = 0; i < 6; i++) {
int base = startIndex + 2 + i * 2;
hex.append(input.charAt(base + 1));
}
return Integer.parseInt(hex.toString(), 16);
}
private static int parseHexColorPlain(String input, int startIndex) {
return Integer.parseInt(input.substring(startIndex, startIndex + 6), 16);
}
private static boolean isHexDigit(char c) {
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
}
private static boolean isHexSequence(String input, int start, int length) {
if (start < 0 || start + length > input.length()) {
return false;
}
for (int i = 0; i < length; i++) {
if (!isHexDigit(input.charAt(start + i))) {
return false;
}
}
return true;
}
private static boolean isWrappedHexSequence(String input, int startIndex, char endChar) {
if (startIndex + 8 >= input.length()) {
return false;
}
if (input.charAt(startIndex + 1) != '#') {
return false;
}
if (!isHexSequence(input, startIndex + 2, 6)) {
return false;
}
return input.charAt(startIndex + 8) == endChar;
}
private static Text applyDefaultColor(Text text, int defaultColor) {
if (hasExplicitColor(text))
return text;
Style base = Style.EMPTY.withColor(TextColor.fromRgb(defaultColor));
return Text.literal("").setStyle(base).append(text);
}
private static boolean hasExplicitColor(Text text) {
final boolean[] hasColor = new boolean[] { false };
text.visit((style, string) -> {
if (style.getColor() != null) {
hasColor[0] = true;
return java.util.Optional.of(true);
}
return java.util.Optional.empty();
}, Style.EMPTY);
return hasColor[0];
}
private LegacyTextHelper() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}
public record ColoredSegment(String text, int color) {
}
}
ScoreboardHud.java:
package moscow.rockstar.ui.hud.impl;
import java.lang.reflect.Method;
import java.util.Comparator;
import java.util.List;
import moscow.rockstar.framework.base.UIContext;
import moscow.rockstar.framework.msdf.Font;
import moscow.rockstar.framework.msdf.Fonts;
import moscow.rockstar.framework.msdf.FormattedTextProcessor;
import moscow.rockstar.framework.objects.BorderRadius;
import moscow.rockstar.Rockstar;
import moscow.rockstar.systems.modules.modules.visuals.Interface;
import moscow.rockstar.systems.theme.Theme;
import moscow.rockstar.ui.hud.HudElement;
import moscow.rockstar.utility.colors.ColorRGBA;
import moscow.rockstar.utility.colors.Colors;
import moscow.rockstar.framework.objects.gradient.impl.HorizontalGradient;
import moscow.rockstar.utility.game.LegacyTextHelper;
import moscow.rockstar.systems.setting.settings.SliderSetting;
import moscow.rockstar.utility.interfaces.IScaledResolution;
import net.minecraft.client.gui.screen.ChatScreen;
import net.minecraft.scoreboard.Scoreboard;
import net.minecraft.scoreboard.ScoreboardDisplaySlot;
import net.minecraft.scoreboard.ScoreboardEntry;
import net.minecraft.scoreboard.ScoreboardObjective;
import net.minecraft.scoreboard.Team;
import net.minecraft.scoreboard.number.StyledNumberFormat;
import net.minecraft.text.Text;
public class ScoreboardHud extends HudElement implements IScaledResolution {
private static final float TITLE_SIZE = 8.8F;
private static final float LINE_SIZE = 7.8F;
private static final float PAD_X = 16.0F;
private static final float PAD_Y = 7.0F;
private static final float LINE_GAP = 5.0F;
private static final float VALUE_GAP = 16.0F;
private boolean initialPos;
private float lastSavedX = Float.NaN;
private float lastSavedY = Float.NaN;
private final SliderSetting scaleSetting = new SliderSetting(this, "\u0420\u0430\u0437\u043c\u0435\u0440").min(0.7F)
.max(1.4F).step(0.05F).currentValue(1.0F);
public ScoreboardHud() {
super("\u0421\u043a\u043e\u0440\u0431\u043e\u0440\u0434", "icons/hud/world.png");
}
@Override
public void update(UIContext context) {
Layout layout = buildLayout();
this.width = layout.width;
this.height = layout.height;
if (!this.initialPos && this.x == 0.0F && this.y == 0.0F) {
this.x = Math.max(0.0F, sr.getScaledWidth() - this.width - 40.0F);
this.y = 40.0F;
this.initialPos = true;
}
if (!this.isDragging() && (this.x != this.lastSavedX || this.y != this.lastSavedY)) {
this.lastSavedX = this.x;
this.lastSavedY = this.y;
Rockstar.getInstance().getFileManager().writeFile("client");
}
super.update(context);
}
@Override
protected void renderComponent(UIContext context) {
Layout layout = buildLayout();
float x = this.x;
float y = this.y;
Font titleFont = getTitleFont();
Font lineFont = getLineFont();
boolean dark = Rockstar.getInstance().getThemeManager().getCurrentTheme() == Theme.DARK;
ColorRGBA bgColor = Colors.getBackgroundColor()
.withAlpha(255.0F * (dark ? 0.8F - 0.6F * Interface.glass() : 0.7F));
context.drawShadow(
x - 5.0F,
y - 5.0F,
layout.width + 10.0F,
layout.height + 10.0F,
15.0F,
BorderRadius.all(6.0F),
ColorRGBA.BLACK.withAlpha(63.75F));
if (Interface.showMinimalizm()) {
context.drawBlurredRect(
x,
y,
layout.width,
layout.height,
45.0F,
7.0F,
BorderRadius.all(6.0F),
ColorRGBA.WHITE.withAlpha(255.0F * Interface.minimalizm()));
}
if (Interface.showGlass()) {
context.drawLiquidGlass(
x,
y,
layout.width,
layout.height,
7.0F,
0.08F,
BorderRadius.all(6.0F),
ColorRGBA.WHITE.withAlpha(255.0F * Interface.glass()));
}
context.drawSquircle(x, y, layout.width, layout.height, 7.0F, BorderRadius.all(6.0F), bgColor);
float lineH = Math.max(1.0F, 1.4F * layout.scale);
ColorRGBA accent = Colors.ACCENT.withAlpha(170.0F);
ColorRGBA secondary = Colors.ACCENT.withAlpha(50.0F);
context.drawRoundedRect(x + layout.padX * 0.6F, y + layout.headerHeight - lineH - layout.padY * 0.3F,
layout.width - layout.padX * 1.2F, lineH, BorderRadius.all(lineH / 2.0F),
new HorizontalGradient(accent, secondary));
float titleX = x + PAD_X;
for (Segment segment : layout.title.segments) {
context.drawText(titleFont, segment.text, titleX, y + PAD_Y, ColorRGBA.fromInt(segment.color));
titleX += titleFont.width(segment.text);
}
float lineY = y + layout.headerHeight;
for (EntryLine line : layout.lines) {
float rowY = lineY + (layout.lineHeight - lineFont.height()) / 2.0F;
float valueWidth = line.value.width;
float nameX = x + PAD_X;
for (Segment segment : line.name.segments) {
context.drawText(lineFont, segment.text, nameX, rowY, ColorRGBA.fromInt(segment.color));
nameX += lineFont.width(segment.text);
}
float valueX = x + layout.width - PAD_X - valueWidth;
for (Segment segment : line.value.segments) {
context.drawText(lineFont, segment.text, valueX, rowY, ColorRGBA.fromInt(segment.color));
valueX += lineFont.width(segment.text);
}
lineY += layout.lineHeight;
}
}
@Override
public boolean show() {
return getObjective() != null;
}
private Layout buildLayout() {
int defaultTextColor = Colors.getTextColor().getRGB() & 0xFFFFFF;
float scale = this.scaleSetting.getCurrentValue();
Font titleFont = getTitleFont();
Font lineFont = getLineFont();
ScoreboardObjective objective = getObjective();
if (objective == null) {
return new Layout(new Segments(List.of(), 0), List.of(), 0, 0, 0, 0, scale, PAD_X, PAD_Y);
}
Text titleSource = objective.getDisplayName();
Segments title = buildSegments(titleSource, titleFont, defaultTextColor);
float maxWidth = title.width;
List<EntryLine> lines = objective.getScoreboard().getScoreboardEntries(objective).stream()
.filter(entry -> entry != null && !entry.hidden())
.sorted(Comparator.comparingInt(ScoreboardEntry::value).reversed().thenComparing(ScoreboardEntry::owner,
String::compareToIgnoreCase))
.limit(25)
.map(entry -> {
Segments name = buildSegments(resolveNameText(objective.getScoreboard(), entry), lineFont,
defaultTextColor);
Segments value = buildSegments(resolveValueText(objective, entry), lineFont, defaultTextColor);
return new EntryLine(name, value);
})
.toList();
for (EntryLine line : lines) {
float rowWidth = line.name.width + line.value.width + VALUE_GAP;
maxWidth = Math.max(maxWidth, rowWidth);
}
float headerHeight = titleFont.height() + PAD_Y * 2.0F;
float lineHeight = lineFont.height() + LINE_GAP;
float totalHeight = headerHeight + lines.size() * lineHeight + PAD_Y;
float extraWidth = 16.0F;
float totalWidth = maxWidth + PAD_X * 2.0F + extraWidth;
totalWidth *= scale;
totalHeight *= scale;
headerHeight *= scale;
lineHeight *= scale;
return new Layout(title, lines, headerHeight, lineHeight, totalWidth, totalHeight, scale, PAD_X, PAD_Y);
}
private Segments buildSegments(Text text, Font font, int defaultColor) {
String raw = LegacyTextHelper.extractRaw(text);
Text source = LegacyTextHelper.containsLegacyCodes(raw) ? LegacyTextHelper.parse(raw, defaultColor) : text;
boolean hasLegacy = LegacyTextHelper.containsLegacyCodes(raw);
List<Segment> segments = hasLegacy
? LegacyTextHelper.parseSegments(raw, defaultColor).stream()
.map(segment -> new Segment(segment.text(), segment.color())).toList()
: FormattedTextProcessor.processText(source, defaultColor).stream()
.map(segment -> new Segment(segment.text, segment.color)).toList();
float width = 0.0F;
List<Segment> sanitized = new java.util.ArrayList<>();
for (Segment segment : segments) {
String cleaned = segment.text;
if (!cleaned.isEmpty()) {
sanitized.add(new Segment(cleaned, segment.color));
width += font.width(cleaned);
}
}
return new Segments(sanitized, width);
}
private Font getTitleFont() {
return Fonts.MEDIUM.getFont(TITLE_SIZE * this.scaleSetting.getCurrentValue());
}
private Font getLineFont() {
return Fonts.REGULAR.getFont(LINE_SIZE * this.scaleSetting.getCurrentValue());
}
private ScoreboardObjective getObjective() {
if (mc.world == null) {
return null;
}
return mc.world.getScoreboard().getObjectiveForSlot(ScoreboardDisplaySlot.SIDEBAR);
}
private Text resolveNameText(Scoreboard scoreboard, ScoreboardEntry entry) {
Text display = entry.display();
if (display != null) {
return display;
}
String owner = entry.owner();
if (owner == null) {
return Text.empty();
}
Team team = resolveTeam(scoreboard, owner);
Text base = Text.literal(owner);
return team != null ? Team.decorateName(team, base) : base;
}
private Text resolveValueText(ScoreboardObjective objective, ScoreboardEntry entry) {
Text formatted = entry.formatted(objective.getNumberFormatOr(StyledNumberFormat.EMPTY));
if (formatted != null) {
return formatted;
}
return Text.literal(Integer.toString(entry.value()));
}
private Team resolveTeam(Scoreboard scoreboard, String owner) {
if (scoreboard == null || owner == null) {
return null;
}
return scoreboard.getScoreHolderTeam(owner);
}
private record Segment(String text, int color) {
}
private record Segments(List<Segment> segments, float width) {
}
private record EntryLine(Segments name, Segments value) {
}
private record Layout(Segments title, List<EntryLine> lines, float headerHeight, float lineHeight, float width,
float height, float scale, float padX, float padY) {
}
}
ScoreboardOverlay.java:
package moscow.rockstar.ui.overlay;
import java.lang.reflect.Method;
import java.util.Comparator;
import java.util.List;
import moscow.rockstar.framework.base.CustomDrawContext;
import moscow.rockstar.framework.msdf.Font;
import moscow.rockstar.framework.msdf.Fonts;
import moscow.rockstar.framework.objects.BorderRadius;
import moscow.rockstar.utility.colors.ColorRGBA;
import moscow.rockstar.utility.colors.Colors;
import moscow.rockstar.utility.game.LegacyTextHelper;
import moscow.rockstar.utility.gui.GuiUtility;
import moscow.rockstar.utility.interfaces.IMinecraft;
import moscow.rockstar.utility.interfaces.IScaledResolution;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.scoreboard.Scoreboard;
import net.minecraft.scoreboard.ScoreboardEntry;
import net.minecraft.scoreboard.ScoreboardObjective;
import net.minecraft.scoreboard.Team;
import net.minecraft.scoreboard.number.StyledNumberFormat;
import net.minecraft.text.Text;
import org.lwjgl.glfw.GLFW;
public class ScoreboardOverlay implements IMinecraft, IScaledResolution {
private static final ScoreboardOverlay INSTANCE = new ScoreboardOverlay();
private float x = -1.0F;
private float y = -1.0F;
private float width;
private float height;
private boolean dragging;
private float dragOffsetX;
private float dragOffsetY;
private boolean wasMouseDown;
public static ScoreboardOverlay getInstance() {
return INSTANCE;
}
public void render(DrawContext context, ScoreboardObjective objective) {
if (objective == null || mc.player == null || mc.world == null) {
return;
}
Scoreboard scoreboard = objective.getScoreboard();
List<ScoreboardEntry> entries = scoreboard.getScoreboardEntries(objective).stream()
.filter(entry -> entry != null && !entry.hidden())
.sorted(Comparator.comparingInt(ScoreboardEntry::value).reversed().thenComparing(ScoreboardEntry::owner, String::compareToIgnoreCase))
.limit(15)
.toList();
Font titleFont = Fonts.MEDIUM.getFont(8.5F);
Font lineFont = Fonts.REGULAR.getFont(7.5F);
float padX = 10.0F;
float padY = 6.0F;
float lineGap = 4.0F;
float valueGap = 10.0F;
float shadowExpand = 5.0F;
int defaultTextColor = Colors.getTextColor().getRGB() & 0xFFFFFF;
Text title = LegacyTextHelper.resolve(objective.getDisplayName(), defaultTextColor);
float maxWidth = titleFont.width(title);
for (ScoreboardEntry entry : entries) {
Text nameText = LegacyTextHelper.resolve(resolveNameText(scoreboard, entry), defaultTextColor);
Text valueText = LegacyTextHelper.resolve(resolveValueText(objective, entry), defaultTextColor);
float rowWidth = lineFont.width(nameText) + lineFont.width(valueText) + valueGap;
maxWidth = Math.max(maxWidth, rowWidth);
}
float headerHeight = titleFont.height() + padY * 2.0F;
float lineHeight = lineFont.height() + lineGap;
float totalHeight = headerHeight + entries.size() * lineHeight + padY;
float totalWidth = maxWidth + padX * 2.0F + 12.0F;
updateDrag(totalWidth, totalHeight);
float x = this.x;
float y = this.y;
this.width = totalWidth;
this.height = totalHeight;
CustomDrawContext drawContext = CustomDrawContext.of(context);
drawContext.drawShadow(
x - shadowExpand,
y - shadowExpand,
totalWidth + shadowExpand * 2.0F,
totalHeight + shadowExpand * 2.0F,
15.0F,
BorderRadius.all(6.0F),
ColorRGBA.BLACK.withAlpha(60.0F)
);
drawContext.drawClientRect(x, y, totalWidth, totalHeight, 1.0F, 0.0F, 7.0F);
drawContext.drawRect(x, y + headerHeight - 1.0F, totalWidth, 1.0F, Colors.getSeparatorColor());
float titleY = y + padY;
drawContext.drawText(titleFont, title, x + padX, titleY);
float lineY = y + headerHeight;
for (ScoreboardEntry entry : entries) {
Text nameText = LegacyTextHelper.resolve(resolveNameText(scoreboard, entry), defaultTextColor);
Text valueText = LegacyTextHelper.resolve(resolveValueText(objective, entry), defaultTextColor);
float rowY = lineY + (lineHeight - lineFont.height()) / 2.0F;
float valueWidth = lineFont.width(valueText);
drawContext.drawText(lineFont, nameText, x + padX, rowY);
drawContext.drawText(lineFont, valueText, x + totalWidth - padX - valueWidth, rowY);
lineY += lineHeight;
}
}
private void updateDrag(float targetWidth, float targetHeight) {
float maxX = Math.max(0.0F, sr.getScaledWidth() - targetWidth);
float maxY = Math.max(0.0F, sr.getScaledHeight() - targetHeight);
if (this.x < 0.0F || this.y < 0.0F) {
this.x = maxX;
this.y = 6.0F;
}
this.x = Math.max(0.0F, Math.min(this.x, maxX));
this.y = Math.max(0.0F, Math.min(this.y, maxY));
boolean mouseDown = GLFW.glfwGetMouseButton(mc.getWindow().getHandle(), 0) == 1;
var mouse = GuiUtility.getMouse();
float mouseX = mouse.getX();
float mouseY = mouse.getY();
if (mouseDown && !this.wasMouseDown && isHovered(mouseX, mouseY, targetWidth, targetHeight)) {
this.dragging = true;
this.dragOffsetX = mouseX - this.x;
this.dragOffsetY = mouseY - this.y;
}
if (!mouseDown) {
this.dragging = false;
}
if (this.dragging) {
this.x = Math.max(0.0F, Math.min(mouseX - this.dragOffsetX, maxX));
this.y = Math.max(0.0F, Math.min(mouseY - this.dragOffsetY, maxY));
}
this.wasMouseDown = mouseDown;
}
private boolean isHovered(float mouseX, float mouseY, float targetWidth, float targetHeight) {
return mouseX >= this.x && mouseX < this.x + targetWidth && mouseY >= this.y && mouseY < this.y + targetHeight;
}
private Text resolveNameText(Scoreboard scoreboard, ScoreboardEntry entry) {
Text display = entry.display();
if (display != null) {
return display;
}
String owner = entry.owner();
if (owner == null) {
return Text.empty();
}
Team team = resolveTeam(scoreboard, owner);
Text base = Text.literal(owner);
return team != null ? Team.decorateName(team, base) : base;
}
private Text resolveValueText(ScoreboardObjective objective, ScoreboardEntry entry) {
Text formatted = entry.formatted(objective.getNumberFormatOr(StyledNumberFormat.EMPTY));
if (formatted != null) {
return formatted;
}
return Text.literal(Integer.toString(entry.value()));
}
private Team resolveTeam(Scoreboard scoreboard, String owner) {
if (scoreboard == null || owner == null) {
return null;
}
try {
Method method = scoreboard.getClass().getMethod("getScoreHolderTeam", String.class);
Object result = method.invoke(scoreboard, owner);
if (result instanceof Team team) {
return team;
}
} catch (Throwable ignored) {
}
try {
Method method = scoreboard.getClass().getMethod("getPlayerTeam", String.class);
Object result = method.invoke(scoreboard, owner);
if (result instanceof Team team) {
return team;
}
} catch (Throwable ignored) {
}
return null;
}
}