aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorKevinthegreat <92656833+kevinthegreat1@users.noreply.github.com>2024-05-14 22:58:56 -0400
committerKevinthegreat <92656833+kevinthegreat1@users.noreply.github.com>2024-05-24 19:51:46 -0400
commit7bf3958477c179185f9532cebffc36f218aa3bd8 (patch)
tree375325e936948bf088de79c049fd26d91ccb9e24 /src/main/java
parente9bd404a36ce3a69e62e97986d42e7f3635ab67d (diff)
downloadSkyblocker-7bf3958477c179185f9532cebffc36f218aa3bd8.tar.gz
Skyblocker-7bf3958477c179185f9532cebffc36f218aa3bd8.tar.bz2
Skyblocker-7bf3958477c179185f9532cebffc36f218aa3bd8.zip
Port waypoints config screens
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/accessors/CheckboxWidgetAccessor.java11
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/waypoint/AbstractWaypointsScreen.java65
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/waypoint/DropdownWidget.java126
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/waypoint/OrderedWaypoints.java2
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/waypoint/Waypoints.java72
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsListWidget.java195
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsScreen.java46
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsShareScreen.java86
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/waypoint/NamedWaypoint.java65
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/waypoint/Waypoint.java40
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/waypoint/WaypointCategory.java20
11 files changed, 629 insertions, 99 deletions
diff --git a/src/main/java/de/hysky/skyblocker/mixins/accessors/CheckboxWidgetAccessor.java b/src/main/java/de/hysky/skyblocker/mixins/accessors/CheckboxWidgetAccessor.java
new file mode 100644
index 00000000..5ec4a8e8
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/mixins/accessors/CheckboxWidgetAccessor.java
@@ -0,0 +1,11 @@
+package de.hysky.skyblocker.mixins.accessors;
+
+import net.minecraft.client.gui.widget.CheckboxWidget;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+@Mixin(CheckboxWidget.class)
+public interface CheckboxWidgetAccessor {
+ @Accessor
+ void setChecked(boolean checked);
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/AbstractWaypointsScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/AbstractWaypointsScreen.java
new file mode 100644
index 00000000..932bc144
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/AbstractWaypointsScreen.java
@@ -0,0 +1,65 @@
+package de.hysky.skyblocker.skyblock.waypoint;
+
+import com.google.common.collect.Multimap;
+import com.google.common.collect.MultimapBuilder;
+import de.hysky.skyblocker.utils.Location;
+import de.hysky.skyblocker.utils.Utils;
+import de.hysky.skyblocker.utils.waypoint.NamedWaypoint;
+import de.hysky.skyblocker.utils.waypoint.WaypointCategory;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.text.Text;
+
+import java.util.Arrays;
+
+public abstract class AbstractWaypointsScreen<T extends Screen> extends Screen {
+ protected final T parent;
+ protected final Multimap<String, WaypointCategory> waypoints;
+ protected String island;
+ protected WaypointsListWidget waypointsListWidget;
+ protected DropdownWidget<Location> islandWidget;
+
+ public AbstractWaypointsScreen(Text title, T parent) {
+ this(title, parent, MultimapBuilder.hashKeys().arrayListValues().build());
+ }
+
+ public AbstractWaypointsScreen(Text title, T parent, Multimap<String, WaypointCategory> waypoints) {
+ this(title, parent, waypoints, Utils.getLocationRaw());
+ }
+
+ public AbstractWaypointsScreen(Text title, T parent, Multimap<String, WaypointCategory> waypoints, String island) {
+ super(title);
+ this.parent = parent;
+ this.waypoints = waypoints;
+ this.island = island;
+ }
+
+ @Override
+ protected void init() {
+ super.init();
+ waypointsListWidget = addDrawableChild(new WaypointsListWidget(client, this, width, height - 96, 32, 24));
+ islandWidget = addDrawableChild(new DropdownWidget<>(client, width - 160, 8, 150, Arrays.asList(Location.values()), this::islandChanged, Location.from(island)));
+ }
+
+ @Override
+ public boolean mouseClicked(double mouseX, double mouseY, int button) {
+ if (islandWidget.mouseClicked(mouseX, mouseY, button)) {
+ return true;
+ }
+ boolean mouseClicked = super.mouseClicked(mouseX, mouseY, button);
+ updateButtons();
+ return mouseClicked;
+ }
+
+ protected void islandChanged(Location location) {
+ island = location.id();
+ waypointsListWidget.setIsland(island);
+ }
+
+ protected abstract boolean isEnabled(NamedWaypoint waypoint);
+
+ protected abstract void enabledChanged(NamedWaypoint waypoint, boolean enabled);
+
+ protected void updateButtons() {
+ waypointsListWidget.updateButtons();
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/DropdownWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/DropdownWidget.java
new file mode 100644
index 00000000..157b0b15
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/DropdownWidget.java
@@ -0,0 +1,126 @@
+package de.hysky.skyblocker.skyblock.waypoint;
+
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.DrawContext;
+import net.minecraft.client.gui.Element;
+import net.minecraft.client.gui.Selectable;
+import net.minecraft.client.gui.widget.ElementListWidget;
+import net.minecraft.text.Style;
+import net.minecraft.text.Text;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+public class DropdownWidget<T> extends ElementListWidget<DropdownWidget.Entry<T>> {
+ private static final MinecraftClient client = MinecraftClient.getInstance();
+ public static final int ENTRY_HEIGHT = 15;
+ protected final List<T> entries;
+ protected final Consumer<T> selectCallback;
+ protected T prevSelected;
+ protected T selected;
+ protected boolean open;
+
+ public DropdownWidget(MinecraftClient minecraftClient, int x, int y, int width, List<T> entries, Consumer<T> selectCallback, T selected) {
+ super(minecraftClient, width, (entries.size() + 1) * ENTRY_HEIGHT + 8, y, ENTRY_HEIGHT);
+ setX(x);
+ this.entries = entries;
+ this.selectCallback = selectCallback;
+ this.selected = selected;
+ setRenderHeader(true, ENTRY_HEIGHT + 4);
+ for (T entry : entries) {
+ addEntry(new Entry<>(this, entry));
+ }
+ }
+
+ @Override
+ public int getRowLeft() {
+ return getX();
+ }
+
+ @Override
+ public int getRowWidth() {
+ return getWidth();
+ }
+
+ @Override
+ protected boolean clickedHeader(int x, int y) {
+ open = !open;
+ return true;
+ }
+
+ @Override
+ protected void renderHeader(DrawContext context, int x, int y) {
+ context.drawTextWithShadow(client.textRenderer, selected.toString(), x + 4, y + 2, 0xFFFFFFFF);
+ }
+
+ @Override
+ public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) {
+ context.getMatrices().push();
+ context.getMatrices().translate(0, 0, 100);
+
+ context.fill(getX(), getY(), getX() + width, getY() + headerHeight, 0xFF000000);
+ context.drawHorizontalLine(getX(), getX() + width, getY(), 0xFFFFFFFF);
+ context.drawHorizontalLine(getX(), getX() + width, getY() + headerHeight, 0xFFFFFFFF);
+ context.drawVerticalLine(getX(), getY(), getY() + headerHeight, 0xFFFFFFFF);
+ context.drawVerticalLine(getX() + width, getY(), getY() + headerHeight, 0xFFFFFFFF);
+
+ if (open) {
+ context.fill(getX(), getY() + headerHeight + 1, getX() + width, getY() + height, 0xFF000000);
+ context.drawHorizontalLine(getX(), getX() + width, getY() + height, 0xFFFFFFFF);
+ context.drawVerticalLine(getX(), getY() + headerHeight, getY() + height, 0xFFFFFFFF);
+ context.drawVerticalLine(getX() + width, getY() + headerHeight, getY() + height, 0xFFFFFFFF);
+
+ super.renderWidget(context, mouseX, mouseY, delta);
+ } else {
+ renderHeader(context, getRowLeft(), getY() + 4 - (int) getScrollAmount());
+ }
+
+ context.getMatrices().pop();
+ }
+
+ protected void select(T entry) {
+ selected = entry;
+ open = false;
+ if (selected != prevSelected) {
+ selectCallback.accept(entry);
+ prevSelected = selected;
+ }
+ }
+
+ static class Entry<T> extends ElementListWidget.Entry<Entry<T>> {
+ private final DropdownWidget<T> dropdownWidget;
+ private final T entry;
+
+ public Entry(DropdownWidget<T> dropdownWidget, T entry) {
+ this.dropdownWidget = dropdownWidget;
+ this.entry = entry;
+ }
+
+ @Override
+ public List<? extends Selectable> selectableChildren() {
+ return List.of();
+ }
+
+ @Override
+ public List<? extends Element> children() {
+ return List.of();
+ }
+
+ @Override
+ public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
+ context.drawTextWithShadow(client.textRenderer, Text.literal(entry.toString()).fillStyle(Style.EMPTY.withUnderline(hovered)), x + 14, y + 2, 0xFFFFFFFF);
+ if (dropdownWidget.selected == this.entry) {
+ context.drawTextWithShadow(client.textRenderer, "✔", x + 4, y + 2, 0xFFFFFFFF);
+ }
+ }
+
+ @Override
+ public boolean mouseClicked(double mouseX, double mouseY, int button) {
+ if (button == 0 && dropdownWidget.open) {
+ dropdownWidget.select(entry);
+ return true;
+ }
+ return super.mouseClicked(mouseX, mouseY, button);
+ }
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/OrderedWaypoints.java b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/OrderedWaypoints.java
index bbc9a655..f8930882 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/OrderedWaypoints.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/OrderedWaypoints.java
@@ -408,7 +408,7 @@ public class OrderedWaypoints {
}
@Override
- protected float[] getColorComponents() {
+ public float[] getColorComponents() {
if (this.colorComponents.length != 3) {
return switch (this.relativeIndex) {
case PREVIOUS -> RED;
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/Waypoints.java b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/Waypoints.java
index 8eeae2aa..18096117 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/Waypoints.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/Waypoints.java
@@ -2,19 +2,25 @@ package de.hysky.skyblocker.skyblock.waypoint;
import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;
+import com.google.common.collect.Multimaps;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
+import com.google.gson.JsonSyntaxException;
import com.mojang.serialization.Codec;
import com.mojang.serialization.JsonOps;
import de.hysky.skyblocker.SkyblockerMod;
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.utils.Utils;
+import de.hysky.skyblocker.utils.scheduler.Scheduler;
import de.hysky.skyblocker.utils.waypoint.WaypointCategory;
+import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.toast.SystemToast;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -24,19 +30,26 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
+import java.util.function.Function;
+
+import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
public class Waypoints {
- private static final Logger LOGGER = LoggerFactory.getLogger(Waypoints.class);
+ public static final Logger LOGGER = LoggerFactory.getLogger(Waypoints.class);
private static final Codec<List<WaypointCategory>> CODEC = WaypointCategory.CODEC.listOf();
private static final Codec<List<WaypointCategory>> SKYTILS_CODEC = WaypointCategory.SKYTILS_CODEC.listOf();
+ protected static final SystemToast.Type WAYPOINTS_TOAST_TYPE = new SystemToast.Type();
+
private static final Path waypointsFile = FabricLoader.getInstance().getConfigDir().resolve(SkyblockerMod.NAMESPACE).resolve("waypoints.json");
- static final Multimap<String, WaypointCategory> waypoints = MultimapBuilder.hashKeys().arrayListValues().build();
+ protected static final Multimap<String, WaypointCategory> waypoints = MultimapBuilder.hashKeys().arrayListValues().build();
public static void init() {
loadWaypoints();
ClientLifecycleEvents.CLIENT_STOPPING.register(Waypoints::saveWaypoints);
WorldRenderEvents.AFTER_TRANSLUCENT.register(Waypoints::render);
+ ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(literal("waypoints").executes(Scheduler.queueOpenScreenCommand(() -> new WaypointsScreen(MinecraftClient.getInstance().currentScreen))))));
}
public static void loadWaypoints() {
@@ -49,22 +62,47 @@ public class Waypoints {
}
}
- public static List<WaypointCategory> fromSkytilsBase64(String base64) {
- return fromSkytilsJson(new String(Base64.getDecoder().decode(base64)));
+ public static List<WaypointCategory> fromSkytilsBase64(String base64, String defaultIsland) {
+ try {
+ if (base64.startsWith("<Skytils-Waypoint-Data>(V")) {
+ int version = Integer.parseInt(base64.substring(26, base64.indexOf(')')));
+ if (version == 1) {
+ return fromSkytilsJson(new String(Base64.getDecoder().decode(base64.substring(base64.indexOf(':') + 1))), defaultIsland);
+ } else {
+ LOGGER.error("[Skyblocker Waypoints] Unknown Skytils waypoint data version: " + version);
+ }
+ } else return fromSkytilsJson(new String(Base64.getDecoder().decode(base64)), defaultIsland);
+ } catch (NumberFormatException e) {
+ LOGGER.error("[Skyblocker Waypoints] Encountered exception while parsing Skytils waypoint data version", e);
+ } catch (IllegalArgumentException e) {
+ LOGGER.error("[Skyblocker Waypoints] Encountered exception while decoding Skytils waypoint data", e);
+ }
+ return Collections.emptyList();
}
- public static List<WaypointCategory> fromSkytilsJson(String waypointCategories) {
- return SKYTILS_CODEC.parse(JsonOps.INSTANCE, SkyblockerMod.GSON.fromJson(waypointCategories, JsonObject.class).getAsJsonArray("categories")).resultOrPartial(LOGGER::error).orElseThrow();
+ public static List<WaypointCategory> fromSkytilsJson(String waypointCategories, String defaultIsland) {
+ JsonArray waypointCategoriesJson;
+ try {
+ waypointCategoriesJson = SkyblockerMod.GSON.fromJson(waypointCategories, JsonObject.class).getAsJsonArray("categories");
+ } catch (JsonSyntaxException e) {
+ JsonObject waypointCategoryJson = new JsonObject();
+ waypointCategoryJson.addProperty("name", "New Category");
+ waypointCategoryJson.addProperty("island", defaultIsland);
+ waypointCategoryJson.add("waypoints", SkyblockerMod.GSON.fromJson(waypointCategories, JsonArray.class));
+ waypointCategoriesJson = new JsonArray();
+ waypointCategoriesJson.add(waypointCategoryJson);
+ }
+ return SKYTILS_CODEC.parse(JsonOps.INSTANCE, waypointCategoriesJson).resultOrPartial(LOGGER::error).orElseThrow();
}
- public static String toSkytilsBase64(Collection<WaypointCategory> waypointCategories) {
+ public static String toSkytilsBase64(List<WaypointCategory> waypointCategories) {
return Base64.getEncoder().encodeToString(toSkytilsJson(waypointCategories).getBytes());
}
- public static String toSkytilsJson(Collection<WaypointCategory> waypointCategories) {
+ public static String toSkytilsJson(List<WaypointCategory> waypointCategories) {
JsonObject waypointCategoriesJson = new JsonObject();
- waypointCategoriesJson.add("categories", SKYTILS_CODEC.encodeStart(JsonOps.INSTANCE, List.copyOf(waypointCategories)).resultOrPartial(LOGGER::error).orElseThrow());
- return SkyblockerMod.GSON.toJson(waypointCategoriesJson);
+ waypointCategoriesJson.add("categories", SKYTILS_CODEC.encodeStart(JsonOps.INSTANCE, waypointCategories).resultOrPartial(LOGGER::error).orElseThrow());
+ return SkyblockerMod.GSON_COMPACT.toJson(waypointCategoriesJson);
}
public static void saveWaypoints(MinecraftClient client) {
@@ -77,11 +115,17 @@ public class Waypoints {
}
}
+ public static Multimap<String, WaypointCategory> waypointsDeepCopy() {
+ return waypoints.values().stream().map(WaypointCategory::deepCopy).collect(Multimaps.toMultimap(WaypointCategory::island, Function.identity(), () -> MultimapBuilder.hashKeys().arrayListValues().build()));
+ }
+
public static void render(WorldRenderContext context) {
- Collection<WaypointCategory> categories = waypoints.get(Utils.getLocationRaw());
- for (WaypointCategory category : categories) {
- if (category != null) {
- category.render(context);
+ if (SkyblockerConfigManager.get().uiAndVisuals.waypoints.enableWaypoints) {
+ Collection<WaypointCategory> categories = waypoints.get(Utils.getLocationRaw());
+ for (WaypointCategory category : categories) {
+ if (category != null) {
+ category.render(context);
+ }
}
}
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsListWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsListWidget.java
index 7a01a494..3e18d673 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsListWidget.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsListWidget.java
@@ -1,41 +1,31 @@
package de.hysky.skyblocker.skyblock.waypoint;
-import de.hysky.skyblocker.debug.Debug;
-import de.hysky.skyblocker.utils.Utils;
+import de.hysky.skyblocker.mixins.accessors.CheckboxWidgetAccessor;
import de.hysky.skyblocker.utils.waypoint.NamedWaypoint;
import de.hysky.skyblocker.utils.waypoint.WaypointCategory;
+import it.unimi.dsi.fastutil.ints.Int2ObjectFunction;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.Selectable;
-import net.minecraft.client.gui.widget.ButtonWidget;
-import net.minecraft.client.gui.widget.ClickableWidget;
-import net.minecraft.client.gui.widget.ElementListWidget;
+import net.minecraft.client.gui.widget.*;
import net.minecraft.text.Text;
import net.minecraft.util.math.BlockPos;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
-import java.util.Objects;
import java.util.Optional;
public class WaypointsListWidget extends ElementListWidget<WaypointsListWidget.AbstractWaypointEntry> {
- private final WaypointsScreen screen;
- private final String island;
- private final List<WaypointCategory> waypoints;
+ private final AbstractWaypointsScreen<?> screen;
+ private String island;
+ private List<WaypointCategory> waypoints;
- public WaypointsListWidget(MinecraftClient client, WaypointsScreen screen, int width, int height, int y, int itemHeight) {
+ public WaypointsListWidget(MinecraftClient client, AbstractWaypointsScreen<?> screen, int width, int height, int y, int itemHeight) {
super(client, width, height, y, itemHeight);
this.screen = screen;
- island = Utils.getLocationRaw();
- waypoints = (List<WaypointCategory>) screen.waypoints.get(island);
- for (WaypointCategory category : waypoints) {
- WaypointCategoryEntry categoryEntry = new WaypointCategoryEntry(category);
- addEntry(categoryEntry);
- for (NamedWaypoint waypoint : category.waypoints()) {
- addEntry(new WaypointEntry(categoryEntry, waypoint));
- }
- }
+ setIsland(screen.island);
}
@Override
@@ -44,8 +34,8 @@ public class WaypointsListWidget extends ElementListWidget<WaypointsListWidget.A
}
@Override
- protected int getScrollbarPositionX() {
- return super.getScrollbarPositionX() + 50;
+ protected int getScrollbarX() {
+ return super.getScrollbarX();
}
Optional<WaypointCategoryEntry> getCategory() {
@@ -57,6 +47,12 @@ public class WaypointsListWidget extends ElementListWidget<WaypointsListWidget.A
return Optional.empty();
}
+ void setIsland(String island) {
+ this.island = island;
+ waypoints = (List<WaypointCategory>) screen.waypoints.get(island);
+ updateEntries();
+ }
+
void addWaypointCategoryAfterSelected() {
WaypointCategoryEntry categoryEntry = new WaypointCategoryEntry();
Optional<WaypointCategoryEntry> selectedCategoryEntryOptional = getCategory();
@@ -74,17 +70,35 @@ public class WaypointsListWidget extends ElementListWidget<WaypointsListWidget.A
children().add(entryIndex, categoryEntry);
}
- @Override
- protected boolean isSelectedEntry(int index) {
- return Debug.debugEnabled() ? Objects.equals(getSelectedOrNull(), children().get(index)) : super.isSelectedEntry(index);
+ void updateEntries() {
+ clearEntries();
+ for (WaypointCategory category : waypoints) {
+ WaypointCategoryEntry categoryEntry = new WaypointCategoryEntry(category);
+ addEntry(categoryEntry);
+ for (NamedWaypoint waypoint : category.waypoints()) {
+ addEntry(new WaypointEntry(categoryEntry, waypoint));
+ }
+ }
+ }
+
+ void updateButtons() {
+ for (Entry<AbstractWaypointEntry> entry : children()) {
+ if (entry instanceof WaypointCategoryEntry categoryEntry && categoryEntry.enabled.isChecked() != categoryEntry.category.waypoints().stream().allMatch(screen::isEnabled)) {
+ ((CheckboxWidgetAccessor) categoryEntry.enabled).setChecked(!categoryEntry.enabled.isChecked());
+ } else if (entry instanceof WaypointEntry waypointEntry && waypointEntry.enabled.isChecked() != screen.isEnabled(waypointEntry.waypoint)) {
+ waypointEntry.enabled.onPress();
+ }
+ }
}
- protected static abstract class AbstractWaypointEntry extends ElementListWidget.Entry<AbstractWaypointEntry> {
+ protected abstract static class AbstractWaypointEntry extends Entry<AbstractWaypointEntry> {
}
protected class WaypointCategoryEntry extends AbstractWaypointEntry {
- private final WaypointCategory category;
+ private WaypointCategory category;
private final List<ClickableWidget> children;
+ private final CheckboxWidget enabled;
+ private final TextFieldWidget nameField;
private final ButtonWidget buttonNewWaypoint;
private final ButtonWidget buttonDelete;
@@ -94,6 +108,10 @@ public class WaypointsListWidget extends ElementListWidget<WaypointsListWidget.A
public WaypointCategoryEntry(WaypointCategory category) {
this.category = category;
+ enabled = CheckboxWidget.builder(Text.literal(""), client.textRenderer).checked(!category.waypoints().isEmpty() && category.waypoints().stream().allMatch(screen::isEnabled)).callback((checkbox, checked) -> category.waypoints().forEach(waypoint -> screen.enabledChanged(waypoint, checked))).build();
+ nameField = new TextFieldWidget(client.textRenderer, 70, 20, Text.literal("Name"));
+ nameField.setText(category.name());
+ nameField.setChangedListener(this::updateName);
buttonNewWaypoint = ButtonWidget.builder(Text.translatable("skyblocker.waypoints.new"), buttonNewWaypoint -> {
WaypointEntry waypointEntry = new WaypointEntry(this);
int entryIndex;
@@ -107,7 +125,7 @@ public class WaypointsListWidget extends ElementListWidget<WaypointsListWidget.A
}
category.waypoints().add(waypointEntry.waypoint);
WaypointsListWidget.this.children().add(entryIndex, waypointEntry);
- }).width(75).build();
+ }).width(72).build();
buttonDelete = ButtonWidget.builder(Text.translatable("selectServer.deleteButton"), buttonDelete -> {
int entryIndex = WaypointsListWidget.this.children().indexOf(this) + 1;
while (entryIndex < WaypointsListWidget.this.children().size() && !(WaypointsListWidget.this.children().get(entryIndex) instanceof WaypointCategoryEntry)) {
@@ -115,8 +133,8 @@ public class WaypointsListWidget extends ElementListWidget<WaypointsListWidget.A
}
WaypointsListWidget.this.children().remove(this);
waypoints.remove(category);
- }).width(50).build();
- children = List.of(buttonNewWaypoint, buttonDelete);
+ }).width(38).build();
+ children = List.of(enabled, nameField, buttonNewWaypoint, buttonDelete);
}
@Override
@@ -129,20 +147,36 @@ public class WaypointsListWidget extends ElementListWidget<WaypointsListWidget.A
return children;
}
+ private void updateName(String name) {
+ int index = waypoints.indexOf(category);
+ category = category.withName(name);
+ if (index >= 0) {
+ waypoints.set(index, category);
+ }
+ }
+
@Override
public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
- context.drawTextWithShadow(client.textRenderer, category.name(), width / 2 - 150, y + 5, 0xFFFFFF);
- buttonNewWaypoint.setPosition(x + entryWidth - 133, y);
- buttonDelete.setPosition(x + entryWidth - 54, y);
- buttonNewWaypoint.render(context, mouseX, mouseY, tickDelta);
- buttonDelete.render(context, mouseX, mouseY, tickDelta);
+ enabled.setPosition(x, y + 1);
+ nameField.setPosition(x + 22, y);
+ buttonNewWaypoint.setPosition(x + entryWidth - 115, y);
+ buttonDelete.setPosition(x + entryWidth - 38, y);
+ for (ClickableWidget child : children) {
+ child.render(context, mouseX, mouseY, tickDelta);
+ }
}
}
protected class WaypointEntry extends AbstractWaypointEntry {
private final WaypointCategoryEntry category;
- private final NamedWaypoint waypoint;
+ private NamedWaypoint waypoint;
private final List<ClickableWidget> children;
+ private final CheckboxWidget enabled;
+ private final TextFieldWidget nameField;
+ private final TextFieldWidget xField;
+ private final TextFieldWidget yField;
+ private final TextFieldWidget zField;
+ private final TextFieldWidget colorField;
private final ButtonWidget buttonDelete;
public WaypointEntry(WaypointCategoryEntry category) {
@@ -152,11 +186,27 @@ public class WaypointsListWidget extends ElementListWidget<WaypointsListWidget.A
public WaypointEntry(WaypointCategoryEntry category, NamedWaypoint waypoint) {
this.category = category;
this.waypoint = waypoint;
+ enabled = CheckboxWidget.builder(Text.literal(""), client.textRenderer).checked(screen.isEnabled(waypoint)).callback((checkbox, checked) -> screen.enabledChanged(waypoint, checked)).build();
+ nameField = new TextFieldWidget(client.textRenderer, 65, 20, Text.literal("Name"));
+ nameField.setText(waypoint.getName().getString());
+ nameField.setChangedListener(this::updateName);
+ xField = new TextFieldWidget(client.textRenderer, 26, 20, Text.literal("X"));
+ xField.setText(Integer.toString(waypoint.pos.getX()));
+ xField.setChangedListener(this::updateX);
+ yField = new TextFieldWidget(client.textRenderer, 26, 20, Text.literal("Y"));
+ yField.setText(Integer.toString(waypoint.pos.getY()));
+ yField.setChangedListener(this::updateY);
+ zField = new TextFieldWidget(client.textRenderer, 26, 20, Text.literal("Z"));
+ zField.setText(Integer.toString(waypoint.pos.getZ()));
+ zField.setChangedListener(this::updateZ);
+ colorField = new TextFieldWidget(client.textRenderer, 56, 20, Text.literal("Color"));
+ colorField.setText(String.format("%02X%02X%02X%02X", (int) (waypoint.alpha * 255), (int) (waypoint.getColorComponents()[0] * 255), (int) (waypoint.getColorComponents()[1] * 255), (int) (waypoint.getColorComponents()[2] * 255)));
+ colorField.setChangedListener(this::updateColor);
buttonDelete = ButtonWidget.builder(Text.translatable("selectServer.deleteButton"), button -> {
category.category.waypoints().remove(waypoint);
WaypointsListWidget.this.children().remove(this);
- }).width(50).build();
- children = List.of(buttonDelete);
+ }).width(38).build();
+ children = List.of(enabled, nameField, xField, yField, zField, colorField, buttonDelete);
}
@Override
@@ -169,14 +219,73 @@ public class WaypointsListWidget extends ElementListWidget<WaypointsListWidget.A
return children;
}
+ public void updateName(String name) {
+ if (waypoint.name.getString().equals(name)) return;
+ int index = category.category.waypoints().indexOf(waypoint);
+ waypoint = waypoint.withName(name);
+ if (index >= 0) {
+ category.category.waypoints().set(index, waypoint);
+ }
+ }
+
+ public void updateX(String xString) {
+ updateInt(xString, waypoint.pos.getX(), waypoint::withX);
+ }
+
+ public void updateY(String yString) {
+ updateInt(yString, waypoint.pos.getY(), waypoint::withY);
+ }
+
+ public void updateZ(String zString) {
+ updateInt(zString, waypoint.pos.getZ(), waypoint::withZ);
+ }
+
+ public void updateInt(String newValueString, int currentValue, Int2ObjectFunction<NamedWaypoint> wither) {
+ try {
+ int index = category.category.waypoints().indexOf(waypoint);
+ int newValue = Integer.parseInt(newValueString);
+ if (newValue == currentValue) return;
+ waypoint = wither.apply(newValue);
+ if (index >= 0) {
+ category.category.waypoints().set(index, waypoint);
+ }
+ } catch (NumberFormatException e) {
+ Waypoints.LOGGER.warn("[Skyblocker Waypoints] Failed to parse integer: {}", newValueString, e);
+ }
+ }
+
+ public void updateColor(String colorString) {
+ try {
+ int index = category.category.waypoints().indexOf(waypoint);
+ int colorInt = Integer.parseInt(colorString, 16);
+ float[] colorComponents = {((colorInt & 0x00FF0000) >> 16) / 255f, ((colorInt & 0x0000FF00) >> 8) / 255f, (colorInt & 0x000000FF) / 255f};
+ float alpha = ((colorInt & 0xFF000000) >>> 24) / 255f;
+ if (Arrays.equals(waypoint.getColorComponents(), colorComponents) && waypoint.alpha == alpha) return;
+ waypoint = waypoint.withColor(colorComponents, alpha);
+ if (index >= 0) {
+ category.category.waypoints().set(index, waypoint);
+ }
+ } catch (NumberFormatException e) {
+ Waypoints.LOGGER.warn("[Skyblocker Waypoints] Failed to parse color: {}", colorString, e);
+ }
+ }
+
@Override
public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
- context.drawTextWithShadow(client.textRenderer, waypoint.getName(), width / 2 - 125, y + 5, 0xFFFFFF);
- context.drawTextWithShadow(client.textRenderer, waypoint.pos.toShortString(), width / 2 - 25, y + 5, 0xFFFFFF);
- float[] colorComponents = waypoint.getColorComponents();
- context.drawTextWithShadow(client.textRenderer, String.format("#%02X%02X%02X", (int) (colorComponents[0] * 255), (int) (colorComponents[1] * 255), (int) (colorComponents[2] * 255)), width / 2 + 25, y + 5, 0xFFFFFF);
- buttonDelete.setPosition(x + entryWidth - 54, y);
- buttonDelete.render(context, mouseX, mouseY, tickDelta);
+ context.drawTextWithShadow(client.textRenderer, "X:", width / 2 - 56, y + 6, 0xFFFFFF);
+ context.drawTextWithShadow(client.textRenderer, "Y:", width / 2 - 19, y + 6, 0xFFFFFF);
+ context.drawTextWithShadow(client.textRenderer, "Z:", width / 2 + 18, y + 6, 0xFFFFFF);
+ context.drawTextWithShadow(client.textRenderer, "#", x + entryWidth - 105, y + 6, 0xFFFFFF);
+ enabled.setPosition(x + 10, y + 1);
+ nameField.setPosition(x + 32, y);
+ xField.setPosition(width / 2 - 48, y);
+ yField.setPosition(width / 2 - 11, y);
+ zField.setPosition(width / 2 + 26, y);
+ colorField.setPosition(x + entryWidth - 99, y);
+ buttonDelete.setPosition(x + entryWidth - 38, y);
+ for (ClickableWidget child : children) {
+ child.render(context, mouseX, mouseY, tickDelta);
+ }
}
}
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsScreen.java
index 9f82f7a2..23a24361 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsScreen.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsScreen.java
@@ -1,9 +1,8 @@
package de.hysky.skyblocker.skyblock.waypoint;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.MultimapBuilder;
-import de.hysky.skyblocker.utils.waypoint.WaypointCategory;
+import de.hysky.skyblocker.utils.waypoint.NamedWaypoint;
import net.minecraft.client.gui.DrawContext;
+import net.minecraft.client.gui.screen.ConfirmScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.GridWidget;
@@ -11,31 +10,21 @@ import net.minecraft.client.gui.widget.SimplePositioningWidget;
import net.minecraft.screen.ScreenTexts;
import net.minecraft.text.Text;
-public class WaypointsScreen extends Screen {
- private final Screen parent;
- final Multimap<String, WaypointCategory> waypoints = MultimapBuilder.hashKeys().arrayListValues().build();
- private WaypointsListWidget waypointsListWidget;
+public class WaypointsScreen extends AbstractWaypointsScreen<Screen> {
private ButtonWidget buttonNew;
private ButtonWidget buttonDone;
- protected WaypointsScreen() {
- this(null);
- }
-
public WaypointsScreen(Screen parent) {
- super(Text.translatable("skyblocker.waypoints.config"));
- this.parent = parent;
- Waypoints.waypoints.forEach((island, category) -> waypoints.put(island, new WaypointCategory(category)));
+ super(Text.translatable("skyblocker.waypoints.config"), parent, Waypoints.waypointsDeepCopy());
}
@Override
protected void init() {
super.init();
- waypointsListWidget = addDrawableChild(new WaypointsListWidget(client, this, width, height - 96, 32, 24));
GridWidget gridWidget = new GridWidget();
gridWidget.getMainPositioner().marginX(5).marginY(2);
GridWidget.Adder adder = gridWidget.createAdder(2);
- adder.add(ButtonWidget.builder(Text.translatable("skyblocker.waypoints.share"), buttonShare -> {}).build());
+ adder.add(ButtonWidget.builder(Text.translatable("skyblocker.waypoints.share"), buttonShare -> client.setScreen(new WaypointsShareScreen(this, waypoints))).build());
buttonNew = adder.add(ButtonWidget.builder(Text.translatable("skyblocker.waypoints.newCategory"), buttonNew -> waypointsListWidget.addWaypointCategoryAfterSelected()).build());
adder.add(ButtonWidget.builder(ScreenTexts.CANCEL, button -> close()).build());
buttonDone = adder.add(ButtonWidget.builder(ScreenTexts.DONE, button -> {
@@ -54,17 +43,34 @@ public class WaypointsScreen extends Screen {
context.drawCenteredTextWithShadow(this.textRenderer, this.title, this.width / 2, 16, 0xFFFFFF);
}
+ @Override
+ protected boolean isEnabled(NamedWaypoint waypoint) {
+ return waypoint.shouldRender();
+ }
+
+ @Override
+ protected void enabledChanged(NamedWaypoint waypoint, boolean enabled) {
+ waypoint.setShouldRender(enabled);
+ }
+
private void saveWaypoints() {
Waypoints.waypoints.clear();
Waypoints.waypoints.putAll(waypoints);
Waypoints.saveWaypoints(client);
}
- private void updateButtons() {}
-
- @SuppressWarnings("DataFlowIssue")
@Override
public void close() {
- client.setScreen(parent);
+ assert client != null;
+ if (!waypoints.equals(Waypoints.waypoints)) {
+ client.setScreen(new ConfirmScreen(confirmedAction -> client.setScreen(confirmedAction ? parent : this),
+ Text.translatable("text.skyblocker.quit_config"),
+ Text.translatable("text.skyblocker.quit_config_sure"),
+ Text.translatable("text.skyblocker.quit_discard"),
+ ScreenTexts.CANCEL
+ ));
+ } else {
+ client.setScreen(parent);
+ }
}
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsShareScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsShareScreen.java
new file mode 100644
index 00000000..aee21ec8
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsShareScreen.java
@@ -0,0 +1,86 @@
+package de.hysky.skyblocker.skyblock.waypoint;
+
+import com.google.common.collect.Multimap;
+import de.hysky.skyblocker.utils.waypoint.NamedWaypoint;
+import de.hysky.skyblocker.utils.waypoint.WaypointCategory;
+import net.minecraft.client.gui.DrawContext;
+import net.minecraft.client.gui.tooltip.Tooltip;
+import net.minecraft.client.gui.widget.ButtonWidget;
+import net.minecraft.client.gui.widget.GridWidget;
+import net.minecraft.client.gui.widget.SimplePositioningWidget;
+import net.minecraft.client.toast.SystemToast;
+import net.minecraft.screen.ScreenTexts;
+import net.minecraft.text.Text;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class WaypointsShareScreen extends AbstractWaypointsScreen<WaypointsScreen> {
+ private final Set<NamedWaypoint> selectedWaypoints = new HashSet<>();
+
+ protected WaypointsShareScreen(WaypointsScreen parent, Multimap<String, WaypointCategory> waypoints) {
+ super(Text.translatable("skyblocker.waypoints.shareWaypoints"), parent, waypoints, parent.island);
+ }
+
+ @Override
+ protected void init() {
+ super.init();
+ GridWidget gridWidget = new GridWidget();
+ gridWidget.getMainPositioner().marginX(5).marginY(2);
+ GridWidget.Adder adder = gridWidget.createAdder(2);
+ adder.add(ButtonWidget.builder(Text.translatable("skyblocker.waypoints.importWaypointsSkytils"), buttonImport -> {
+ try {
+ List<WaypointCategory> waypointCategories = Waypoints.fromSkytilsBase64(client.keyboard.getClipboard(), island);
+ for (WaypointCategory waypointCategory : waypointCategories) {
+ selectedWaypoints.addAll(waypointCategory.waypoints());
+ waypoints.put(waypointCategory.island(), waypointCategory);
+ }
+ waypointsListWidget.updateEntries();
+ SystemToast.show(client.getToastManager(), Waypoints.WAYPOINTS_TOAST_TYPE, Text.translatable("skyblocker.waypoints.importSuccess"), Text.translatable("skyblocker.waypoints.importSuccessText", waypointCategories.stream().map(WaypointCategory::waypoints).mapToInt(List::size).sum(), waypointCategories.size()));
+ } catch (Exception e) {
+ Waypoints.LOGGER.error("[Skyblocker Waypoints] Encountered exception while parsing Skytils waypoint data", e);
+ SystemToast.show(client.getToastManager(), Waypoints.WAYPOINTS_TOAST_TYPE, Text.translatable("skyblocker.waypoints.importError"), Text.translatable("skyblocker.waypoints.importErrorText"));
+ }
+ }).tooltip(Tooltip.of(Text.translatable("skyblocker.waypoints.importWaypointsSkytils.tooltip"))).build());
+ adder.add(ButtonWidget.builder(Text.translatable("skyblocker.waypoints.importWaypointsSnoopy"), buttonImport -> {
+ }).tooltip(Tooltip.of(Text.translatable("skyblocker.waypoints.importWaypointsSnoopy.tooltip"))).build());
+ adder.add(ButtonWidget.builder(ScreenTexts.BACK, buttonBack -> close()).build());
+ adder.add(ButtonWidget.builder(Text.translatable("skyblocker.waypoints.exportWaypointsSkytils"), buttonExport -> {
+ try {
+ List<WaypointCategory> waypointCategories = waypoints.values().stream().filter(waypointCategory -> waypointCategory.island().equals(island)).map(WaypointCategory.filter(selectedWaypoints::contains)).filter(waypointCategory -> !waypointCategory.waypoints().isEmpty()).toList();
+ client.keyboard.setClipboard(Waypoints.toSkytilsBase64(waypointCategories));
+ SystemToast.show(client.getToastManager(), Waypoints.WAYPOINTS_TOAST_TYPE, Text.translatable("skyblocker.waypoints.exportSuccess"), Text.translatable("skyblocker.waypoints.exportSuccessText", waypointCategories.stream().map(WaypointCategory::waypoints).mapToInt(List::size).sum(), waypointCategories.size()));
+ } catch (Exception e) {
+ Waypoints.LOGGER.error("[Skyblocker Waypoints] Encountered exception while serializing Skytils waypoint data", e);
+ SystemToast.show(client.getToastManager(), Waypoints.WAYPOINTS_TOAST_TYPE, Text.translatable("skyblocker.waypoints.exportError"), Text.translatable("skyblocker.waypoints.exportErrorText"));
+ }
+ }).tooltip(Tooltip.of(Text.translatable("skyblocker.waypoints.exportWaypointsSkytils.tooltip"))).build());
+ gridWidget.refreshPositions();
+ SimplePositioningWidget.setPos(gridWidget, 0, this.height - 64, this.width, 64);
+ gridWidget.forEachChild(this::addDrawableChild);
+ }
+
+ @Override
+ public void render(DrawContext context, int mouseX, int mouseY, float delta) {
+ super.render(context, mouseX, mouseY, delta);
+ context.drawCenteredTextWithShadow(this.textRenderer, this.title, this.width / 2, 16, 0xFFFFFF);
+ }
+
+ @Override
+ protected boolean isEnabled(NamedWaypoint waypoint) {
+ return selectedWaypoints.contains(waypoint);
+ }
+
+ @Override
+ protected void enabledChanged(NamedWaypoint waypoint, boolean enabled) {
+ if (enabled) selectedWaypoints.add(waypoint);
+ else selectedWaypoints.remove(waypoint);
+ }
+
+ @SuppressWarnings("DataFlowIssue")
+ @Override
+ public void close() {
+ client.setScreen(parent);
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/utils/waypoint/NamedWaypoint.java b/src/main/java/de/hysky/skyblocker/utils/waypoint/NamedWaypoint.java
index f959de78..2f02b51f 100644
--- a/src/main/java/de/hysky/skyblocker/utils/waypoint/NamedWaypoint.java
+++ b/src/main/java/de/hysky/skyblocker/utils/waypoint/NamedWaypoint.java
@@ -13,6 +13,7 @@ import net.minecraft.text.TextCodecs;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
+import java.util.Objects;
import java.util.function.Supplier;
public class NamedWaypoint extends Waypoint {
@@ -23,6 +24,7 @@ public class NamedWaypoint extends Waypoint {
colorComponentsList -> colorComponentsList.size() == 3 ? DataResult.success(Floats.toArray(colorComponentsList)) : DataResult.error(() -> "Expected 3 color components, got " + colorComponentsList.size() + " instead"),
Floats::asList
).fieldOf("colorComponents").forGetter(secretWaypoint -> secretWaypoint.colorComponents),
+ Codec.FLOAT.fieldOf("alpha").forGetter(secretWaypoint -> secretWaypoint.alpha),
Codec.BOOL.fieldOf("shouldRender").forGetter(Waypoint::shouldRender)
).apply(instance, NamedWaypoint::new));
public static final Codec<NamedWaypoint> SKYTILS_CODEC = RecordCodecBuilder.create(instance -> instance.group(
@@ -30,46 +32,78 @@ public class NamedWaypoint extends Waypoint {
Codec.INT.fieldOf("y").forGetter(waypoint -> waypoint.pos.getY()),
Codec.INT.fieldOf("z").forGetter(waypoint -> waypoint.pos.getZ()),
Codec.either(Codec.STRING, Codec.INT).xmap(either -> either.map(str -> str, Object::toString), Either::left).fieldOf("name").forGetter(waypoint -> waypoint.name.getString()),
- Codec.INT.fieldOf("color").forGetter(waypoint -> (int) (waypoint.colorComponents[0] * 255) << 16 | (int) (waypoint.colorComponents[1] * 255) << 8 | (int) (waypoint.colorComponents[2] * 255)),
+ Codec.INT.fieldOf("color").forGetter(waypoint -> (int) (waypoint.alpha * 255) << 24 | (int) (waypoint.colorComponents[0] * 255) << 16 | (int) (waypoint.colorComponents[1] * 255) << 8 | (int) (waypoint.colorComponents[2] * 255)),
Codec.BOOL.fieldOf("enabled").forGetter(Waypoint::shouldRender)
).apply(instance, NamedWaypoint::fromSkytils));
- protected final Text name;
- protected final Vec3d centerPos;
+ public final Text name;
+ public final Vec3d centerPos;
public NamedWaypoint(BlockPos pos, String name, float[] colorComponents) {
this(pos, name, colorComponents, true);
}
public NamedWaypoint(BlockPos pos, String name, float[] colorComponents, boolean shouldRender) {
- this(pos, Text.of(name), colorComponents, shouldRender);
+ this(pos, name, colorComponents, DEFAULT_HIGHLIGHT_ALPHA, shouldRender);
}
- public NamedWaypoint(BlockPos pos, Text name, float[] colorComponents, boolean shouldRender) {
- this(pos, name, () -> SkyblockerConfigManager.get().general.waypoints.waypointType, colorComponents, shouldRender);
+ public NamedWaypoint(BlockPos pos, String name, float[] colorComponents, float alpha, boolean shouldRender) {
+ this(pos, Text.of(name), colorComponents, alpha, shouldRender);
}
- public NamedWaypoint(BlockPos pos, String name, Supplier<Type> typeSupplier, float[] colorComponents, boolean shouldRender) {
- this(pos, Text.of(name), typeSupplier, colorComponents, shouldRender);
+ public NamedWaypoint(BlockPos pos, Text name, float[] colorComponents, float alpha, boolean shouldRender) {
+ this(pos, name, () -> SkyblockerConfigManager.get().uiAndVisuals.waypoints.waypointType, colorComponents, alpha, shouldRender);
}
public NamedWaypoint(BlockPos pos, Text name, Supplier<Type> typeSupplier, float[] colorComponents) {
- this(pos, name, typeSupplier, colorComponents, true);
+ this(pos, name, typeSupplier, colorComponents, DEFAULT_HIGHLIGHT_ALPHA, true);
}
- public NamedWaypoint(BlockPos pos, Text name, Supplier<Type> typeSupplier, float[] colorComponents, boolean shouldRender) {
- super(pos, typeSupplier, colorComponents, DEFAULT_HIGHLIGHT_ALPHA, DEFAULT_LINE_WIDTH, true, shouldRender);
+ public NamedWaypoint(BlockPos pos, Text name, Supplier<Type> typeSupplier, float[] colorComponents, float alpha, boolean shouldRender) {
+ super(pos, typeSupplier, colorComponents, alpha, DEFAULT_LINE_WIDTH, true, shouldRender);
this.name = name;
this.centerPos = pos.toCenterPos();
}
public static NamedWaypoint fromSkytils(int x, int y, int z, String name, int color, boolean enabled) {
- return new NamedWaypoint(new BlockPos(x, y, z), name, new float[]{((color & 0x00FF0000) >> 16) / 255f, ((color & 0x0000FF00) >> 8) / 255f, (color & 0x000000FF) / 255f}, enabled);
+ float alpha = ((color & 0xFF000000) >>> 24) / 255f;
+ if (alpha == 0) {
+ alpha = DEFAULT_HIGHLIGHT_ALPHA;
+ }
+ return new NamedWaypoint(new BlockPos(x, y, z), name, new float[]{((color & 0x00FF0000) >> 16) / 255f, ((color & 0x0000FF00) >> 8) / 255f, (color & 0x000000FF) / 255f}, alpha, enabled);
+ }
+
+ public NamedWaypoint copy() {
+ return new NamedWaypoint(pos, name, typeSupplier, getColorComponents(), alpha, shouldRender());
+ }
+
+ @Override
+ public NamedWaypoint withX(int x) {
+ return new NamedWaypoint(new BlockPos(x, pos.getY(), pos.getZ()), name, typeSupplier, getColorComponents(), alpha, shouldRender());
+ }
+
+ @Override
+ public NamedWaypoint withY(int y) {
+ return new NamedWaypoint(pos.withY(y), name, typeSupplier, getColorComponents(), alpha, shouldRender());
+ }
+
+ @Override
+ public NamedWaypoint withZ(int z) {
+ return new NamedWaypoint(new BlockPos(pos.getX(), pos.getY(), z), name, typeSupplier, getColorComponents(), alpha, shouldRender());
+ }
+
+ @Override
+ public NamedWaypoint withColor(float[] colorComponents, float alpha) {
+ return new NamedWaypoint(pos, name, typeSupplier, colorComponents, alpha, shouldRender());
}
public Text getName() {
return name;
}
+ public NamedWaypoint withName(String name) {
+ return new NamedWaypoint(pos, Text.literal(name), typeSupplier, getColorComponents(), alpha, shouldRender());
+ }
+
protected boolean shouldRenderName() {
return true;
}
@@ -83,7 +117,12 @@ public class NamedWaypoint extends Waypoint {
}
@Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), name);
+ }
+
+ @Override
public boolean equals(Object obj) {
- return this == obj || obj instanceof NamedWaypoint waypoint && name.equals(waypoint.name);
+ return this == obj || super.equals(obj) && obj instanceof NamedWaypoint waypoint && name.equals(waypoint.name);
}
}
diff --git a/src/main/java/de/hysky/skyblocker/utils/waypoint/Waypoint.java b/src/main/java/de/hysky/skyblocker/utils/waypoint/Waypoint.java
index 75e2edcf..c991fb9c 100644
--- a/src/main/java/de/hysky/skyblocker/utils/waypoint/Waypoint.java
+++ b/src/main/java/de/hysky/skyblocker/utils/waypoint/Waypoint.java
@@ -3,10 +3,12 @@ package de.hysky.skyblocker.utils.waypoint;
import de.hysky.skyblocker.utils.render.RenderHelper;
import de.hysky.skyblocker.utils.render.Renderable;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
+import net.minecraft.util.StringIdentifiable;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import java.util.Arrays;
+import java.util.Objects;
import java.util.function.Supplier;
public class Waypoint implements Renderable {
@@ -16,9 +18,9 @@ public class Waypoint implements Renderable {
final Box box;
final Supplier<Type> typeSupplier;
protected final float[] colorComponents;
- final float alpha;
- final float lineWidth;
- final boolean throughWalls;
+ public final float alpha;
+ public final float lineWidth;
+ public final boolean throughWalls;
private boolean shouldRender;
public Waypoint(BlockPos pos, Type type, float[] colorComponents) {
@@ -56,6 +58,22 @@ public class Waypoint implements Renderable {
this.shouldRender = shouldRender;
}
+ public Waypoint withX(int x) {
+ return new Waypoint(new BlockPos(x, pos.getY(), pos.getZ()), typeSupplier, getColorComponents(), alpha, lineWidth, throughWalls, shouldRender());
+ }
+
+ public Waypoint withY(int y) {
+ return new Waypoint(pos.withY(y), typeSupplier, getColorComponents(), alpha, lineWidth, throughWalls, shouldRender());
+ }
+
+ public Waypoint withZ(int z) {
+ return new Waypoint(new BlockPos(pos.getX(), pos.getY(), z), typeSupplier, getColorComponents(), alpha, lineWidth, throughWalls, shouldRender());
+ }
+
+ public Waypoint withColor(float[] colorComponents, float alpha) {
+ return new Waypoint(pos, typeSupplier, colorComponents, alpha, lineWidth, throughWalls, shouldRender());
+ }
+
public boolean shouldRender() {
return shouldRender;
}
@@ -72,6 +90,10 @@ public class Waypoint implements Renderable {
this.shouldRender = !this.shouldRender;
}
+ public void setShouldRender(boolean shouldRender) {
+ this.shouldRender = shouldRender;
+ }
+
public float[] getColorComponents() {
return colorComponents;
}
@@ -96,11 +118,16 @@ public class Waypoint implements Renderable {
}
@Override
+ public int hashCode() {
+ return Objects.hash(pos, typeSupplier.get(), Arrays.hashCode(colorComponents), alpha, lineWidth, throughWalls, shouldRender);
+ }
+
+ @Override
public boolean equals(Object obj) {
return super.equals(obj) || obj instanceof Waypoint other && pos.equals(other.pos) && typeSupplier.get() == other.typeSupplier.get() && Arrays.equals(colorComponents, other.colorComponents) && alpha == other.alpha && lineWidth == other.lineWidth && throughWalls == other.throughWalls && shouldRender == other.shouldRender;
}
- public enum Type {
+ public enum Type implements StringIdentifiable {
WAYPOINT,
OUTLINED_WAYPOINT,
HIGHLIGHT,
@@ -108,6 +135,11 @@ public class Waypoint implements Renderable {
OUTLINE;
@Override
+ public String asString() {
+ return name().toLowerCase();
+ }
+
+ @Override
public String toString() {
return switch (this) {
case WAYPOINT -> "Waypoint";
diff --git a/src/main/java/de/hysky/skyblocker/utils/waypoint/WaypointCategory.java b/src/main/java/de/hysky/skyblocker/utils/waypoint/WaypointCategory.java
index b1ac6135..db2a6d82 100644
--- a/src/main/java/de/hysky/skyblocker/utils/waypoint/WaypointCategory.java
+++ b/src/main/java/de/hysky/skyblocker/utils/waypoint/WaypointCategory.java
@@ -4,8 +4,10 @@ import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
-import java.util.ArrayList;
import java.util.List;
+import java.util.function.Predicate;
+import java.util.function.UnaryOperator;
+import java.util.stream.Collectors;
public record WaypointCategory(String name, String island, List<NamedWaypoint> waypoints) {
public static final Codec<WaypointCategory> CODEC = RecordCodecBuilder.create(instance -> instance.group(
@@ -19,13 +21,23 @@ public record WaypointCategory(String name, String island, List<NamedWaypoint> w
NamedWaypoint.SKYTILS_CODEC.listOf().fieldOf("waypoints").forGetter(WaypointCategory::waypoints)
).apply(instance, WaypointCategory::new));
- public WaypointCategory(WaypointCategory waypointCategory) {
- this(waypointCategory.name(), waypointCategory.island(), new ArrayList<>(waypointCategory.waypoints()));
+ public static UnaryOperator<WaypointCategory> filter(Predicate<NamedWaypoint> predicate) {
+ return waypointCategory -> new WaypointCategory(waypointCategory.name(), waypointCategory.island(), waypointCategory.waypoints().stream().filter(predicate).toList());
+ }
+
+ public WaypointCategory withName(String name) {
+ return new WaypointCategory(name, island(), waypoints());
+ }
+
+ public WaypointCategory deepCopy() {
+ return new WaypointCategory(name(), island(), waypoints().stream().map(NamedWaypoint::copy).collect(Collectors.toList()));
}
public void render(WorldRenderContext context) {
for (NamedWaypoint waypoint : waypoints) {
- waypoint.render(context);
+ if (waypoint.shouldRender()) {
+ waypoint.render(context);
+ }
}
}
}