diff --git a/common/src/main/java/net/xolt/freecam/config/ModConfig.java b/common/src/main/java/net/xolt/freecam/config/ModConfig.java index a619c898..2b84cca8 100644 --- a/common/src/main/java/net/xolt/freecam/config/ModConfig.java +++ b/common/src/main/java/net/xolt/freecam/config/ModConfig.java @@ -9,6 +9,7 @@ import me.shedaniel.autoconfig.serializer.JanksonConfigSerializer; import me.shedaniel.clothconfig2.gui.entries.SelectionListEntry; import net.minecraft.client.gui.screens.Screen; +import net.xolt.freecam.gui.go.tabs.GotoScreenTab; import net.xolt.freecam.variant.api.BuildVariant; import org.jetbrains.annotations.NotNull; @@ -125,6 +126,7 @@ public static class NotificationConfig { @ConfigEntry.Gui.Excluded public Hidden hidden = new Hidden(); public static class Hidden { + public GotoScreenTab currentTab = GotoScreenTab.PLAYER; public Perspective gotoPlayerPerspective = Perspective.THIRD_PERSON; } diff --git a/common/src/main/java/net/xolt/freecam/gui/go/GotoScreen.java b/common/src/main/java/net/xolt/freecam/gui/go/GotoScreen.java index a568f1ad..ea044cdd 100644 --- a/common/src/main/java/net/xolt/freecam/gui/go/GotoScreen.java +++ b/common/src/main/java/net/xolt/freecam/gui/go/GotoScreen.java @@ -2,7 +2,6 @@ import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; -import net.minecraft.client.gui.components.CycleButton; import net.minecraft.client.gui.components.Tooltip; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.layouts.FrameLayout; @@ -16,6 +15,7 @@ import net.xolt.freecam.Freecam; import net.xolt.freecam.config.ModConfig; import net.xolt.freecam.gui.textures.ScaledTexture; +import net.xolt.freecam.gui.go.tabs.GotoScreenTab; import org.jetbrains.annotations.Nullable; import java.util.Objects; @@ -35,7 +35,6 @@ public class GotoScreen extends Screen { private TargetsPane targets; private Button buttonBack; private Button buttonJump; - private CycleButton buttonPerspective; private boolean initialized; public GotoScreen() { @@ -47,27 +46,17 @@ protected void init() { super.init(); if (!initialized) { - targets = new TargetsPane(LIST_TOP, width, height); + targets = new TargetsPane(LIST_TOP, width, height, ModConfig.get().hidden.currentTab); buttonJump = Button.builder(Component.translatable("gui.freecam.goto.button.go"), button -> targets.gotoTarget()) .tooltip(Tooltip.create(Component.translatable("gui.freecam.goto.button.go.@Tooltip"))) .width(48) .build(); - buttonPerspective = CycleButton - .builder((ModConfig.Perspective value) -> Component.translatable(value.getKey())) - .withValues(ModConfig.Perspective.values()) - .withInitialValue(ModConfig.get().hidden.gotoPlayerPerspective) - .withTooltip(value -> Tooltip.create(Component.translatable("gui.freecam.goto.button.perspective.@Tooltip"))) - .displayOnlyValue() - .create(0, 0, 80, 20, null, (button, value) -> { - ModConfig.get().hidden.gotoPlayerPerspective = value; - ModConfig.save(); - }); - buttonBack = Button.builder(CommonComponents.GUI_BACK, button -> onClose()).width(48).build(); } + targets.setTab(ModConfig.get().hidden.currentTab); targets.setSize(width, getListHeight()); int innerWidth = GUI_WIDTH - 10; @@ -82,7 +71,7 @@ protected void init() { .paddingHorizontal(2); layout.addChild(buttonBack); - layout.addChild(buttonPerspective); + ModConfig.get().hidden.currentTab.extraButtons().forEach(layout::addChild); layout.addChild(buttonJump); positioner.arrangeElements(); @@ -139,6 +128,12 @@ public boolean isPauseScreen() { return false; } + public void setTab(GotoScreenTab tab) { + ModConfig.get().hidden.currentTab = tab; + ModConfig.save(); + init(); + } + // GUI height private int getGuiHeight() { return Math.max(MIN_GUI_HEIGHT, height - (GUI_TOP * 2)); diff --git a/common/src/main/java/net/xolt/freecam/gui/go/TargetsPane.java b/common/src/main/java/net/xolt/freecam/gui/go/TargetsPane.java index b367b8aa..ce1a62a7 100644 --- a/common/src/main/java/net/xolt/freecam/gui/go/TargetsPane.java +++ b/common/src/main/java/net/xolt/freecam/gui/go/TargetsPane.java @@ -12,14 +12,15 @@ import net.minecraft.resources.ResourceLocation; import net.xolt.freecam.Freecam; import net.xolt.freecam.gui.textures.ScaledTexture; -import net.xolt.freecam.util.FreeCamera; -import net.xolt.freecam.variant.api.BuildVariant; +import net.xolt.freecam.gui.go.tabs.GotoScreenTab; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; -import java.util.*; -import java.util.stream.Collectors; +import java.util.List; +import java.util.Locale; +import java.util.Objects; +import java.util.Optional; import static net.xolt.freecam.Freecam.MC; @@ -39,11 +40,13 @@ public class TargetsPane extends AbstractContainerWidget implements Tickable { private final TargetListWidget list; private final List children; + private GotoScreenTab currentTab; private String currentSearch; - public TargetsPane(int top, int width, int height) { + public TargetsPane(int top, int width, int height, GotoScreenTab tab) { super(0, top, width, height, Component.empty()); + this.currentTab = tab; this.list = new TargetListWidget(top + LIST_Y_OFFSET, width, height - LIST_Y_OFFSET - 1, LIST_ITEM_HEIGHT); this.searchBox = new EditBox(MC.font, list.getRowWidth() - SEARCH_X_OFFSET - 1, SEARCH_HEIGHT, SEARCH_TEXT); this.searchBox.setPosition(renderX() + SEARCH_X_OFFSET, getY() + SEARCH_Y_OFFSET); @@ -80,7 +83,7 @@ protected void updateWidgetNarration(NarrationElementOutput narrationElementOutp @Override public void tick() { - list.replaceEntries(calculatePlayerEntries().stream() + list.replaceEntries(currentTab.provideEntriesFor(list).stream() .filter(entry -> currentSearch == null || currentSearch.isEmpty() || entry.matchesSearch(currentSearch)) @@ -161,27 +164,6 @@ public boolean keyPressed(int keyCode, int scanCode, int modifiers) { return false; } - private List calculatePlayerEntries() { - // Store the existing entries in a UUID map for easy lookup - Map currentEntries = list.children() - .parallelStream() - .filter(PlayerListEntry.class::isInstance) - .map(PlayerListEntry.class::cast) - .collect(Collectors.toUnmodifiableMap(PlayerListEntry::getUUID, entry -> entry)); - - // Map the in-range players into PlayerListEntries - // Use existing entries if possible - return MC.level.players() - .parallelStream() - .filter(player -> !(player instanceof FreeCamera)) - .filter(player -> BuildVariant.getInstance().cheatsPermitted() || Objects.equals(MC.player, player)) // TODO check if player is visible - .map(player -> Objects.requireNonNullElseGet( - currentEntries.get(player.getUUID()), - () -> new PlayerListEntry(list, player))) - .map(TargetListEntry.class::cast) - .toList(); - } - private int renderWidth() { return list.getRowWidth() + 2; } @@ -190,6 +172,10 @@ private int renderX() { return (width - renderWidth()) / 2; } + public void setTab(GotoScreenTab tab) { + this.currentTab = tab; + } + /** * @return whether a text entry widget is in focus. */ diff --git a/common/src/main/java/net/xolt/freecam/gui/go/tabs/GotoScreenTab.java b/common/src/main/java/net/xolt/freecam/gui/go/tabs/GotoScreenTab.java new file mode 100644 index 00000000..77dd0583 --- /dev/null +++ b/common/src/main/java/net/xolt/freecam/gui/go/tabs/GotoScreenTab.java @@ -0,0 +1,27 @@ +package net.xolt.freecam.gui.go.tabs; + +import net.minecraft.client.gui.components.AbstractButton; +import net.xolt.freecam.gui.go.TargetListEntry; +import net.xolt.freecam.gui.go.TargetListWidget; + +import java.util.List; + +public enum GotoScreenTab implements Tab { + PLAYER(new PlayerTab()); + + private final Tab implementation; + + GotoScreenTab(Tab tab) { + this.implementation = tab; + } + + @Override + public List provideEntriesFor(TargetListWidget widget) { + return implementation.provideEntriesFor(widget); + } + + @Override + public List extraButtons() { + return implementation.extraButtons(); + } +} diff --git a/common/src/main/java/net/xolt/freecam/gui/go/tabs/PlayerTab.java b/common/src/main/java/net/xolt/freecam/gui/go/tabs/PlayerTab.java new file mode 100644 index 00000000..b1115a0b --- /dev/null +++ b/common/src/main/java/net/xolt/freecam/gui/go/tabs/PlayerTab.java @@ -0,0 +1,67 @@ +package net.xolt.freecam.gui.go.tabs; + +import com.google.common.base.Suppliers; +import net.minecraft.client.gui.components.AbstractButton; +import net.minecraft.client.gui.components.CycleButton; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.network.chat.Component; +import net.xolt.freecam.config.ModConfig; +import net.xolt.freecam.gui.go.PlayerListEntry; +import net.xolt.freecam.gui.go.TargetListEntry; +import net.xolt.freecam.gui.go.TargetListWidget; +import net.xolt.freecam.util.FreeCamera; +import net.xolt.freecam.variant.api.BuildVariant; + +import java.util.*; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +import static net.xolt.freecam.Freecam.MC; + +class PlayerTab implements Tab { + + private final Supplier> perspectiveButton = Suppliers.memoize(() -> CycleButton + .builder((ModConfig.Perspective value) -> Component.translatable(value.getKey())) + .withValues(ModConfig.Perspective.values()) + .withInitialValue(ModConfig.get().hidden.gotoPlayerPerspective) + .withTooltip(value -> Tooltip.create(Component.translatable("gui.freecam.goto.button.perspective.@Tooltip"))) + .displayOnlyValue() + .create(0, 0, 80, 20, Component.empty(), (button, value) -> { + ModConfig.get().hidden.gotoPlayerPerspective = value; + ModConfig.save(); + })); + + @Override + public List provideEntriesFor(TargetListWidget widget) { + // Store the existing entries in a UUID map for easy lookup + Map currentEntries = widget.children() + .parallelStream() + .filter(PlayerListEntry.class::isInstance) + .map(PlayerListEntry.class::cast) + .collect(Collectors.toUnmodifiableMap(PlayerListEntry::getUUID, Function.identity())); + + // Map the in-range players into PlayerListEntries + // Use existing entries if possible + return MC.level.players() + .parallelStream() + .filter(player -> !(player instanceof FreeCamera)) + .filter(this::permitted) + .map(player -> Objects.requireNonNullElseGet( + currentEntries.get(player.getUUID()), + () -> new PlayerListEntry(widget, player))) + .map(TargetListEntry.class::cast) + .toList(); + } + + @Override + public List extraButtons() { + return Collections.singletonList(perspectiveButton.get()); + } + + private boolean permitted(AbstractClientPlayer player) { + // TODO check if player is visible + return BuildVariant.getInstance().cheatsPermitted() || Objects.equals(MC.player, player); + } +} diff --git a/common/src/main/java/net/xolt/freecam/gui/go/tabs/Tab.java b/common/src/main/java/net/xolt/freecam/gui/go/tabs/Tab.java new file mode 100644 index 00000000..1fe1bb07 --- /dev/null +++ b/common/src/main/java/net/xolt/freecam/gui/go/tabs/Tab.java @@ -0,0 +1,14 @@ +package net.xolt.freecam.gui.go.tabs; + +import net.minecraft.client.gui.components.AbstractButton; +import net.xolt.freecam.gui.go.TargetListEntry; +import net.xolt.freecam.gui.go.TargetListWidget; + +import java.util.List; + +interface Tab { + + List provideEntriesFor(TargetListWidget widget); + + List extraButtons(); +}