Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.awt.Color;
import lombok.Builder;
import lombok.Getter;
import org.jetbrains.annotations.Nullable;

/**
* Represents a waypoint which can be shown on the client.
Expand Down Expand Up @@ -82,4 +83,45 @@ public final class Waypoint {
*/
boolean hidden;

/**
* Whether the beacon beam for this waypoint is drawn.
*
* @since 1.2.7
*/
@Builder.Default
boolean showBeam = true;

/**
* Whether the in-world block outline highlight at the waypoint location is drawn.
*
* @since 1.2.7
*/
@Builder.Default
boolean highlightBlock = true;

/**
* Line width of the block highlight outline when {@link #highlightBlock} is enabled.
*
* <p>Accepts {@code 1.5F} to {@code 7.5F}. Leaving the
* field at its default of {@code 0.0F} is treated as a
* fallback to the player's own configured line width.</p>
*
* @since 1.2.7
*/
@Builder.Default
float highlightBlockLineWidth = 0.0F;

/**
* Label and HUD text overrides applied to this waypoint.
*
* <p>Set to a built {@link WaypointTextStyle} to drive the
* client's text rendering from the server; leave {@code null} to
* defer to the Lunar waypoint mod's own settings.</p>
*
* @return the text style, or {@code null} when no override is sent
* @since 1.2.7
*/
@Builder.Default
@Nullable WaypointTextStyle textStyle = null;

}
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,22 @@ public boolean isClientNotify() {
*/
public abstract void resetWaypoints(Recipients recipients);

/**
* Shows a {@link Waypoint} for the {@link Recipients} that was previously hidden.
*
* @param recipients the recipients that are receiving the packet
* @param waypointName the waypoint name
* @since 1.2.7
*/
public abstract void showWaypoint(Recipients recipients, String waypointName);

/**
* Hides a {@link Waypoint} for the {@link Recipients} without removing it.
*
* @param recipients the recipients that are receiving the packet
* @param waypointName the waypoint name
* @since 1.2.7
*/
public abstract void hideWaypoint(Recipients recipients, String waypointName);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* This file is part of Apollo, licensed under the MIT License.
*
* Copyright (c) 2026 Moonsworth
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.lunarclient.apollo.module.waypoint;

import lombok.Builder;
import lombok.Getter;

/**
* Overrides for a waypoint's on-screen label, icons and distance HUD on the Lunar client.
*
* @since 1.2.7
*/
@Getter
@Builder
public final class WaypointTextStyle {

/**
* Whether the waypoint label (text and box) is drawn at all.
*
* @since 1.2.7
*/
@Builder.Default
boolean showText = true;

/**
* Restricts the waypoint label drawing to when the player is looking roughly toward the waypoint.
*
* @since 1.2.7
*/
@Builder.Default
boolean onlyShowTextWhenLookingNear = false;

/**
* Whether the waypoint icons are drawn.
*
* @since 1.2.7
*/
@Builder.Default
boolean showIcons = false;

/**
* The waypoint scale applied to the label icon.
*
* <p>Accepts {@code 0.1F} to {@code 3.0F}</p>
*
* @since 1.2.7
*/
@Builder.Default
float textIconScale = 1.5F;

/**
* The waypoint scale applied to the main label text.
*
* <p>Accepts {@code 0.1F} to {@code 2.0F}</p>
*
* @since 1.2.7
*/
@Builder.Default
float labelScale = 1.0F;

/**
* The waypoint padding of the label background box.
*
* <p>Accepts {@code 1.0F} to {@code 8.0F}</p>
*
* @since 1.2.7
*/
@Builder.Default
float boxPadding = 4.0F;

/**
* Whether a border is drawn around the label background box.
*
* @since 1.2.7
*/
@Builder.Default
boolean boxBorders = true;

/**
* Whether a shadow is drawn behind the label text.
*
* @since 1.2.7
*/
@Builder.Default
boolean textShadow = false;

/**
* Whether the distance from the player to the waypoint is shown next to the label.
*
* @since 1.2.7
*/
@Builder.Default
boolean showDistance = true;

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@
import com.lunarclient.apollo.player.ApolloPlayer;
import com.lunarclient.apollo.recipients.Recipients;
import com.lunarclient.apollo.waypoint.v1.DisplayWaypointMessage;
import com.lunarclient.apollo.waypoint.v1.HideWaypointMessage;
import com.lunarclient.apollo.waypoint.v1.RemoveWaypointMessage;
import com.lunarclient.apollo.waypoint.v1.ResetWaypointsMessage;
import com.lunarclient.apollo.waypoint.v1.ShowWaypointMessage;
import java.awt.Color;
import java.lang.reflect.Type;
import java.util.Arrays;
Expand All @@ -43,6 +45,8 @@
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;

import static com.lunarclient.apollo.util.Ranges.checkRange;

/**
* Provides the waypoints module.
*
Expand Down Expand Up @@ -87,6 +91,24 @@ public void resetWaypoints(@NonNull Recipients recipients) {
recipients.forEach(player -> ((AbstractApolloPlayer) player).sendPacket(message));
}

@Override
public void showWaypoint(@NonNull Recipients recipients, @NonNull String waypointName) {
ShowWaypointMessage message = ShowWaypointMessage.newBuilder()
.setName(waypointName)
.build();

recipients.forEach(player -> ((AbstractApolloPlayer) player).sendPacket(message));
}

@Override
public void hideWaypoint(@NonNull Recipients recipients, @NonNull String waypointName) {
HideWaypointMessage message = HideWaypointMessage.newBuilder()
.setName(waypointName)
.build();

recipients.forEach(player -> ((AbstractApolloPlayer) player).sendPacket(message));
}

private void onPlayerRegister(ApolloRegisterPlayerEvent event) {
ApolloPlayer player = event.getPlayer();
List<Waypoint> waypoints = this.getOptions().get(player, WaypointModule.DEFAULT_WAYPOINTS);
Expand All @@ -99,31 +121,74 @@ private void onPlayerRegister(ApolloRegisterPlayerEvent event) {
}

private DisplayWaypointMessage toProtobuf(Waypoint waypoint) {
return DisplayWaypointMessage.newBuilder()
DisplayWaypointMessage.Builder builder = DisplayWaypointMessage.newBuilder()
.setName(waypoint.getName())
.setLocation(NetworkTypes.toProtobuf(waypoint.getLocation()))
.setColor(NetworkTypes.toProtobuf(waypoint.getColor()))
.setPreventRemoval(waypoint.isPreventRemoval())
.setHidden(waypoint.isHidden())
.setShowBeam(waypoint.isShowBeam())
.setHighlightBlock(waypoint.isHighlightBlock());

float highlightBlockLineWidth = waypoint.getHighlightBlockLineWidth();
if (highlightBlockLineWidth != 0.0F) {
builder.setHighlightBlockLineWidth(checkRange(highlightBlockLineWidth, 1.5F, 7.5F, "Waypoint#highlightBlockLineWidth"));
}

WaypointTextStyle style = waypoint.getTextStyle();
if (style != null) {
builder.setStyle(this.toProtobuf(style));
}

return builder.build();
}

private com.lunarclient.apollo.waypoint.v1.WaypointTextStyle toProtobuf(WaypointTextStyle style) {
return com.lunarclient.apollo.waypoint.v1.WaypointTextStyle.newBuilder()
.setShowText(style.isShowText())
.setOnlyShowTextWhenLookingNear(style.isOnlyShowTextWhenLookingNear())
.setShowIcons(style.isShowIcons())
.setTextIconScale(checkRange(style.getTextIconScale(), 0.1F, 3.0F, "WaypointTextStyle#textIconScale"))
.setLabelScale(checkRange(style.getLabelScale(), 0.1F, 2.0F, "WaypointTextStyle#labelScale"))
.setBoxPadding(checkRange(style.getBoxPadding(), 1.0F, 8.0F, "WaypointTextStyle#boxPadding"))
.setBoxBorders(style.isBoxBorders())
.setTextShadow(style.isTextShadow())
.setShowDistance(style.isShowDistance())
.build();
}

private static final class WaypointSerializer implements TypeSerializer<Waypoint> {
@Override
public Waypoint deserialize(Type type, ConfigurationNode node) throws SerializationException {
return Waypoint.builder()
Waypoint.WaypointBuilder builder = Waypoint.builder()
.name(this.virtualNode(node, "name").getString())
.location(ApolloBlockLocation.builder()
.world(this.virtualNode(node, "location", "world").getString())
.x(this.virtualNode(node, "location", "x").getInt())
.y(this.virtualNode(node, "location", "y").getInt())
.z(this.virtualNode(node, "location", "z").getInt())
.build()
)
.color(Color.decode(this.virtualNode(node, "color").getString("#FFFFFF")))
.preventRemoval(this.virtualNode(node, "prevent-removal").getBoolean())
.hidden(this.virtualNode(node, "hidden").getBoolean())
.build();
.build())
.color(Color.decode(node.node("color").getString("#FFFFFF")))
.preventRemoval(node.node("prevent-removal").getBoolean())
.hidden(node.node("hidden").getBoolean());

if (node.hasChild("show-beam")) {
builder.showBeam(node.node("show-beam").getBoolean(true));
}

if (node.hasChild("highlight-block")) {
builder.highlightBlock(node.node("highlight-block").getBoolean(true));
}

if (node.hasChild("highlight-block-line-width")) {
builder.highlightBlockLineWidth((float) node.node("highlight-block-line-width").getDouble(4.0D));
}

if (node.hasChild("style")) {
builder.textStyle(this.readStyle(node.node("style")));
}

return builder.build();
}

@Override
Expand All @@ -141,6 +206,66 @@ public void serialize(Type type, @Nullable Waypoint waypoint, ConfigurationNode
node.node("color").set(String.format("#%06X", (0xFFFFFF & waypoint.getColor().getRGB())));
node.node("prevent-removal").set(waypoint.isPreventRemoval());
node.node("hidden").set(waypoint.isHidden());
node.node("show-beam").set(waypoint.isShowBeam());
node.node("highlight-block").set(waypoint.isHighlightBlock());
node.node("highlight-block-line-width").set(waypoint.getHighlightBlockLineWidth());

if (waypoint.getTextStyle() != null) {
this.writeStyle(node.node("style"), waypoint.getTextStyle());
}
}

private WaypointTextStyle readStyle(ConfigurationNode node) {
WaypointTextStyle.WaypointTextStyleBuilder builder = WaypointTextStyle.builder();
if (node.hasChild("show-text")) {
builder.showText(node.node("show-text").getBoolean(true));
}

if (node.hasChild("only-show-text-when-looking-near")) {
builder.onlyShowTextWhenLookingNear(node.node("only-show-text-when-looking-near").getBoolean(false));
}

if (node.hasChild("show-icons")) {
builder.showIcons(node.node("show-icons").getBoolean(false));
}

if (node.hasChild("text-icon-scale")) {
builder.textIconScale(node.node("text-icon-scale").getFloat(1.5F));
}

if (node.hasChild("label-scale")) {
builder.labelScale(node.node("label-scale").getFloat(1.0F));
}

if (node.hasChild("box-padding")) {
builder.boxPadding(node.node("box-padding").getFloat(4.0F));
}

if (node.hasChild("box-borders")) {
builder.boxBorders(node.node("box-borders").getBoolean(true));
}

if (node.hasChild("text-shadow")) {
builder.textShadow(node.node("text-shadow").getBoolean(false));
}

if (node.hasChild("show-distance")) {
builder.showDistance(node.node("show-distance").getBoolean(true));
}

return builder.build();
}

private void writeStyle(ConfigurationNode node, WaypointTextStyle style) throws SerializationException {
node.node("show-text").set(style.isShowText());
node.node("only-show-text-when-looking-near").set(style.isOnlyShowTextWhenLookingNear());
node.node("show-icons").set(style.isShowIcons());
node.node("text-icon-scale").set(style.getTextIconScale());
node.node("label-scale").set(style.getLabelScale());
node.node("box-padding").set(style.getBoxPadding());
node.node("box-borders").set(style.isBoxBorders());
node.node("text-shadow").set(style.isTextShadow());
node.node("show-distance").set(style.isShowDistance());
}

private ConfigurationNode virtualNode(ConfigurationNode source, Object... path) throws SerializationException {
Expand Down
Loading
Loading