package net.fretux.ascend.client.screen; import com.mojang.blaze3d.systems.RenderSystem; import net.fretux.ascend.network.PacketHandler; import net.fretux.ascend.network.ServerboundSpendPointPacket; import net.fretux.ascend.player.PlayerStatsProvider; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; import java.util.HashMap; import java.util.Map; public class StatsScreen extends Screen { private static final int WIDTH = 480; private static final int HEIGHT = 266; private static final int PADDING = 12; private static final int COLUMN_GAP = 8; private static final int CARD_GAP = 4; private static final int CARD_HEIGHT = 40; private static final int CARDS_TOP = 64; private static final int CARD_WIDTH = (WIDTH - PADDING * 2 - COLUMN_GAP) / 2; private static final String[] ATTRIBUTES = { "vigor", "mind", "strength", "agility", "intelligence", "willpower", "charisma", "arcane" }; private static final Map ATTRIBUTE_COLORS = Map.of( "vigor", 0xFFD85C5C, "mind", 0xFF6699E8, "strength", 0xFFD78445, "agility", 0xFF71C988, "intelligence", 0xFF9A7BE8, "willpower", 0xFF79B9C8, "charisma", 0xFFE28AB8, "arcane", 0xFFC878E0 ); private static final Map ATTRIBUTE_TOOLTIPS = new HashMap<>(); static { for (String key : ATTRIBUTES) { ATTRIBUTE_TOOLTIPS.put(key, Component.translatable("ascend.attribute." + key + ".desc")); } } private final Minecraft minecraft = Minecraft.getInstance(); private final Map plusButtons = new HashMap<>(); private int leftPos; private int topPos; private String hoveredAttributeKey; public StatsScreen() { super(Component.translatable("ascend.stats.title")); } @Override protected void init() { super.init(); leftPos = (width - WIDTH) / 2; topPos = (height - HEIGHT) / 2; plusButtons.clear(); clearWidgets(); for (int index = 0; index < ATTRIBUTES.length; index++) { String attribute = ATTRIBUTES[index]; int column = index % 2; int row = index / 2; int cardX = leftPos + PADDING + column * (CARD_WIDTH + COLUMN_GAP); int cardY = topPos + CARDS_TOP + row * (CARD_HEIGHT + CARD_GAP); Button plus = Button.builder(Component.literal("+"), button -> PacketHandler.INSTANCE.sendToServer(new ServerboundSpendPointPacket(attribute))) .bounds(cardX + CARD_WIDTH - 30, cardY + 5, 22, 18) .build(); addRenderableWidget(plus); plusButtons.put(attribute, plus); } addRenderableWidget(Button.builder(Component.translatable("gui.done"), button -> onClose()) .bounds(leftPos + WIDTH / 2 - 45, topPos + HEIGHT - 24, 90, 18) .build()); } @Override public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { renderBackground(graphics); drawWindow(graphics); hoveredAttributeKey = null; if (minecraft.player != null) { minecraft.player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> { drawProgression(graphics, stats.getAscendLevel(), stats.getMaxAscendLevel(), stats.getAscendXP(), stats.getXPToNextAscendLevel(), stats.getKnowledge(), stats.getUnspentPoints()); for (int index = 0; index < ATTRIBUTES.length; index++) { String attribute = ATTRIBUTES[index]; int column = index % 2; int row = index / 2; int cardX = leftPos + PADDING + column * (CARD_WIDTH + COLUMN_GAP); int cardY = topPos + CARDS_TOP + row * (CARD_HEIGHT + CARD_GAP); int value = stats.getAttributeLevel(attribute); boolean hovered = mouseX >= cardX && mouseX < cardX + CARD_WIDTH && mouseY >= cardY && mouseY < cardY + CARD_HEIGHT; drawAttributeCard(graphics, attribute, value, stats.getMaxAttributePoints(), cardX, cardY, hovered); if (hovered) hoveredAttributeKey = attribute; Button plus = plusButtons.get(attribute); if (plus != null) { int cost = stats.getCostToUpgrade(attribute); plus.active = stats.getUnspentPoints() >= cost && value < stats.getMaxAttributePoints(); plus.setMessage(value >= stats.getMaxAttributePoints() ? Component.literal("✓") : Component.literal("+")); } } }); } super.render(graphics, mouseX, mouseY, partialTicks); if (hoveredAttributeKey != null) { graphics.renderTooltip(font, ATTRIBUTE_TOOLTIPS.get(hoveredAttributeKey), mouseX, mouseY); } } private void drawWindow(GuiGraphics graphics) { RenderSystem.enableBlend(); graphics.fill(leftPos - 6, topPos - 6, leftPos + WIDTH + 6, topPos + HEIGHT + 6, 0xCC07070C); graphics.fill(leftPos - 3, topPos - 3, leftPos + WIDTH + 3, topPos + HEIGHT + 3, 0xFF30253C); graphics.fill(leftPos, topPos, leftPos + WIDTH, topPos + HEIGHT, 0xF016131E); graphics.fill(leftPos, topPos, leftPos + WIDTH, topPos + 20, 0xFF2A2036); graphics.fill(leftPos, topPos + 20, leftPos + WIDTH, topPos + 21, 0xFF655275); RenderSystem.disableBlend(); graphics.drawCenteredString(font, title, leftPos + WIDTH / 2, topPos + 6, 0xFFF4EAFB); } private void drawProgression(GuiGraphics graphics, int level, int maxLevel, int xp, int xpNext, int knowledge, int unspent) { int panelX = leftPos + PADDING; int panelY = topPos + 26; int panelWidth = WIDTH - PADDING * 2; graphics.fill(panelX, panelY, panelX + panelWidth, panelY + 31, 0xAA211C29); graphics.fill(panelX, panelY, panelX + 3, panelY + 31, 0xFFCFB060); graphics.drawString(font, Component.translatable("ascend.stats.level", level, maxLevel), panelX + 9, panelY + 5, 0xFFFFDF78, false); graphics.drawString(font, Component.translatable("ascend.stats.knowledge", knowledge), panelX + 112, panelY + 5, 0xFFA9C7FF, false); Component points = Component.translatable("ascend.stats.unspent", unspent); int pointsWidth = font.width(points); int pointsX = panelX + panelWidth - pointsWidth - 9; graphics.fill(pointsX - 5, panelY + 2, panelX + panelWidth - 4, panelY + 16, 0x663D623D); graphics.drawString(font, points, pointsX, panelY + 5, unspent > 0 ? 0xFF87F58D : 0xFF9D9D9D, false); int barX = panelX + 9; int barY = panelY + 20; int barWidth = panelWidth - 18; graphics.fill(barX, barY, barX + barWidth, barY + 5, 0xFF0C0A10); double progress = level >= maxLevel || xpNext <= 0 ? 1.0 : Math.min(1.0, (double) xp / xpNext); graphics.fill(barX + 1, barY + 1, barX + 1 + (int) ((barWidth - 2) * progress), barY + 4, 0xFF8E68C3); Component xpLabel = level >= maxLevel ? Component.translatable("ascend.stats.xp_max") : Component.translatable("ascend.stats.xp", xp, xpNext); graphics.drawCenteredString(font, xpLabel, barX + barWidth / 2, barY - 2, 0xFFC9C1D0); } private void drawAttributeCard(GuiGraphics graphics, String attribute, int value, int maximum, int x, int y, boolean hovered) { int accent = ATTRIBUTE_COLORS.getOrDefault(attribute, 0xFFFFFFFF); graphics.fill(x, y, x + CARD_WIDTH, y + CARD_HEIGHT, hovered ? 0xE0332B3D : 0xC925202F); graphics.fill(x, y, x + 3, y + CARD_HEIGHT, accent); graphics.fill(x + 3, y, x + CARD_WIDTH, y + 1, hovered ? 0x667F6B8C : 0x334C4057); graphics.drawString(font, Component.translatable("ascend.attribute." + attribute), x + 9, y + 7, 0xFFF1ECF4, false); Component valueLabel = Component.literal(value + " / " + maximum); int valueX = x + CARD_WIDTH - 38 - font.width(valueLabel); graphics.drawString(font, valueLabel, valueX, y + 7, value >= maximum ? 0xFFFFD66B : 0xFFC9C1D0, false); graphics.drawString(font, Component.translatable("ascend.attribute." + attribute + ".short"), x + 9, y + 26, 0xFF9F98A8, false); } @Override public boolean isPauseScreen() { return false; } }