diff options
| author | Linnea Gräf <nea@nea.moe> | 2025-07-31 16:04:27 +0200 |
|---|---|---|
| committer | Linnea Gräf <nea@nea.moe> | 2025-07-31 18:09:40 +0200 |
| commit | 93dfb15f25dcbe857e99d1a1fcbbc2205f06eef6 (patch) | |
| tree | 6604eb393b12d02d6dc3e381002a648c9f854178 | |
| parent | a893415fec63410c16bb45924989c6b51e5f85ed (diff) | |
| download | Skyblocker-93dfb15f25dcbe857e99d1a1fcbbc2205f06eef6.tar.gz Skyblocker-93dfb15f25dcbe857e99d1a1fcbbc2205f06eef6.tar.bz2 Skyblocker-93dfb15f25dcbe857e99d1a1fcbbc2205f06eef6.zip | |
feat: new profile viewer scaffolding
10 files changed, 396 insertions, 50 deletions
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerNavButton.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerNavButton.java index 8da17988..d14b47cc 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerNavButton.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerNavButton.java @@ -11,51 +11,56 @@ import net.minecraft.text.Text; import net.minecraft.util.Identifier; import java.util.Map; +import java.util.function.Consumer; public class ProfileViewerNavButton extends ClickableWidget { - private static final Identifier BUTTON_TEXTURES_TOGGLED = Identifier.of("container/creative_inventory/tab_top_selected_2"); - private static final Identifier BUTTON_TEXTURES = Identifier.of("container/creative_inventory/tab_top_unselected_2"); - private boolean toggled; - private final int index; - private final ProfileViewerScreen screen; - private final ItemStack icon; - - private static final Map<String, ItemStack> HEAD_ICON = Map.ofEntries( - Map.entry("Skills", Ico.IRON_SWORD), - Map.entry("Slayers", ProfileViewerUtils.createSkull("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHBzOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzkzMzZkN2NjOTVjYmY2Njg5ZjVlOGM5NTQyOTRlYzhkMWVmYzQ5NGE0MDMxMzI1YmI0MjdiYzgxZDU2YTQ4NGQifX19")), - Map.entry("Pets", Ico.BONE), - Map.entry("Dungeons", ProfileViewerUtils.createSkull("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHBzOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzliNTY4OTViOTY1OTg5NmFkNjQ3ZjU4NTk5MjM4YWY1MzJkNDZkYjljMWIwMzg5YjhiYmViNzA5OTlkYWIzM2QifX19")), - Map.entry("Inventories", Ico.E_CHEST), - Map.entry("Collections", Ico.PAINTING) - ); - - public ProfileViewerNavButton(ProfileViewerScreen screen, String tabName, int index, boolean toggled) { - super(-100, -100, 28, 32, Text.empty()); - this.screen = screen; - this.toggled = toggled; - this.index = index; - this.icon = HEAD_ICON.getOrDefault(tabName, Ico.BARRIER); - } - - @Override - protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { - context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, toggled ? BUTTON_TEXTURES_TOGGLED : BUTTON_TEXTURES, this.getX(), this.getY(), this.width, this.height - ((this.toggled) ? 0 : 4)); - context.drawItem(this.icon, this.getX() + 6, this.getY() + (this.toggled ? 7 : 9)); - } - - @Override - public void onClick(double mouseX, double mouseY) { - screen.onNavButtonClick(this); - } - - @Override - protected void appendClickableNarrations(NarrationMessageBuilder builder) {} - - public void setToggled(boolean toggled) { - this.toggled = toggled; - } - - public int getIndex() { - return index; - } + private static final Identifier BUTTON_TEXTURES_TOGGLED = Identifier.of("container/creative_inventory/tab_top_selected_2"); + private static final Identifier BUTTON_TEXTURES = Identifier.of("container/creative_inventory/tab_top_unselected_2"); + private boolean toggled; + private final int index; + private final Consumer<ProfileViewerNavButton> onClick; + private final ItemStack icon; + + private static final Map<String, ItemStack> HEAD_ICON = Map.ofEntries( + Map.entry("Skills", Ico.IRON_SWORD), + Map.entry("Slayers", ProfileViewerUtils.createSkull("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHBzOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzkzMzZkN2NjOTVjYmY2Njg5ZjVlOGM5NTQyOTRlYzhkMWVmYzQ5NGE0MDMxMzI1YmI0MjdiYzgxZDU2YTQ4NGQifX19")), + Map.entry("Pets", Ico.BONE), + Map.entry("Dungeons", ProfileViewerUtils.createSkull("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHBzOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzliNTY4OTViOTY1OTg5NmFkNjQ3ZjU4NTk5MjM4YWY1MzJkNDZkYjljMWIwMzg5YjhiYmViNzA5OTlkYWIzM2QifX19")), + Map.entry("Inventories", Ico.E_CHEST), + Map.entry("Collections", Ico.PAINTING) + ); + + public ProfileViewerNavButton(Consumer<ProfileViewerNavButton> onClick, String tabName, ItemStack icon, int index, boolean toggled) { + super(-100, -100, 28, 32, Text.empty()); + this.onClick = onClick; + this.toggled = toggled; + this.index = index; + this.icon = icon; + } + + public ProfileViewerNavButton(ProfileViewerScreen screen, String tabName, int index, boolean toggled) { + this(screen::onNavButtonClick, tabName, HEAD_ICON.getOrDefault(tabName, Ico.BARRIER), index, toggled); + } + + @Override + protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { + context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, toggled ? BUTTON_TEXTURES_TOGGLED : BUTTON_TEXTURES, this.getX(), this.getY(), this.width, this.height - ((this.toggled) ? 0 : 4)); + context.drawItem(this.icon, this.getX() + 6, this.getY() + (this.toggled ? 7 : 9)); + } + + @Override + public void onClick(double mouseX, double mouseY) { + onClick.accept(this); + } + + @Override + protected void appendClickableNarrations(NarrationMessageBuilder builder) {} + + public void setToggled(boolean toggled) { + this.toggled = toggled; + } + + public int getIndex() { + return index; + } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerScreen.java index 907b3cc6..9f2f69bc 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerScreen.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerScreen.java @@ -1,10 +1,9 @@ package de.hysky.skyblocker.skyblock.profileviewer; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; +import com.google.gson.*; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.util.UUIDTypeAdapter; import com.mojang.util.UndashedUuid; import de.hysky.skyblocker.SkyblockerMod; @@ -12,6 +11,7 @@ import de.hysky.skyblocker.annotations.Init; import de.hysky.skyblocker.skyblock.profileviewer.collections.CollectionsPage; import de.hysky.skyblocker.skyblock.profileviewer.dungeons.DungeonsPage; import de.hysky.skyblocker.skyblock.profileviewer.inventory.InventoryPage; +import de.hysky.skyblocker.skyblock.profileviewer.rework.ProfileViewerScreenRework; import de.hysky.skyblocker.skyblock.profileviewer.skills.SkillsPage; import de.hysky.skyblocker.skyblock.profileviewer.slayers.SlayersPage; import de.hysky.skyblocker.utils.ApiAuthentication; @@ -226,9 +226,9 @@ public class ProfileViewerScreen extends Screen { LiteralArgumentBuilder<FabricClientCommandSource> literalArgumentBuilder = ClientCommandManager.literal("pv") .then(ClientCommandManager.argument("username", StringArgumentType.string()) .suggests((source, builder) -> CommandSource.suggestMatching(getPlayerSuggestions(source.getSource()), builder)) - .executes(Scheduler.queueOpenScreenFactoryCommand(context -> new ProfileViewerScreen(StringArgumentType.getString(context, "username")))) + .executes(Scheduler.queueOpenScreenFactoryCommand(context -> ProfileViewerScreenRework.forPlayer(StringArgumentType.getString(context, "username")))) ) - .executes(Scheduler.queueOpenScreenCommand(() -> new ProfileViewerScreen(MinecraftClient.getInstance().getSession().getUsername()))); + .executes(Scheduler.queueOpenScreenCommand(() -> ProfileViewerScreenRework.forPlayer(MinecraftClient.getInstance().getSession().getUsername()))); dispatcher.register(literalArgumentBuilder); dispatcher.register(ClientCommandManager.literal(SkyblockerMod.NAMESPACE).then(literalArgumentBuilder)); }); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/ErrorPage.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/ErrorPage.java new file mode 100644 index 00000000..934a4a4e --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/ErrorPage.java @@ -0,0 +1,34 @@ +package de.hysky.skyblocker.skyblock.profileviewer.rework; + +import de.hysky.skyblocker.skyblock.tabhud.util.Ico; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public record ErrorPage(ProfileLoadState.Error error) implements ProfileViewerPage { + + @Override + public int getSortIndex() { + return 0; + } + + @Override + public @NotNull ItemStack getIcon() { + return Ico.BARRIER; + } + + @Override + public @NotNull String getName() { + return "Error Loading"; + } + + @Override + public @NotNull List<ProfileViewerWidget.Instance> getWidgets() { + return List.of( + ProfileViewerWidget.widget(ProfileViewerScreenRework.GUI_WIDTH / 2, 8, TextWidget.centered(Text.of("Error!"))), + ProfileViewerWidget.widget(ProfileViewerScreenRework.GUI_WIDTH / 2, 19, TextWidget.centered(Text.of(error.message()))) + ); + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/LoadingPage.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/LoadingPage.java new file mode 100644 index 00000000..d2b523b4 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/LoadingPage.java @@ -0,0 +1,31 @@ +package de.hysky.skyblocker.skyblock.profileviewer.rework; + +import de.hysky.skyblocker.skyblock.tabhud.util.Ico; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; + +import java.util.List; + +public class LoadingPage implements ProfileViewerPage { + @Override + public int getSortIndex() { + return 0; + } + + @Override + public ItemStack getIcon() { + return Ico.CLOCK; + } + + @Override + public String getName() { + return "Loading..."; + } + + @Override + public List<ProfileViewerWidget.Instance> getWidgets() { + return List.of( + ProfileViewerWidget.widget(ProfileViewerScreenRework.GUI_WIDTH / 2, 8, TextWidget.centered(Text.of("Loading profile..."))) + ); + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/ProfileLoadState.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/ProfileLoadState.java new file mode 100644 index 00000000..ac8f5bff --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/ProfileLoadState.java @@ -0,0 +1,20 @@ +package de.hysky.skyblocker.skyblock.profileviewer.rework; + +import de.hysky.skyblocker.skyblock.profileviewer.model.ApiProfile; +import de.hysky.skyblocker.skyblock.profileviewer.model.ProfileMember; + +import java.util.UUID; + +public sealed interface ProfileLoadState { + record SuccessfulLoad( + ApiProfile profile, + UUID mainMemberId, + ProfileMember member + ) implements ProfileLoadState {} + + record Error( + String message + ) implements ProfileLoadState {} + + record Loading() implements ProfileLoadState {} +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/ProfileViewerPage.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/ProfileViewerPage.java new file mode 100644 index 00000000..184f6660 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/ProfileViewerPage.java @@ -0,0 +1,27 @@ +package de.hysky.skyblocker.skyblock.profileviewer.rework; + +import net.minecraft.item.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.NotNullByDefault; + +import java.util.List; + +@NotNullByDefault +public interface ProfileViewerPage extends Comparable<ProfileViewerPage> { + int getSortIndex(); + + @Override + default int compareTo(@NotNull ProfileViewerPage o) { + return Integer.compare(this.getSortIndex(), o.getSortIndex()); + } + + static ProfileViewerWidget.Instance widget(int x, int y, ProfileViewerWidget widget) { + return ProfileViewerWidget.widget(x, y, widget); + } + + ItemStack getIcon(); + + String getName(); + + List<ProfileViewerWidget.Instance> getWidgets(); +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/ProfileViewerScreenRework.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/ProfileViewerScreenRework.java new file mode 100644 index 00000000..4158fcf4 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/ProfileViewerScreenRework.java @@ -0,0 +1,139 @@ +package de.hysky.skyblocker.skyblock.profileviewer.rework; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.mojang.util.UUIDTypeAdapter; +import com.mojang.util.UndashedUuid; +import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.skyblock.profileviewer.ProfileViewerNavButton; +import de.hysky.skyblocker.skyblock.profileviewer.model.ApiProfileResponse; +import de.hysky.skyblocker.utils.ApiUtils; +import de.hysky.skyblocker.utils.ProfileUtils; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gl.RenderPipelines; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; + +public class ProfileViewerScreenRework extends Screen { + public static final Gson GSON = new GsonBuilder() + .registerTypeAdapter(UUID.class, new UUIDTypeAdapter()) + .create(); + public static final List<Function<ProfileLoadState.SuccessfulLoad, ProfileViewerPage>> PAGE_CONSTRUCTORS = + new ArrayList<>(); + + public ProfileViewerScreenRework() { + super(Text.of("SkyBlocker Profile Viewer")); + displayLoadedProfile(new ProfileLoadState.Loading()); + } + + public static Screen forPlayer(String username) { + var screen = new ProfileViewerScreenRework(); + screen.loadProfilesFromPlayer(username); + return screen; + } + + //<editor-fold desc="Loading and state management"> + private CompletableFuture<ProfileLoadState> reload; + private ProfileLoadState currentLoadState; + private List<ProfileViewerPage> pages; + private List<ProfileViewerNavButton> buttons; + private List<ProfileViewerWidget.Instance> widgets; + private int selectedIndex = 0; + + + public ProfileLoadState getCurrentLoadState() { + return currentLoadState; + } + + public void displayLoadedProfile(ProfileLoadState profileLoadState) { + this.currentLoadState = profileLoadState; + this.pages = switch (profileLoadState) { + case ProfileLoadState.Error error -> List.of(new ErrorPage(error)); + case ProfileLoadState.SuccessfulLoad successfulLoad -> + PAGE_CONSTRUCTORS.stream().sorted().map(it -> it.apply(successfulLoad)).toList(); + case ProfileLoadState.Loading ignored -> List.of(new LoadingPage()); + }; + this.buttons = new ArrayList<>(); + for (int i = 0; i < pages.size(); i++) { + var page = pages.get(i); + buttons.add(new ProfileViewerNavButton(ignored -> setSelectedPage(selectedIndex), page.getName(), page.getIcon(), i, false)); + } + setSelectedPage(0); + } + + public int getSelectedIndex() { + return selectedIndex; + } + + public ProfileViewerPage getSelectedPage() { + return pages.get(selectedIndex); + } + + public void setSelectedPage(int index) { + this.selectedIndex = index; + for (int i = 0; i < buttons.size(); i++) { + buttons.get(i).setToggled(i == selectedIndex); + } + widgets = pages.get(selectedIndex).getWidgets(); + } + + public CompletableFuture<ProfileLoadState> loadProfilesFromPlayer(String name) { + if (reload != null) { + reload.cancel(true); + } + this.displayLoadedProfile(new ProfileLoadState.Loading()); + return reload = ProfileUtils.fetchFullProfile(name) + .thenApplyAsync(jsonObject -> GSON.fromJson(jsonObject, ApiProfileResponse.class)) + .thenApplyAsync(apiProfileResponse -> apiProfileResponse + .profiles + .stream() + .max(Comparator.comparing(it -> it.selected)) + .<ProfileLoadState>map(selectedProfile -> { + var uuid = UndashedUuid.fromStringLenient(ApiUtils.name2Uuid(name)); + return new ProfileLoadState.SuccessfulLoad( + selectedProfile, + uuid, + selectedProfile.members.get(uuid) + ); + }) + .orElseGet(() -> new ProfileLoadState.Error("No profile found"))) + .exceptionally(ex -> new ProfileLoadState.Error(ex.getMessage())) + .thenApplyAsync(load -> { + displayLoadedProfile(load); + return load; + }, MinecraftClient.getInstance()); + } + //</editor-fold> + + private static final Identifier TEXTURE = Identifier.of(SkyblockerMod.NAMESPACE, "textures/gui/profile_viewer/base_plate.png"); + public static final int GUI_WIDTH = 322; + public static final int GUI_HEIGHT = 180; + + @Override + public void render(DrawContext context, int mouseX, int mouseY, float deltaTicks) { + super.render(context, mouseX, mouseY, deltaTicks); + int rootX = width / 2 - GUI_WIDTH / 2; + int rootY = height / 2 - GUI_HEIGHT / 2 + 5; + + context.drawTexture(RenderPipelines.GUI_TEXTURED, TEXTURE, rootX, rootY, 0, 0, GUI_WIDTH, GUI_HEIGHT, GUI_WIDTH, GUI_HEIGHT); + for (var button : buttons) { + button.setX(rootX + button.getIndex() * 28 + 4); + button.setY(rootY - 28); + button.render(context, mouseX, mouseY, deltaTicks); + } + + for (var widget : widgets) { + widget.render(context, rootX, rootY, mouseX, mouseY, deltaTicks); + } + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/ProfileViewerWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/ProfileViewerWidget.java new file mode 100644 index 00000000..d601b6e4 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/ProfileViewerWidget.java @@ -0,0 +1,19 @@ +package de.hysky.skyblocker.skyblock.profileviewer.rework; + +import net.minecraft.client.gui.DrawContext; + +public interface ProfileViewerWidget { + void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY, float deltaTicks); + + default void click(int x, int y, int mouseX, int mouseY) {} + + static Instance widget(int x, int y, ProfileViewerWidget widget) { + return new Instance(widget, x, y); + } + + record Instance(ProfileViewerWidget widget, int xRelative, int yRelative) { + void render(DrawContext drawContext, int rootX, int rootY, int mouseX, int mouseY, float deltaTicks) { + widget.render(drawContext, rootX + xRelative, rootY + yRelative, mouseX, mouseY, deltaTicks); + } + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/TextWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/TextWidget.java new file mode 100644 index 00000000..a4e515d2 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/TextWidget.java @@ -0,0 +1,31 @@ +package de.hysky.skyblocker.skyblock.profileviewer.rework; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.Text; + +public final class TextWidget implements ProfileViewerWidget { + private final TextRenderer textRenderer; + private final Text text; + private final int offset; + + public TextWidget(TextRenderer textRenderer, Text text, boolean centered) { + this.textRenderer = textRenderer; + this.text = text; + this.offset = centered ? -textRenderer.getWidth(text) / 2 : 0; + } + + public static TextWidget leftAligned(Text text) { + return new TextWidget(MinecraftClient.getInstance().textRenderer, text, false); + } + + public static TextWidget centered(Text text) { + return new TextWidget(MinecraftClient.getInstance().textRenderer, text, true); + } + + @Override + public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY, float deltaTicks) { + drawContext.drawText(textRenderer, text, x + offset, y, -1, true); + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/pages/MainPage.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/pages/MainPage.java new file mode 100644 index 00000000..5387373c --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/rework/pages/MainPage.java @@ -0,0 +1,40 @@ +package de.hysky.skyblocker.skyblock.profileviewer.rework.pages; + +import de.hysky.skyblocker.annotations.Init; +import de.hysky.skyblocker.skyblock.profileviewer.rework.*; +import de.hysky.skyblocker.skyblock.tabhud.util.Ico; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; + +import java.util.List; + +public class MainPage implements ProfileViewerPage { + public MainPage(ProfileLoadState.SuccessfulLoad load) {} + + @Init + public static void init() { + ProfileViewerScreenRework.PAGE_CONSTRUCTORS.add(MainPage::new); + } + + @Override + public int getSortIndex() { + return 0; + } + + @Override + public ItemStack getIcon() { + return Ico.IRON_SWORD; + } + + @Override + public String getName() { + return "Skills"; + } + + @Override + public List<ProfileViewerWidget.Instance> getWidgets() { + return List.of( + ProfileViewerWidget.widget(ProfileViewerScreenRework.GUI_WIDTH / 2, 8, TextWidget.centered(Text.of("Skills"))) + ); + } +} |
