diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index d9e8de162..d4c8e124e 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -41,7 +41,7 @@ jobs: fi - name: Gradle Publish - if: "${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/version/') }}" + if: "${{ github.ref == 'refs/heads/master' || github.ref == 'refs/heads/feature/server-links' || startsWith(github.ref, 'refs/heads/version/') }}" run: ./gradlew publish - name: Gradle Release diff --git a/api/src/main/java/com/lunarclient/apollo/common/icon/ResourceLocationIcon.java b/api/src/main/java/com/lunarclient/apollo/common/icon/ResourceLocationIcon.java new file mode 100644 index 000000000..f4716c4a6 --- /dev/null +++ b/api/src/main/java/com/lunarclient/apollo/common/icon/ResourceLocationIcon.java @@ -0,0 +1,48 @@ +/* + * 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.common.icon; + +import lombok.Builder; +import lombok.Getter; + +/** + * Represents a resource location icon. + * + * @since 1.2.5 + */ +@Getter +@Builder +public final class ResourceLocationIcon extends Icon { + + /** + * Returns the icon {@link String} resource location. + * + *

Represents a path to an icon that will appear for the player.

+ * + * @return the icon resource location + * @since 1.2.5 + */ + String resourceLocation; + +} diff --git a/api/src/main/java/com/lunarclient/apollo/module/serverlink/ServerLink.java b/api/src/main/java/com/lunarclient/apollo/module/serverlink/ServerLink.java new file mode 100644 index 000000000..2c6d5abfe --- /dev/null +++ b/api/src/main/java/com/lunarclient/apollo/module/serverlink/ServerLink.java @@ -0,0 +1,63 @@ +/* + * 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.serverlink; + +import lombok.Builder; +import lombok.Getter; +import net.kyori.adventure.text.Component; + +/** + * Represents a link entry displayed in the Server Links menu. + * + * @since 1.2.5 + */ +@Getter +@Builder +public final class ServerLink { + + /** + * Returns the server link {@link String} id. + * + * @return the server link id + * @since 1.2.5 + */ + String id; + + /** + * Returns the server link {@link Component} display name. + * + * @return the server link display name + * @since 1.2.5 + */ + Component displayName; + + /** + * Returns the server link {@link String} url. + * + * @return the server link url + * @since 1.2.5 + */ + String url; + +} diff --git a/api/src/main/java/com/lunarclient/apollo/module/serverlink/ServerLinkModule.java b/api/src/main/java/com/lunarclient/apollo/module/serverlink/ServerLinkModule.java new file mode 100644 index 000000000..f3010c971 --- /dev/null +++ b/api/src/main/java/com/lunarclient/apollo/module/serverlink/ServerLinkModule.java @@ -0,0 +1,130 @@ +/* + * 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.serverlink; + +import com.lunarclient.apollo.common.icon.ResourceLocationIcon; +import com.lunarclient.apollo.module.ApolloModule; +import com.lunarclient.apollo.module.ModuleDefinition; +import com.lunarclient.apollo.recipients.Recipients; +import java.util.List; +import org.jetbrains.annotations.ApiStatus; + +/** + * Represents the server links module. + * + *

This module provides support for the Server Links feature introduced in + * Minecraft 1.21.0, with compatibility extending down to version 1.7.

+ * + * @since 1.2.5 + */ +@ApiStatus.NonExtendable +@ModuleDefinition(id = "server_link", name = "Server Link") +public abstract class ServerLinkModule extends ApolloModule { + + /** + * Overrides the server link menu title image for the {@link Recipients}. + * + *

The provided {@link ResourceLocationIcon} will be displayed in place of the default + * menu title.

+ * + *

The resource location must reference a valid client-side asset using the standard + * namespace format:

+ * + *
+     * minecraft:textures/item/apple.png
+     * lunar:logo/logo-100x100.png
+     * 
+ * + *

For optimal results, a square image (e.g. 128x128) is recommended.

+ * + * @param recipients the recipients that are receiving the packet + * @param icon the resource location icon + * @since 1.2.5 + */ + public abstract void overrideServerLinkResource(Recipients recipients, ResourceLocationIcon icon); + + /** + * Resets the server link menu title image for the {@link Recipients}. + * + *

Reverts back to displaying the default menu title.

+ * + * @param recipients the recipients that are receiving the packet + * @since 1.2.5 + */ + public abstract void resetServerLinkResource(Recipients recipients); + + /** + * Adds or updates the {@link ServerLink} for the {@link Recipients}. + * + * @param recipients the recipients that are receiving the packet + * @param serverLink the server link + * @since 1.2.5 + */ + public abstract void addServerLink(Recipients recipients, ServerLink serverLink); + + /** + * Adds or updates the {@link ServerLink}s for the {@link Recipients}. + * + * @param recipients the recipients that are receiving the packet + * @param serverLinks the server links + * @since 1.2.5 + */ + public abstract void addServerLink(Recipients recipients, List serverLinks); + + /** + * Removes the {@link ServerLink} from the {@link Recipients}. + * + * @param recipients the recipients that are receiving the packet + * @param serverLinkId the server link id + * @since 1.2.5 + */ + public abstract void removeServerLink(Recipients recipients, String serverLinkId); + + /** + * Removes the {@link ServerLink} from the {@link Recipients}. + * + * @param recipients the recipients that are receiving the packet + * @param serverLink the server link + * @since 1.2.5 + */ + public abstract void removeServerLink(Recipients recipients, ServerLink serverLink); + + /** + * Removes the {@link ServerLink}s from the {@link Recipients}. + * + * @param recipients the recipients that are receiving the packet + * @param serverLinkIds the server link ids + * @since 1.2.5 + */ + public abstract void removeServerLink(Recipients recipients, List serverLinkIds); + + /** + * Resets all {@link ServerLink}s for the {@link Recipients}. + * + * @param recipients the recipients that are receiving the packet + * @since 1.2.5 + */ + public abstract void resetServerLinks(Recipients recipients); + +} diff --git a/common/src/main/java/com/lunarclient/apollo/module/serverlink/ServerLinkModuleImpl.java b/common/src/main/java/com/lunarclient/apollo/module/serverlink/ServerLinkModuleImpl.java new file mode 100644 index 000000000..4427a9718 --- /dev/null +++ b/common/src/main/java/com/lunarclient/apollo/module/serverlink/ServerLinkModuleImpl.java @@ -0,0 +1,114 @@ +/* + * 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.serverlink; + +import com.lunarclient.apollo.common.ApolloComponent; +import com.lunarclient.apollo.common.icon.ResourceLocationIcon; +import com.lunarclient.apollo.network.NetworkTypes; +import com.lunarclient.apollo.player.AbstractApolloPlayer; +import com.lunarclient.apollo.recipients.Recipients; +import com.lunarclient.apollo.serverlink.v1.AddServerLinkMessage; +import com.lunarclient.apollo.serverlink.v1.OverrideServerLinkResourceMessage; +import com.lunarclient.apollo.serverlink.v1.RemoveServerLinkMessage; +import com.lunarclient.apollo.serverlink.v1.ResetServerLinkResourceMessage; +import com.lunarclient.apollo.serverlink.v1.ResetServerLinksMessage; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import lombok.NonNull; + +/** + * Provides the server link module. + * + * @since 1.2.5 + */ +public final class ServerLinkModuleImpl extends ServerLinkModule { + + @Override + public void overrideServerLinkResource(@NonNull Recipients recipients, @NonNull ResourceLocationIcon icon) { + OverrideServerLinkResourceMessage message = OverrideServerLinkResourceMessage.newBuilder() + .setIcon(NetworkTypes.toProtobuf(icon)) + .build(); + + recipients.forEach(player -> ((AbstractApolloPlayer) player).sendPacket(message)); + } + + @Override + public void resetServerLinkResource(@NonNull Recipients recipients) { + ResetServerLinkResourceMessage message = ResetServerLinkResourceMessage.getDefaultInstance(); + recipients.forEach(player -> ((AbstractApolloPlayer) player).sendPacket(message)); + } + + @Override + public void addServerLink(@NonNull Recipients recipients, @NonNull ServerLink serverLink) { + this.addServerLink(recipients, Collections.singletonList(serverLink)); + } + + @Override + public void addServerLink(@NonNull Recipients recipients, @NonNull List serverLinks) { + List serverLinksProto = serverLinks.stream() + .map(this::toProtobuf) + .collect(Collectors.toList()); + + AddServerLinkMessage message = AddServerLinkMessage.newBuilder() + .addAllServerLinks(serverLinksProto) + .build(); + + recipients.forEach(player -> ((AbstractApolloPlayer) player).sendPacket(message)); + } + + @Override + public void removeServerLink(@NonNull Recipients recipients, @NonNull String serverLinkId) { + this.removeServerLink(recipients, Collections.singletonList(serverLinkId)); + } + + @Override + public void removeServerLink(@NonNull Recipients recipients, @NonNull ServerLink serverLink) { + this.removeServerLink(recipients, Collections.singletonList(serverLink.getId())); + } + + @Override + public void removeServerLink(@NonNull Recipients recipients, @NonNull List serverLinkIds) { + RemoveServerLinkMessage message = RemoveServerLinkMessage.newBuilder() + .addAllServerLinkIds(serverLinkIds) + .build(); + + recipients.forEach(player -> ((AbstractApolloPlayer) player).sendPacket(message)); + } + + @Override + public void resetServerLinks(@NonNull Recipients recipients) { + ResetServerLinksMessage message = ResetServerLinksMessage.getDefaultInstance(); + recipients.forEach(player -> ((AbstractApolloPlayer) player).sendPacket(message)); + } + + private com.lunarclient.apollo.serverlink.v1.ServerLink toProtobuf(ServerLink serverLink) { + return com.lunarclient.apollo.serverlink.v1.ServerLink.newBuilder() + .setId(serverLink.getId()) + .setDisplayNameAdventureJsonLines(ApolloComponent.toJson(serverLink.getDisplayName())) + .setUrl(serverLink.getUrl()) + .build(); + } + +} diff --git a/common/src/main/java/com/lunarclient/apollo/network/NetworkTypes.java b/common/src/main/java/com/lunarclient/apollo/network/NetworkTypes.java index 0ecf1dcd8..6d20395f0 100644 --- a/common/src/main/java/com/lunarclient/apollo/network/NetworkTypes.java +++ b/common/src/main/java/com/lunarclient/apollo/network/NetworkTypes.java @@ -30,6 +30,7 @@ import com.lunarclient.apollo.common.icon.AdvancedResourceLocationIcon; import com.lunarclient.apollo.common.icon.Icon; import com.lunarclient.apollo.common.icon.ItemStackIcon; +import com.lunarclient.apollo.common.icon.ResourceLocationIcon; import com.lunarclient.apollo.common.icon.SimpleResourceLocationIcon; import com.lunarclient.apollo.common.location.ApolloBlockLocation; import com.lunarclient.apollo.common.location.ApolloLocation; @@ -484,37 +485,15 @@ public static com.lunarclient.apollo.common.v1.Icon toProtobuf(Icon icon) { com.lunarclient.apollo.common.v1.Icon.Builder builder = com.lunarclient.apollo.common.v1.Icon.newBuilder(); if (icon instanceof ItemStackIcon) { - ItemStackIcon item = (ItemStackIcon) icon; - String itemName = item.getItemName(); - - com.lunarclient.apollo.common.v1.ItemStackIcon.Builder itemBuilder = com.lunarclient.apollo.common.v1.ItemStackIcon.newBuilder() - .setItemId(item.getItemId()) - .setCustomModelData(item.getCustomModelData()); - - if (itemName != null) { - itemBuilder.setItemName(itemName); - } - - builder.setItemStack(itemBuilder.build()); + builder.setItemStack(NetworkTypes.toProtobuf((ItemStackIcon) icon)); + } else if (icon instanceof ResourceLocationIcon) { + builder.setResourceLocation(NetworkTypes.toProtobuf((ResourceLocationIcon) icon)); } else if (icon instanceof SimpleResourceLocationIcon) { - SimpleResourceLocationIcon simple = (SimpleResourceLocationIcon) icon; - - builder.setSimpleResourceLocation(com.lunarclient.apollo.common.v1.SimpleResourceLocationIcon.newBuilder() - .setResourceLocation(simple.getResourceLocation()) - .setSize(checkPositive(simple.getSize(), "SimpleResourceLocationIcon#size")) - .build()); + builder.setSimpleResourceLocation(NetworkTypes.toProtobuf((SimpleResourceLocationIcon) icon)); } else if (icon instanceof AdvancedResourceLocationIcon) { - AdvancedResourceLocationIcon advanced = (AdvancedResourceLocationIcon) icon; - - builder.setAdvancedResourceLocation(com.lunarclient.apollo.common.v1.AdvancedResourceLocationIcon.newBuilder() - .setResourceLocation(advanced.getResourceLocation()) - .setWidth(checkPositive(advanced.getWidth(), "AdvancedResourceLocationIcon#width")) - .setHeight(checkPositive(advanced.getHeight(), "AdvancedResourceLocationIcon#height")) - .setMinU(checkRange(advanced.getMinU(), 0, 1, "AdvancedResourceLocationIcon#minU")) - .setMaxU(checkRange(advanced.getMaxU(), 0, 1, "AdvancedResourceLocationIcon#maxU")) - .setMinV(checkRange(advanced.getMinV(), 0, 1, "AdvancedResourceLocationIcon#minV")) - .setMaxV(checkRange(advanced.getMaxV(), 0, 1, "AdvancedResourceLocationIcon#maxV")) - .build()); + builder.setAdvancedResourceLocation(NetworkTypes.toProtobuf((AdvancedResourceLocationIcon) icon)); + } else { + throw new IllegalArgumentException("Unknown icon type: " + icon.getClass().getName()); } return builder.build(); @@ -530,35 +509,150 @@ public static com.lunarclient.apollo.common.v1.Icon toProtobuf(Icon icon) { */ public static Icon fromProtobuf(com.lunarclient.apollo.common.v1.Icon icon) { if (icon.hasItemStack()) { - com.lunarclient.apollo.common.v1.ItemStackIcon item = icon.getItemStack(); - - return ItemStackIcon.builder() - .itemName(item.getItemName()) - .itemId(item.getItemId()) - .customModelData(item.getCustomModelData()) - .build(); + return NetworkTypes.fromProtobuf(icon.getItemStack()); + } else if (icon.hasResourceLocation()) { + return NetworkTypes.fromProtobuf(icon.getResourceLocation()); } else if (icon.hasSimpleResourceLocation()) { - com.lunarclient.apollo.common.v1.SimpleResourceLocationIcon simple = icon.getSimpleResourceLocation(); - - return SimpleResourceLocationIcon.builder() - .resourceLocation(simple.getResourceLocation()) - .size(simple.getSize()) - .build(); + return NetworkTypes.fromProtobuf(icon.getSimpleResourceLocation()); } else if (icon.hasAdvancedResourceLocation()) { - com.lunarclient.apollo.common.v1.AdvancedResourceLocationIcon advanced = icon.getAdvancedResourceLocation(); - - return AdvancedResourceLocationIcon.builder() - .resourceLocation(advanced.getResourceLocation()) - .width(advanced.getWidth()) - .height(advanced.getHeight()) - .minU(advanced.getMinU()) - .maxU(advanced.getMaxU()) - .minV(advanced.getMinV()) - .maxV(advanced.getMaxV()) - .build(); + return NetworkTypes.fromProtobuf(icon.getAdvancedResourceLocation()); } - return null; + throw new IllegalArgumentException("Unknown icon proto type"); + } + + /** + * Converts an {@link ItemStackIcon} to a + * {@link com.lunarclient.apollo.common.v1.ItemStackIcon} proto message. + * + * @param icon the item stack icon + * @return the proto item stack icon message + * @since 1.2.5 + */ + public static com.lunarclient.apollo.common.v1.ItemStackIcon toProtobuf(ItemStackIcon icon) { + com.lunarclient.apollo.common.v1.ItemStackIcon.Builder builder = com.lunarclient.apollo.common.v1.ItemStackIcon.newBuilder() + .setItemId(icon.getItemId()) + .setCustomModelData(icon.getCustomModelData()); + + if (icon.getItemName() != null) { + builder.setItemName(icon.getItemName()); + } + + return builder.build(); + } + + /** + * Converts a {@link com.lunarclient.apollo.common.v1.ItemStackIcon} + * proto message to an {@link ItemStackIcon}. + * + * @param icon the item stack icon message + * @return the item stack icon + * @since 1.2.5 + */ + public static ItemStackIcon fromProtobuf(com.lunarclient.apollo.common.v1.ItemStackIcon icon) { + return ItemStackIcon.builder() + .itemName(icon.getItemName()) + .itemId(icon.getItemId()) + .customModelData(icon.getCustomModelData()) + .build(); + } + + /** + * Converts a {@link ResourceLocationIcon} to a + * {@link com.lunarclient.apollo.common.v1.ResourceLocationIcon} proto message. + * + * @param icon the resource location icon + * @return the proto resource location icon message + * @since 1.2.5 + */ + public static com.lunarclient.apollo.common.v1.ResourceLocationIcon toProtobuf(ResourceLocationIcon icon) { + return com.lunarclient.apollo.common.v1.ResourceLocationIcon.newBuilder() + .setResourceLocation(icon.getResourceLocation()) + .build(); + } + + /** + * Converts a {@link com.lunarclient.apollo.common.v1.ResourceLocationIcon} + * proto message to a {@link ResourceLocationIcon}. + * + * @param icon the resource location icon message + * @return the resource location icon + * @since 1.2.5 + */ + public static ResourceLocationIcon fromProtobuf(com.lunarclient.apollo.common.v1.ResourceLocationIcon icon) { + return ResourceLocationIcon.builder() + .resourceLocation(icon.getResourceLocation()) + .build(); + } + + /** + * Converts a {@link SimpleResourceLocationIcon} to a + * {@link com.lunarclient.apollo.common.v1.SimpleResourceLocationIcon} proto message. + * + * @param icon the simple resource location icon + * @return the proto simple resource location icon message + * @since 1.2.5 + */ + public static com.lunarclient.apollo.common.v1.SimpleResourceLocationIcon toProtobuf(SimpleResourceLocationIcon icon) { + return com.lunarclient.apollo.common.v1.SimpleResourceLocationIcon.newBuilder() + .setResourceLocation(icon.getResourceLocation()) + .setSize(checkPositive(icon.getSize(), "SimpleResourceLocationIcon#size")) + .build(); + } + + /** + * Converts a {@link com.lunarclient.apollo.common.v1.SimpleResourceLocationIcon} + * proto message to a {@link SimpleResourceLocationIcon}. + * + * @param icon the simple resource location icon message + * @return the simple resource location icon + * @since 1.2.5 + */ + public static SimpleResourceLocationIcon fromProtobuf(com.lunarclient.apollo.common.v1.SimpleResourceLocationIcon icon) { + return SimpleResourceLocationIcon.builder() + .resourceLocation(icon.getResourceLocation()) + .size(icon.getSize()) + .build(); + } + + /** + * Converts an {@link AdvancedResourceLocationIcon} to an + * {@link com.lunarclient.apollo.common.v1.AdvancedResourceLocationIcon} proto message. + * + * @param icon the advanced resource location icon + * @return the proto advanced resource location icon message + * @since 1.2.5 + */ + public static com.lunarclient.apollo.common.v1.AdvancedResourceLocationIcon toProtobuf(AdvancedResourceLocationIcon icon) { + return com.lunarclient.apollo.common.v1.AdvancedResourceLocationIcon.newBuilder() + .setResourceLocation(icon.getResourceLocation()) + .setWidth(checkPositive(icon.getWidth(), "AdvancedResourceLocationIcon#width")) + .setHeight(checkPositive(icon.getHeight(), "AdvancedResourceLocationIcon#height")) + .setMinU(checkRange(icon.getMinU(), 0, 1, "AdvancedResourceLocationIcon#minU")) + .setMaxU(checkRange(icon.getMaxU(), 0, 1, "AdvancedResourceLocationIcon#maxU")) + .setMinV(checkRange(icon.getMinV(), 0, 1, "AdvancedResourceLocationIcon#minV")) + .setMaxV(checkRange(icon.getMaxV(), 0, 1, "AdvancedResourceLocationIcon#maxV")) + .build(); + } + + /** + * Converts an {@link com.lunarclient.apollo.common.v1.AdvancedResourceLocationIcon} + * proto message to an {@link AdvancedResourceLocationIcon}. + * + * @param icon the advanced resource location icon message + * @return the advanced resource location icon + * @since 1.2.5 + */ + public static AdvancedResourceLocationIcon fromProtobuf(com.lunarclient.apollo.common.v1.AdvancedResourceLocationIcon icon) { + return AdvancedResourceLocationIcon.builder() + .resourceLocation(icon.getResourceLocation()) + .width(icon.getWidth()) + .height(icon.getHeight()) + .minU(icon.getMinU()) + .maxU(icon.getMaxU()) + .minV(icon.getMinV()) + .maxV(icon.getMaxV()) + .build(); } private NetworkTypes() { diff --git a/docs/developers/lightweight/json/object-util.mdx b/docs/developers/lightweight/json/object-util.mdx index 1a79ade80..de62365e5 100644 --- a/docs/developers/lightweight/json/object-util.mdx +++ b/docs/developers/lightweight/json/object-util.mdx @@ -99,6 +99,16 @@ public static JsonObject createItemStackIconObject(@Nullable String itemName, in return iconObject; } +public static JsonObject createResourceLocationIconObject(@NotNull String resourceLocation) { + JsonObject resourceIconObject = new JsonObject(); + resourceIconObject.addProperty("resource_location", resourceLocation); + + JsonObject iconObject = new JsonObject(); + iconObject.add("resource_location", resourceIconObject); + + return iconObject; +} + public static JsonObject createSimpleResourceLocationIconObject(@NotNull String resourceLocation, int size) { JsonObject simpleIconObject = new JsonObject(); simpleIconObject.addProperty("resource_location", resourceLocation); diff --git a/docs/developers/lightweight/protobuf/getting-started.mdx b/docs/developers/lightweight/protobuf/getting-started.mdx index 467c0db9e..b3ce05011 100644 --- a/docs/developers/lightweight/protobuf/getting-started.mdx +++ b/docs/developers/lightweight/protobuf/getting-started.mdx @@ -26,7 +26,7 @@ Available fields for each message, including their types, are available on the B com.lunarclient apollo-protos - 0.0.6 + 0.0.8 ``` @@ -41,7 +41,7 @@ Available fields for each message, including their types, are available on the B } dependencies { - api 'com.lunarclient:apollo-protos:0.0.6' + api 'com.lunarclient:apollo-protos:0.0.8' } ``` @@ -55,7 +55,7 @@ Available fields for each message, including their types, are available on the B } dependencies { - api("com.lunarclient:apollo-protos:0.0.6") + api("com.lunarclient:apollo-protos:0.0.8") } ``` diff --git a/docs/developers/lightweight/protobuf/object-util.mdx b/docs/developers/lightweight/protobuf/object-util.mdx index b4111e5bf..bff0bbdeb 100644 --- a/docs/developers/lightweight/protobuf/object-util.mdx +++ b/docs/developers/lightweight/protobuf/object-util.mdx @@ -97,7 +97,7 @@ public static Location toBukkitPlayerLocation(JsonObject message) { Icon-related methods ```java -public static Icon createItemStackIconProto(@Nullable String itemName, int itemId, int customModelData) { +public static ItemStackIcon createItemStackIconProto(@Nullable String itemName, int itemId, int customModelData) { ItemStackIcon.Builder iconBuilder = ItemStackIcon.newBuilder() .setItemId(itemId) .setCustomModelData(customModelData); @@ -106,21 +106,25 @@ public static Icon createItemStackIconProto(@Nullable String itemName, int itemI iconBuilder.setItemName(itemName); } - return Icon.newBuilder().setItemStack(iconBuilder.build()).build(); + return iconBuilder.build(); } -public static Icon createSimpleResourceLocationIconProto(String resourceLocation, int size) { - SimpleResourceLocationIcon icon = SimpleResourceLocationIcon.newBuilder() +public static ResourceLocationIcon createResourceLocationIconProto(String resourceLocation) { + return ResourceLocationIcon.newBuilder() .setResourceLocation(resourceLocation) - .setSize(size) .build(); +} - return Icon.newBuilder().setSimpleResourceLocation(icon).build(); +public static SimpleResourceLocationIcon createSimpleResourceLocationIconProto(String resourceLocation, int size) { + return SimpleResourceLocationIcon.newBuilder() + .setResourceLocation(resourceLocation) + .setSize(size) + .build(); } -public static Icon createAdvancedResourceLocationIconProto(String resourceLocation, float width, float height, +public static AdvancedResourceLocationIcon createAdvancedResourceLocationIconProto(String resourceLocation, float width, float height, float minU, float maxU, float minV, float maxV) { - AdvancedResourceLocationIcon icon = AdvancedResourceLocationIcon.newBuilder() + return AdvancedResourceLocationIcon.newBuilder() .setResourceLocation(resourceLocation) .setWidth(width) .setHeight(height) @@ -129,7 +133,5 @@ public static Icon createAdvancedResourceLocationIconProto(String resourceLocati .setMinV(minV) .setMaxV(maxV) .build(); - - return Icon.newBuilder().setAdvancedResourceLocation(icon).build(); } ``` diff --git a/docs/developers/modules/_meta.json b/docs/developers/modules/_meta.json index 02faf06d0..1f3fba9c1 100644 --- a/docs/developers/modules/_meta.json +++ b/docs/developers/modules/_meta.json @@ -20,6 +20,7 @@ "packetenrichment": "Packet Enrichment", "richpresence": "Rich Presence", "saturation": "Saturation", + "serverlink": "Server Link", "serverrule": "Server Rule", "staffmod": "Staff Mod", "stopwatch": "Stopwatch", diff --git a/docs/developers/modules/cooldown.mdx b/docs/developers/modules/cooldown.mdx index 4264a826b..d04c75f97 100644 --- a/docs/developers/modules/cooldown.mdx +++ b/docs/developers/modules/cooldown.mdx @@ -121,7 +121,9 @@ public void displayCooldownItemExample(Player viewer) { DisplayCooldownMessage message = DisplayCooldownMessage.newBuilder() .setName("enderpearl-cooldown") .setDuration(ProtobufUtil.createDurationProto(Duration.ofSeconds(15))) - .setIcon(ProtobufUtil.createItemStackIconProto("ENDER_PEARL", 0, 0)) + .setIcon(Icon.newBuilder() + .setItemStack(ProtobufUtil.createItemStackIconProto("ENDER_PEARL", 0, 0)) + .build()) .build(); ProtobufPacketUtil.sendPacket(viewer, message); @@ -135,7 +137,9 @@ public void displayCooldownResourceExample(Player viewer) { DisplayCooldownMessage message = DisplayCooldownMessage.newBuilder() .setName("lunar-cooldown") .setDuration(ProtobufUtil.createDurationProto(Duration.ofSeconds(15))) - .setIcon(ProtobufUtil.createSimpleResourceLocationIconProto("lunar:logo/logo-200x182.svg", 12)) + .setIcon(Icon.newBuilder() + .setSimpleResourceLocation(ProtobufUtil.createSimpleResourceLocationIconProto("lunar:logo/logo-200x182.svg", 12)) + .build()) .build(); ProtobufPacketUtil.sendPacket(viewer, message); diff --git a/docs/developers/modules/hologram.mdx b/docs/developers/modules/hologram.mdx index 5cc882065..db5ab913e 100644 --- a/docs/developers/modules/hologram.mdx +++ b/docs/developers/modules/hologram.mdx @@ -88,7 +88,7 @@ public void resetHologramsExample(Player viewer) { ) ``` -`.lines(Component)` should be a string, or an Adventure `Component`. See the [chat components](https://docs.advntr.dev/text.html) page for more. +`.lines(Component)` is using the Adventure `Component`. See the [chat components](https://docs.advntr.dev/text.html) page for more. ```java .lines(List.of( diff --git a/docs/developers/modules/nametag.mdx b/docs/developers/modules/nametag.mdx index 679cfcf22..5ca13ec02 100644 --- a/docs/developers/modules/nametag.mdx +++ b/docs/developers/modules/nametag.mdx @@ -81,7 +81,7 @@ public void resetNametagsExample(Player viewer) { ### `Nametag` Options -`.lines(Component)` should be a string, or an Adventure `Component`. See the [chat components](https://docs.advntr.dev/text.html) page for more. +`.lines(Component)` is using the Adventure `Component`. See the [chat components](https://docs.advntr.dev/text.html) page for more. ```java .lines(List.of( diff --git a/docs/developers/modules/notification.mdx b/docs/developers/modules/notification.mdx index b88c2b6d3..f9b506b1b 100644 --- a/docs/developers/modules/notification.mdx +++ b/docs/developers/modules/notification.mdx @@ -41,7 +41,7 @@ public void displayNotificationExample(Player viewer) { .append(Component.newline()) .append(Component.text("Good luck!", NamedTextColor.GOLD)) ) - .resourceLocation("icons/golden_apple.png") // This field is optional + .resourceLocation("textures/items/apple_golden.png") // This field is optional .displayTime(Duration.ofSeconds(5)) .build()); }); @@ -78,7 +78,7 @@ public void resetNotificationsExample(Player viewer) { `.resourceLocation(String)` is the resource location of the shown icon. ```java -.resourceLocation("icons/golden_apple.png") +.resourceLocation("textures/items/apple_golden.png") ``` `.displayTime(java.time.Duration)` is the duration you want to keep the notification on screen. See the [java.time.Duration Javadocs](https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html) for more. @@ -125,7 +125,7 @@ public void displayNotificationExample(Player viewer) { .append(Component.text("Good luck!", NamedTextColor.GOLD)) ) ) - .setResourceLocation("icons/golden_apple.png") // This field is optional + .setResourceLocation("textures/items/apple_golden.png") // This field is optional .setDisplayTime(ProtobufUtil.createDurationProto(Duration.ofSeconds(5))) .build(); @@ -164,7 +164,7 @@ public void displayNotificationExample(Player viewer) { )); message.addProperty("display_time", JsonUtil.createDurationObject(Duration.ofSeconds(5))); - message.addProperty("resource_location", "icons/golden_apple.png"); + message.addProperty("resource_location", "textures/items/apple_golden.png"); JsonPacketUtil.sendPacket(viewer, message); } diff --git a/docs/developers/modules/serverlink.mdx b/docs/developers/modules/serverlink.mdx new file mode 100644 index 000000000..96ca563d9 --- /dev/null +++ b/docs/developers/modules/serverlink.mdx @@ -0,0 +1,282 @@ +import { Tab, Tabs } from 'nextra-theme-docs' + +# Server Link Module + +## Overview + +The server link module provides enhancements and additional support to the vanilla Minecraft server link feature. Which allows you to display important links to players in a dedicated UI. + +- Adds improvements to the existing server link features + - Ability to set a custom image title resource for the server links menu + - Ability to use chat colors and formats for button names +- Backported legacy version support for all versions below 1.21 + +![Server Link Module Example](/modules/serverlink/overview.png#center) + +## Integration + +### Sample Code +Explore each integration by cycling through each tab, to find the best fit for your requirements and needs. + + + + + +### Override the Server Link Menu resource + +```java +public void overrideServerLinkResourceExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + + apolloPlayerOpt.ifPresent(apolloPlayer -> { + this.serverLinkModule.overrideServerLinkResource(apolloPlayer, ResourceLocationIcon.builder() + .resourceLocation("lunar:logo/logo-100x100.png") + .build()); + }); +} +``` + +### Reset the Server Link Menu resource + +```java +public void resetServerLinkResourceExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + apolloPlayerOpt.ifPresent(this.serverLinkModule::resetServerLinkResource); +} +``` + +### Add Server Link + +```java +public void addServerLinkExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + + apolloPlayerOpt.ifPresent(apolloPlayer -> { + this.serverLinkModule.addServerLink(apolloPlayer, Lists.newArrayList( + ServerLink.builder() + .id("website") + .displayName(Component.text("Website", NamedTextColor.LIGHT_PURPLE)) + .url("https://www.lunarclient.com/") + .build(), + ServerLink.builder() + .id("support") + .displayName(Component.text("Support", NamedTextColor.AQUA)) + .url("https://support.lunarclient.com/") + .build(), + ServerLink.builder() + .id("status") + .displayName(Component.text("Status", NamedTextColor.RED)) + .url("https://status.lunarclient.com/") + .build() + )); + }); +} +``` + +### Remove Server Link + +```java +public void removeServerLinkExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + + apolloPlayerOpt.ifPresent(apolloPlayer -> { + this.serverLinkModule.removeServerLink(apolloPlayer, Lists.newArrayList( + "website", "support", "status" + )); + }); +} +``` + +### Resetting all Server Links + +```java +public void resetServerLinksExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + apolloPlayerOpt.ifPresent(this.serverLinkModule::resetServerLinks); +} +``` + +### `ServerLink` Options + +`.id(String)` sets a unique identifier for the server link. + +```java +.id("website") +``` + +`.displayName(Component)` is the public-facing name of the server link. It should contain an Adventure `Component`. See the [chat components](https://docs.advntr.dev/text.html) page for more. + +```java +.displayName(Component.text("Website", NamedTextColor.LIGHT_PURPLE)) +``` + +`.url(String)` should be a string that specifies the destination URL that will be opened from the server link. + +```java +.url("https://www.lunarclient.com/") +``` + + + + + + +**Override the Server Link Menu resource** + +```java +public void overrideServerLinkResourceExample(Player viewer) { + OverrideServerLinkResourceMessage message = OverrideServerLinkResourceMessage.newBuilder() + .setIcon(ProtobufUtil.createResourceLocationIconProto("lunar:logo/logo-100x100.png")) + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); +} +``` + +**Reset the Server Link Menu resource** + +```java +public void resetServerLinkResourceExample(Player viewer) { + ResetServerLinkResourceMessage message = ResetServerLinkResourceMessage.getDefaultInstance(); + ProtobufPacketUtil.sendPacket(viewer, message); +} +``` + +**Add Server Link** + +```java +public void addServerLinkExample(Player viewer) { + List serverLinks = Lists.newArrayList( + ServerLink.newBuilder() + .setId("website") + .setDisplayNameAdventureJsonLines(AdventureUtil.toJson( + Component.text("Website", NamedTextColor.LIGHT_PURPLE))) + .setUrl("https://www.lunarclient.com/") + .build(), + ServerLink.newBuilder() + .setId("support") + .setDisplayNameAdventureJsonLines(AdventureUtil.toJson( + Component.text("Support", NamedTextColor.AQUA))) + .setUrl("https://support.lunarclient.com/") + .build(), + ServerLink.newBuilder() + .setId("status") + .setDisplayNameAdventureJsonLines(AdventureUtil.toJson( + Component.text("Status", NamedTextColor.RED))) + .setUrl("https://status.lunarclient.com/") + .build() + ); + + AddServerLinkMessage message = AddServerLinkMessage.newBuilder() + .addAllServerLinks(serverLinks) + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); +} +``` + +**Remove Server Link** + +```java +public void removeServerLinkExample(Player viewer) { + List serverLinkIds = Lists.newArrayList("website", "support", "status"); + + RemoveServerLinkMessage message = RemoveServerLinkMessage.newBuilder() + .addAllServerLinkIds(serverLinkIds) + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); +} +``` + +**Resetting all Server Links** + +```java +public void resetServerLinksExample(Player viewer) { + ResetServerLinksMessage message = ResetServerLinksMessage.getDefaultInstance(); + ProtobufPacketUtil.sendPacket(viewer, message); +} +``` + + + + + +**Override the Server Link Menu resource** + +```java +public void overrideServerLinkResourceExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.serverlink.v1.OverrideServerLinkResourceMessage"); + message.add("icon", JsonUtil.createResourceLocationIconObject("lunar:logo/logo-100x100.png")); + + JsonPacketUtil.sendPacket(viewer, message); +} +``` + +**Reset the Server Link Menu resource** + +```java +public void resetServerLinkResourceExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.serverlink.v1.ResetServerLinkResourceMessage"); + + JsonPacketUtil.sendPacket(viewer, message); +} +``` + +**Add Server Link** + +```java +public void addServerLinkExample(Player viewer) { + JsonArray serverLinks = Lists.newArrayList( + this.createServerLinkObject("website", Component.text("Website", NamedTextColor.LIGHT_PURPLE), "https://www.lunarclient.com/"), + this.createServerLinkObject("support", Component.text("Support", NamedTextColor.AQUA), "https://support.lunarclient.com/"), + this.createServerLinkObject("status", Component.text("Status", NamedTextColor.RED), "https://status.lunarclient.com/") + ).stream().collect(JsonArray::new, JsonArray::add, JsonArray::addAll); + + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.serverlink.v1.AddServerLinkMessage"); + message.add("server_links", serverLinks); + + JsonPacketUtil.sendPacket(viewer, message); +} + +private JsonObject createServerLinkObject(String id, Component displayName, String url) { + JsonObject serverLinkObject = new JsonObject(); + serverLinkObject.addProperty("id", id); + serverLinkObject.addProperty("display_name_adventure_json_lines", AdventureUtil.toJson(displayName)); + serverLinkObject.addProperty("url", url); + return serverLinkObject; +} +``` + +**Remove Server Link** + +```java +public void removeServerLinkExample(Player viewer) { + JsonArray serverLinkIds = Lists.newArrayList("website", "support", "status") + .stream().collect(JsonArray::new, JsonArray::add, JsonArray::addAll); + + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.serverlink.v1.RemoveServerLinkMessage"); + message.add("server_link_ids", serverLinkIds); + + JsonPacketUtil.sendPacket(viewer, message); +} +``` + +**Resetting all Server Links** + +```java +public void resetServerLinksExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.serverlink.v1.ResetServerLinksMessage"); + + JsonPacketUtil.sendPacket(viewer, message); +} +``` + + + + diff --git a/docs/developers/utilities/icons.mdx b/docs/developers/utilities/icons.mdx index 4c01099f9..449151b7c 100644 --- a/docs/developers/utilities/icons.mdx +++ b/docs/developers/utilities/icons.mdx @@ -61,6 +61,40 @@ public static ItemStackIcon itemStackNameIconExample() { } ``` +## `ResourceLocationIcon` Builder + +If you're using a custom resource pack and want to create an icon, you can use the `ResourceLocationIcon` builder. + + + The supplied resource location should point to a texture in the resource pack, or the path to an `svg` file in the resource pack. + + +```java +public class ResourceLocationIcon extends Icon { + + /** + * Returns the icon {@link String} resource location. + * + *

Represents a path to an icon that will appear for the player.

+ * + * @return the icon resource location + * @since 1.2.5 + */ + String resourceLocation; + +} +``` + +### Sample Code + +```java +public static ResourceLocationIcon resourceLocationExample() { + return ResourceLocationIcon.builder() + .resourceLocation("minecraft:textures/item/apple.png") // Resource path location + .build(); +} +``` + ## `SimpleResourceLocation` Builder If you're using a custom resource pack and want to create an icon, you can use the `SimpleResourceLocation` builder. diff --git a/docs/public/modules/serverlink/overview.png b/docs/public/modules/serverlink/overview.png new file mode 100644 index 000000000..512543fef Binary files /dev/null and b/docs/public/modules/serverlink/overview.png differ diff --git a/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/ApolloApiExamplePlatform.java b/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/ApolloApiExamplePlatform.java index 6fc763dcf..8575bc784 100644 --- a/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/ApolloApiExamplePlatform.java +++ b/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/ApolloApiExamplePlatform.java @@ -47,6 +47,7 @@ import com.lunarclient.apollo.example.api.module.NotificationApiExample; import com.lunarclient.apollo.example.api.module.PayNowApiExample; import com.lunarclient.apollo.example.api.module.RichPresenceApiExample; +import com.lunarclient.apollo.example.api.module.ServerLinkApiExample; import com.lunarclient.apollo.example.api.module.ServerRuleApiExample; import com.lunarclient.apollo.example.api.module.StaffModApiExample; import com.lunarclient.apollo.example.api.module.StopwatchApiExample; @@ -97,6 +98,7 @@ public void registerModuleExamples() { this.setNotificationExample(new NotificationApiExample()); this.setPayNowExample(new PayNowApiExample()); this.setRichPresenceExample(new RichPresenceApiExample()); + this.setServerLinkExample(new ServerLinkApiExample()); this.setServerRuleExample(new ServerRuleApiExample()); this.setStaffModExample(new StaffModApiExample()); this.setStopwatchExample(new StopwatchApiExample()); diff --git a/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/listener/ApolloPlayerApiListener.java b/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/listener/ApolloPlayerApiListener.java index 837b525d4..3f1dc22e3 100644 --- a/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/listener/ApolloPlayerApiListener.java +++ b/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/listener/ApolloPlayerApiListener.java @@ -29,6 +29,7 @@ import com.lunarclient.apollo.event.player.ApolloRegisterPlayerEvent; import com.lunarclient.apollo.example.ApolloExamplePlugin; import com.lunarclient.apollo.example.api.module.TeamApiExample; +import com.lunarclient.apollo.example.module.impl.ServerLinkExample; import com.lunarclient.apollo.player.ApolloPlayer; import org.bukkit.entity.Player; @@ -61,6 +62,10 @@ private void onApolloRegister(ApolloRegisterPlayerEvent event) { this.example.getCooldownExample().displayCooldownItemExample(player); this.example.getNametagExample().overrideNametagExample(player); this.example.getWaypointExample().displayWaypointExample(player); + + ServerLinkExample serverLinkExample = this.example.getServerLinkExample(); + serverLinkExample.overrideServerLinkResourceExample(player); + serverLinkExample.addServerLinkExample(player); } } diff --git a/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/module/NotificationApiExample.java b/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/module/NotificationApiExample.java index 528953801..512074740 100644 --- a/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/module/NotificationApiExample.java +++ b/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/module/NotificationApiExample.java @@ -51,7 +51,7 @@ public void displayNotificationExample(Player viewer) { .append(Component.newline()) .append(Component.text("Good luck!", NamedTextColor.GOLD)) ) - .resourceLocation("icons/golden_apple.png") // This field is optional + .resourceLocation("textures/items/apple_golden.png") // This field is optional .displayTime(Duration.ofSeconds(5)) .build()); }); diff --git a/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/module/ServerLinkApiExample.java b/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/module/ServerLinkApiExample.java new file mode 100644 index 000000000..8c8f9e44c --- /dev/null +++ b/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/module/ServerLinkApiExample.java @@ -0,0 +1,101 @@ +/* + * 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.example.api.module; + +import com.google.common.collect.Lists; +import com.lunarclient.apollo.Apollo; +import com.lunarclient.apollo.common.icon.ResourceLocationIcon; +import com.lunarclient.apollo.example.module.impl.ServerLinkExample; +import com.lunarclient.apollo.module.serverlink.ServerLink; +import com.lunarclient.apollo.module.serverlink.ServerLinkModule; +import com.lunarclient.apollo.player.ApolloPlayer; +import java.util.Optional; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.entity.Player; + +public class ServerLinkApiExample extends ServerLinkExample { + + private final ServerLinkModule serverLinkModule = Apollo.getModuleManager().getModule(ServerLinkModule.class); + + @Override + public void overrideServerLinkResourceExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + + apolloPlayerOpt.ifPresent(apolloPlayer -> { + this.serverLinkModule.overrideServerLinkResource(apolloPlayer, ResourceLocationIcon.builder() + .resourceLocation("lunar:logo/logo-100x100.png") + .build()); + }); + } + + @Override + public void resetServerLinkResourceExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + apolloPlayerOpt.ifPresent(this.serverLinkModule::resetServerLinkResource); + } + + @Override + public void addServerLinkExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + + apolloPlayerOpt.ifPresent(apolloPlayer -> { + this.serverLinkModule.addServerLink(apolloPlayer, Lists.newArrayList( + ServerLink.builder() + .id("website") + .displayName(Component.text("Website", NamedTextColor.LIGHT_PURPLE)) + .url("https://www.lunarclient.com/") + .build(), + ServerLink.builder() + .id("support") + .displayName(Component.text("Support", NamedTextColor.AQUA)) + .url("https://support.lunarclient.com/") + .build(), + ServerLink.builder() + .id("status") + .displayName(Component.text("Status", NamedTextColor.RED)) + .url("https://status.lunarclient.com/") + .build() + )); + }); + } + + @Override + public void removeServerLinkExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + + apolloPlayerOpt.ifPresent(apolloPlayer -> { + this.serverLinkModule.removeServerLink(apolloPlayer, Lists.newArrayList( + "website", "support", "status" + )); + }); + } + + @Override + public void resetServerLinksExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + apolloPlayerOpt.ifPresent(this.serverLinkModule::resetServerLinks); + } + +} diff --git a/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/util/IconExample.java b/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/util/IconExample.java index ebd6f896a..426b63d1f 100644 --- a/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/util/IconExample.java +++ b/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/util/IconExample.java @@ -25,6 +25,7 @@ import com.lunarclient.apollo.common.icon.AdvancedResourceLocationIcon; import com.lunarclient.apollo.common.icon.ItemStackIcon; +import com.lunarclient.apollo.common.icon.ResourceLocationIcon; import com.lunarclient.apollo.common.icon.SimpleResourceLocationIcon; import org.bukkit.Material; @@ -42,6 +43,12 @@ public static ItemStackIcon itemStackNameIconExample() { .build(); } + public static ResourceLocationIcon resourceLocationExample() { + return ResourceLocationIcon.builder() + .resourceLocation("minecraft:textures/item/apple.png") // Resource path location + .build(); + } + public static SimpleResourceLocationIcon simpleResourceLocationIconExample() { return SimpleResourceLocationIcon.builder() .resourceLocation("icons/server-logo.png") // Resource path location diff --git a/example/bukkit/api/src/main/resources/plugin.yml b/example/bukkit/api/src/main/resources/plugin.yml index fbe960bbe..042f5363f 100644 --- a/example/bukkit/api/src/main/resources/plugin.yml +++ b/example/bukkit/api/src/main/resources/plugin.yml @@ -49,6 +49,8 @@ commands: description: "Pay Now!" richpresence: description: "Rich Presence!" + serverlink: + description: "Server Links!" saturation: description: "Saturation!" serverrule: diff --git a/example/bukkit/common/src/main/java/com/lunarclient/apollo/example/ApolloExamplePlugin.java b/example/bukkit/common/src/main/java/com/lunarclient/apollo/example/ApolloExamplePlugin.java index f69da42ef..81d28966a 100644 --- a/example/bukkit/common/src/main/java/com/lunarclient/apollo/example/ApolloExamplePlugin.java +++ b/example/bukkit/common/src/main/java/com/lunarclient/apollo/example/ApolloExamplePlugin.java @@ -43,6 +43,7 @@ import com.lunarclient.apollo.example.command.PayNowCommand; import com.lunarclient.apollo.example.command.RichPresenceCommand; import com.lunarclient.apollo.example.command.SaturationCommand; +import com.lunarclient.apollo.example.command.ServerLinkCommand; import com.lunarclient.apollo.example.command.ServerRuleCommand; import com.lunarclient.apollo.example.command.StaffModCommand; import com.lunarclient.apollo.example.command.StopwatchCommand; @@ -73,6 +74,7 @@ import com.lunarclient.apollo.example.module.impl.PayNowExample; import com.lunarclient.apollo.example.module.impl.RichPresenceExample; import com.lunarclient.apollo.example.module.impl.SaturationExample; +import com.lunarclient.apollo.example.module.impl.ServerLinkExample; import com.lunarclient.apollo.example.module.impl.ServerRuleExample; import com.lunarclient.apollo.example.module.impl.StaffModExample; import com.lunarclient.apollo.example.module.impl.StopwatchExample; @@ -112,6 +114,7 @@ public abstract class ApolloExamplePlugin extends JavaPlugin { private NotificationExample notificationExample; private PayNowExample payNowExample; private RichPresenceExample richPresenceExample; + private ServerLinkExample serverLinkExample; private SaturationExample saturationExample; private ServerRuleExample serverRuleExample; private StaffModExample staffModExample; @@ -163,6 +166,7 @@ private void registerCommonCommands() { this.getCommand("paynow").setExecutor(new PayNowCommand()); this.getCommand("richpresence").setExecutor(new RichPresenceCommand()); this.getCommand("saturation").setExecutor(new SaturationCommand()); + this.getCommand("serverlink").setExecutor(new ServerLinkCommand()); this.getCommand("serverrule").setExecutor(new ServerRuleCommand()); this.getCommand("staffmod").setExecutor(new StaffModCommand()); this.getCommand("stopwatch").setExecutor(new StopwatchCommand()); diff --git a/example/bukkit/common/src/main/java/com/lunarclient/apollo/example/command/ServerLinkCommand.java b/example/bukkit/common/src/main/java/com/lunarclient/apollo/example/command/ServerLinkCommand.java new file mode 100644 index 000000000..d52802288 --- /dev/null +++ b/example/bukkit/common/src/main/java/com/lunarclient/apollo/example/command/ServerLinkCommand.java @@ -0,0 +1,91 @@ +/* + * 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.example.command; + +import com.lunarclient.apollo.example.ApolloExamplePlugin; +import com.lunarclient.apollo.example.module.impl.ServerLinkExample; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +public class ServerLinkCommand implements CommandExecutor { + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage("Player only!"); + return true; + } + + Player player = (Player) sender; + + if (args.length != 1) { + player.sendMessage("Usage: /serverlink "); + return true; + } + + ServerLinkExample serverLinkExample = ApolloExamplePlugin.getInstance().getServerLinkExample(); + + switch (args[0].toLowerCase()) { + case "overrideresource": { + serverLinkExample.overrideServerLinkResourceExample(player); + player.sendMessage("Overriding server link resource..."); + break; + } + + case "resetresource": { + serverLinkExample.resetServerLinkResourceExample(player); + player.sendMessage("Resetting server link resource..."); + break; + } + + case "addserverlink": { + serverLinkExample.addServerLinkExample(player); + player.sendMessage("Adding server link..."); + break; + } + + case "removeserverlink": { + serverLinkExample.removeServerLinkExample(player); + player.sendMessage("Removing server link..."); + break; + } + + case "resetserverlinks": { + serverLinkExample.resetServerLinksExample(player); + player.sendMessage("Resetting server links..."); + break; + } + + default: { + player.sendMessage("Usage: /serverlink "); + break; + } + } + + return true; + } +} diff --git a/example/bukkit/common/src/main/java/com/lunarclient/apollo/example/module/impl/ServerLinkExample.java b/example/bukkit/common/src/main/java/com/lunarclient/apollo/example/module/impl/ServerLinkExample.java new file mode 100644 index 000000000..26ad56fba --- /dev/null +++ b/example/bukkit/common/src/main/java/com/lunarclient/apollo/example/module/impl/ServerLinkExample.java @@ -0,0 +1,41 @@ +/* + * 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.example.module.impl; + +import com.lunarclient.apollo.example.module.ApolloModuleExample; +import org.bukkit.entity.Player; + +public abstract class ServerLinkExample extends ApolloModuleExample { + + public abstract void overrideServerLinkResourceExample(Player viewer); + + public abstract void resetServerLinkResourceExample(Player viewer); + + public abstract void addServerLinkExample(Player viewer); + + public abstract void removeServerLinkExample(Player viewer); + + public abstract void resetServerLinksExample(Player viewer); + +} diff --git a/example/bukkit/json/src/main/java/com/lunarclient/apollo/example/json/ApolloJsonExamplePlatform.java b/example/bukkit/json/src/main/java/com/lunarclient/apollo/example/json/ApolloJsonExamplePlatform.java index 6ca73781a..196b6f81a 100644 --- a/example/bukkit/json/src/main/java/com/lunarclient/apollo/example/json/ApolloJsonExamplePlatform.java +++ b/example/bukkit/json/src/main/java/com/lunarclient/apollo/example/json/ApolloJsonExamplePlatform.java @@ -43,6 +43,7 @@ import com.lunarclient.apollo.example.json.module.NotificationJsonExample; import com.lunarclient.apollo.example.json.module.PayNowJsonExample; import com.lunarclient.apollo.example.json.module.RichPresenceJsonExample; +import com.lunarclient.apollo.example.json.module.ServerLinkJsonExample; import com.lunarclient.apollo.example.json.module.ServerRuleJsonExample; import com.lunarclient.apollo.example.json.module.StaffModJsonExample; import com.lunarclient.apollo.example.json.module.StopwatchJsonExample; @@ -85,6 +86,7 @@ public void registerModuleExamples() { this.setNotificationExample(new NotificationJsonExample()); this.setPayNowExample(new PayNowJsonExample()); this.setRichPresenceExample(new RichPresenceJsonExample()); + this.setServerLinkExample(new ServerLinkJsonExample()); this.setServerRuleExample(new ServerRuleJsonExample()); this.setStaffModExample(new StaffModJsonExample()); this.setStopwatchExample(new StopwatchJsonExample()); diff --git a/example/bukkit/json/src/main/java/com/lunarclient/apollo/example/json/module/NotificationJsonExample.java b/example/bukkit/json/src/main/java/com/lunarclient/apollo/example/json/module/NotificationJsonExample.java index c8f92e4a2..70c4b1bdc 100644 --- a/example/bukkit/json/src/main/java/com/lunarclient/apollo/example/json/module/NotificationJsonExample.java +++ b/example/bukkit/json/src/main/java/com/lunarclient/apollo/example/json/module/NotificationJsonExample.java @@ -51,7 +51,7 @@ public void displayNotificationExample(Player viewer) { )); message.addProperty("display_time", JsonUtil.createDurationObject(Duration.ofSeconds(5))); - message.addProperty("resource_location", "icons/golden_apple.png"); + message.addProperty("resource_location", "textures/items/apple_golden.png"); JsonPacketUtil.sendPacket(viewer, message); } diff --git a/example/bukkit/json/src/main/java/com/lunarclient/apollo/example/json/module/ServerLinkJsonExample.java b/example/bukkit/json/src/main/java/com/lunarclient/apollo/example/json/module/ServerLinkJsonExample.java new file mode 100644 index 000000000..6cd6f7cd4 --- /dev/null +++ b/example/bukkit/json/src/main/java/com/lunarclient/apollo/example/json/module/ServerLinkJsonExample.java @@ -0,0 +1,99 @@ +/* + * 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.example.json.module; + +import com.google.common.collect.Lists; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.lunarclient.apollo.example.json.util.AdventureUtil; +import com.lunarclient.apollo.example.json.util.JsonPacketUtil; +import com.lunarclient.apollo.example.json.util.JsonUtil; +import com.lunarclient.apollo.example.module.impl.ServerLinkExample; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.entity.Player; + +public class ServerLinkJsonExample extends ServerLinkExample { + + @Override + public void overrideServerLinkResourceExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.serverlink.v1.OverrideServerLinkResourceMessage"); + message.add("icon", JsonUtil.createResourceLocationIconObject("lunar:logo/logo-100x100.png")); + + JsonPacketUtil.sendPacket(viewer, message); + } + + @Override + public void resetServerLinkResourceExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.serverlink.v1.ResetServerLinkResourceMessage"); + + JsonPacketUtil.sendPacket(viewer, message); + } + + @Override + public void addServerLinkExample(Player viewer) { + JsonArray serverLinks = Lists.newArrayList( + this.createServerLinkObject("website", Component.text("Website", NamedTextColor.LIGHT_PURPLE), "https://www.lunarclient.com/"), + this.createServerLinkObject("support", Component.text("Support", NamedTextColor.AQUA), "https://support.lunarclient.com/"), + this.createServerLinkObject("status", Component.text("Status", NamedTextColor.RED), "https://status.lunarclient.com/") + ).stream().collect(JsonArray::new, JsonArray::add, JsonArray::addAll); + + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.serverlink.v1.AddServerLinkMessage"); + message.add("server_links", serverLinks); + + JsonPacketUtil.sendPacket(viewer, message); + } + + private JsonObject createServerLinkObject(String id, Component displayName, String url) { + JsonObject serverLinkObject = new JsonObject(); + serverLinkObject.addProperty("id", id); + serverLinkObject.addProperty("display_name_adventure_json_lines", AdventureUtil.toJson(displayName)); + serverLinkObject.addProperty("url", url); + return serverLinkObject; + } + + @Override + public void removeServerLinkExample(Player viewer) { + JsonArray serverLinkIds = Lists.newArrayList("website", "support", "status") + .stream().collect(JsonArray::new, JsonArray::add, JsonArray::addAll); + + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.serverlink.v1.RemoveServerLinkMessage"); + message.add("server_link_ids", serverLinkIds); + + JsonPacketUtil.sendPacket(viewer, message); + } + + @Override + public void resetServerLinksExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.serverlink.v1.ResetServerLinksMessage"); + + JsonPacketUtil.sendPacket(viewer, message); + } + +} diff --git a/example/bukkit/json/src/main/java/com/lunarclient/apollo/example/json/util/JsonUtil.java b/example/bukkit/json/src/main/java/com/lunarclient/apollo/example/json/util/JsonUtil.java index dce4fdf0d..841a96943 100644 --- a/example/bukkit/json/src/main/java/com/lunarclient/apollo/example/json/util/JsonUtil.java +++ b/example/bukkit/json/src/main/java/com/lunarclient/apollo/example/json/util/JsonUtil.java @@ -150,6 +150,16 @@ public static JsonObject createItemStackIconObject(@Nullable String itemName, in return iconObject; } + public static JsonObject createResourceLocationIconObject(@NotNull String resourceLocation) { + JsonObject resourceIconObject = new JsonObject(); + resourceIconObject.addProperty("resource_location", resourceLocation); + + JsonObject iconObject = new JsonObject(); + iconObject.add("resource_location", resourceIconObject); + + return iconObject; + } + public static JsonObject createSimpleResourceLocationIconObject(@NotNull String resourceLocation, int size) { JsonObject simpleIconObject = new JsonObject(); simpleIconObject.addProperty("resource_location", resourceLocation); diff --git a/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/ApolloProtoExamplePlatform.java b/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/ApolloProtoExamplePlatform.java index 57c5a1930..f02c1bfd3 100644 --- a/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/ApolloProtoExamplePlatform.java +++ b/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/ApolloProtoExamplePlatform.java @@ -43,6 +43,7 @@ import com.lunarclient.apollo.example.proto.module.NotificationProtoExample; import com.lunarclient.apollo.example.proto.module.PayNowProtoExample; import com.lunarclient.apollo.example.proto.module.RichPresenceProtoExample; +import com.lunarclient.apollo.example.proto.module.ServerLinkProtoExample; import com.lunarclient.apollo.example.proto.module.ServerRuleProtoExample; import com.lunarclient.apollo.example.proto.module.StaffModProtoExample; import com.lunarclient.apollo.example.proto.module.StopwatchProtoExample; @@ -85,6 +86,7 @@ public void registerModuleExamples() { this.setNotificationExample(new NotificationProtoExample()); this.setPayNowExample(new PayNowProtoExample()); this.setRichPresenceExample(new RichPresenceProtoExample()); + this.setServerLinkExample(new ServerLinkProtoExample()); this.setServerRuleExample(new ServerRuleProtoExample()); this.setStaffModExample(new StaffModProtoExample()); this.setStopwatchExample(new StopwatchProtoExample()); diff --git a/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/module/CooldownProtoExample.java b/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/module/CooldownProtoExample.java index d8c6741ca..cd515b09b 100644 --- a/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/module/CooldownProtoExample.java +++ b/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/module/CooldownProtoExample.java @@ -23,6 +23,7 @@ */ package com.lunarclient.apollo.example.proto.module; +import com.lunarclient.apollo.common.v1.Icon; import com.lunarclient.apollo.cooldown.v1.DisplayCooldownMessage; import com.lunarclient.apollo.cooldown.v1.RemoveCooldownMessage; import com.lunarclient.apollo.cooldown.v1.ResetCooldownsMessage; @@ -39,7 +40,9 @@ public void displayCooldownItemExample(Player viewer) { DisplayCooldownMessage message = DisplayCooldownMessage.newBuilder() .setName("enderpearl-cooldown") .setDuration(ProtobufUtil.createDurationProto(Duration.ofSeconds(15))) - .setIcon(ProtobufUtil.createItemStackIconProto("ENDER_PEARL", 0, 0)) + .setIcon(Icon.newBuilder() + .setItemStack(ProtobufUtil.createItemStackIconProto("ENDER_PEARL", 0, 0)) + .build()) .build(); ProtobufPacketUtil.sendPacket(viewer, message); @@ -50,7 +53,9 @@ public void displayCooldownResourceExample(Player viewer) { DisplayCooldownMessage message = DisplayCooldownMessage.newBuilder() .setName("lunar-cooldown") .setDuration(ProtobufUtil.createDurationProto(Duration.ofSeconds(15))) - .setIcon(ProtobufUtil.createSimpleResourceLocationIconProto("lunar:logo/logo-200x182.svg", 12)) + .setIcon(Icon.newBuilder() + .setSimpleResourceLocation(ProtobufUtil.createSimpleResourceLocationIconProto("lunar:logo/logo-200x182.svg", 12)) + .build()) .build(); ProtobufPacketUtil.sendPacket(viewer, message); diff --git a/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/module/NotificationProtoExample.java b/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/module/NotificationProtoExample.java index 3fcf905cb..0853dca56 100644 --- a/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/module/NotificationProtoExample.java +++ b/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/module/NotificationProtoExample.java @@ -50,7 +50,7 @@ public void displayNotificationExample(Player viewer) { .append(Component.text("Good luck!", NamedTextColor.GOLD)) ) ) - .setResourceLocation("icons/golden_apple.png") // This field is optional + .setResourceLocation("textures/items/apple_golden.png") // This field is optional .setDisplayTime(ProtobufUtil.createDurationProto(Duration.ofSeconds(5))) .build(); diff --git a/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/module/ServerLinkProtoExample.java b/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/module/ServerLinkProtoExample.java new file mode 100644 index 000000000..c39e53cc2 --- /dev/null +++ b/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/module/ServerLinkProtoExample.java @@ -0,0 +1,106 @@ +/* + * 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.example.proto.module; + +import com.google.common.collect.Lists; +import com.lunarclient.apollo.example.module.impl.ServerLinkExample; +import com.lunarclient.apollo.example.proto.util.AdventureUtil; +import com.lunarclient.apollo.example.proto.util.ProtobufPacketUtil; +import com.lunarclient.apollo.example.proto.util.ProtobufUtil; +import com.lunarclient.apollo.serverlink.v1.AddServerLinkMessage; +import com.lunarclient.apollo.serverlink.v1.OverrideServerLinkResourceMessage; +import com.lunarclient.apollo.serverlink.v1.RemoveServerLinkMessage; +import com.lunarclient.apollo.serverlink.v1.ResetServerLinkResourceMessage; +import com.lunarclient.apollo.serverlink.v1.ResetServerLinksMessage; +import com.lunarclient.apollo.serverlink.v1.ServerLink; +import java.util.List; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.entity.Player; + +public class ServerLinkProtoExample extends ServerLinkExample { + + @Override + public void overrideServerLinkResourceExample(Player viewer) { + OverrideServerLinkResourceMessage message = OverrideServerLinkResourceMessage.newBuilder() + .setIcon(ProtobufUtil.createResourceLocationIconProto("lunar:logo/logo-100x100.png")) + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); + } + + @Override + public void resetServerLinkResourceExample(Player viewer) { + ResetServerLinkResourceMessage message = ResetServerLinkResourceMessage.getDefaultInstance(); + ProtobufPacketUtil.sendPacket(viewer, message); + } + + @Override + public void addServerLinkExample(Player viewer) { + List serverLinks = Lists.newArrayList( + ServerLink.newBuilder() + .setId("website") + .setDisplayNameAdventureJsonLines(AdventureUtil.toJson( + Component.text("Website", NamedTextColor.LIGHT_PURPLE))) + .setUrl("https://www.lunarclient.com/") + .build(), + ServerLink.newBuilder() + .setId("support") + .setDisplayNameAdventureJsonLines(AdventureUtil.toJson( + Component.text("Support", NamedTextColor.AQUA))) + .setUrl("https://support.lunarclient.com/") + .build(), + ServerLink.newBuilder() + .setId("status") + .setDisplayNameAdventureJsonLines(AdventureUtil.toJson( + Component.text("Status", NamedTextColor.RED))) + .setUrl("https://status.lunarclient.com/") + .build() + ); + + AddServerLinkMessage message = AddServerLinkMessage.newBuilder() + .addAllServerLinks(serverLinks) + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); + } + + @Override + public void removeServerLinkExample(Player viewer) { + List serverLinkIds = Lists.newArrayList("website", "support", "status"); + + RemoveServerLinkMessage message = RemoveServerLinkMessage.newBuilder() + .addAllServerLinkIds(serverLinkIds) + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); + } + + @Override + public void resetServerLinksExample(Player viewer) { + ResetServerLinksMessage message = ResetServerLinksMessage.getDefaultInstance(); + ProtobufPacketUtil.sendPacket(viewer, message); + } + +} diff --git a/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/util/ProtobufUtil.java b/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/util/ProtobufUtil.java index affc6a1f2..2c35b3c34 100644 --- a/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/util/ProtobufUtil.java +++ b/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/util/ProtobufUtil.java @@ -28,8 +28,8 @@ import com.lunarclient.apollo.common.v1.BlockLocation; import com.lunarclient.apollo.common.v1.Cuboid2D; import com.lunarclient.apollo.common.v1.EntityId; -import com.lunarclient.apollo.common.v1.Icon; import com.lunarclient.apollo.common.v1.ItemStackIcon; +import com.lunarclient.apollo.common.v1.ResourceLocationIcon; import com.lunarclient.apollo.common.v1.SimpleResourceLocationIcon; import com.lunarclient.apollo.common.v1.Uuid; import java.awt.Color; @@ -114,7 +114,7 @@ public static Location toBukkitLocation(com.lunarclient.apollo.common.v1.PlayerL return location; } - public static Icon createItemStackIconProto(@Nullable String itemName, int itemId, int customModelData) { + public static ItemStackIcon createItemStackIconProto(@Nullable String itemName, int itemId, int customModelData) { ItemStackIcon.Builder iconBuilder = ItemStackIcon.newBuilder() .setItemId(itemId) .setCustomModelData(customModelData); @@ -123,21 +123,25 @@ public static Icon createItemStackIconProto(@Nullable String itemName, int itemI iconBuilder.setItemName(itemName); } - return Icon.newBuilder().setItemStack(iconBuilder.build()).build(); + return iconBuilder.build(); } - public static Icon createSimpleResourceLocationIconProto(String resourceLocation, int size) { - SimpleResourceLocationIcon icon = SimpleResourceLocationIcon.newBuilder() + public static ResourceLocationIcon createResourceLocationIconProto(String resourceLocation) { + return ResourceLocationIcon.newBuilder() .setResourceLocation(resourceLocation) - .setSize(size) .build(); + } - return Icon.newBuilder().setSimpleResourceLocation(icon).build(); + public static SimpleResourceLocationIcon createSimpleResourceLocationIconProto(String resourceLocation, int size) { + return SimpleResourceLocationIcon.newBuilder() + .setResourceLocation(resourceLocation) + .setSize(size) + .build(); } - public static Icon createAdvancedResourceLocationIconProto(String resourceLocation, float width, float height, + public static AdvancedResourceLocationIcon createAdvancedResourceLocationIconProto(String resourceLocation, float width, float height, float minU, float maxU, float minV, float maxV) { - AdvancedResourceLocationIcon icon = AdvancedResourceLocationIcon.newBuilder() + return AdvancedResourceLocationIcon.newBuilder() .setResourceLocation(resourceLocation) .setWidth(width) .setHeight(height) @@ -146,8 +150,6 @@ public static Icon createAdvancedResourceLocationIconProto(String resourceLocati .setMinV(minV) .setMaxV(maxV) .build(); - - return Icon.newBuilder().setAdvancedResourceLocation(icon).build(); } private ProtobufUtil() { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1a56e5582..08faec7e0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ geantyref = "1.3.11" idea = "1.1.7" jetbrains = "24.0.1" lombok = "1.18.38" -protobuf = "0.0.6" +protobuf = "0.0.8" gson = "2.10.1" shadow = "8.1.1" spotless = "6.13.0" diff --git a/platform/bukkit/src/main/java/com/lunarclient/apollo/ApolloBukkitPlatform.java b/platform/bukkit/src/main/java/com/lunarclient/apollo/ApolloBukkitPlatform.java index fd5918685..8965682cf 100644 --- a/platform/bukkit/src/main/java/com/lunarclient/apollo/ApolloBukkitPlatform.java +++ b/platform/bukkit/src/main/java/com/lunarclient/apollo/ApolloBukkitPlatform.java @@ -68,6 +68,8 @@ import com.lunarclient.apollo.module.richpresence.RichPresenceModule; import com.lunarclient.apollo.module.richpresence.RichPresenceModuleImpl; import com.lunarclient.apollo.module.saturation.SaturationModule; +import com.lunarclient.apollo.module.serverlink.ServerLinkModule; +import com.lunarclient.apollo.module.serverlink.ServerLinkModuleImpl; import com.lunarclient.apollo.module.serverrule.ServerRuleModule; import com.lunarclient.apollo.module.staffmod.StaffModModule; import com.lunarclient.apollo.module.staffmod.StaffModModuleImpl; @@ -152,6 +154,7 @@ public void onEnable() { .addModule(PacketEnrichmentModule.class, new PacketEnrichmentImpl()) .addModule(PayNowModule.class, new PayNowModuleImpl()) .addModule(RichPresenceModule.class, new RichPresenceModuleImpl()) + .addModule(ServerLinkModule.class, new ServerLinkModuleImpl()) .addModule(SaturationModule.class) .addModule(ServerRuleModule.class) .addModule(StaffModModule.class, new StaffModModuleImpl()) diff --git a/platform/bungee/src/main/java/com/lunarclient/apollo/ApolloBungeePlatform.java b/platform/bungee/src/main/java/com/lunarclient/apollo/ApolloBungeePlatform.java index 24d75c18c..7e958dc05 100644 --- a/platform/bungee/src/main/java/com/lunarclient/apollo/ApolloBungeePlatform.java +++ b/platform/bungee/src/main/java/com/lunarclient/apollo/ApolloBungeePlatform.java @@ -58,6 +58,8 @@ import com.lunarclient.apollo.module.paynow.PayNowModuleImpl; import com.lunarclient.apollo.module.richpresence.RichPresenceModule; import com.lunarclient.apollo.module.richpresence.RichPresenceModuleImpl; +import com.lunarclient.apollo.module.serverlink.ServerLinkModule; +import com.lunarclient.apollo.module.serverlink.ServerLinkModuleImpl; import com.lunarclient.apollo.module.serverrule.ServerRuleModule; import com.lunarclient.apollo.module.staffmod.StaffModModule; import com.lunarclient.apollo.module.staffmod.StaffModModuleImpl; @@ -131,6 +133,7 @@ public void onEnable() { .addModule(NotificationModule.class, new NotificationModuleImpl()) .addModule(PayNowModule.class, new PayNowModuleImpl()) .addModule(RichPresenceModule.class, new RichPresenceModuleImpl()) + .addModule(ServerLinkModule.class, new ServerLinkModuleImpl()) .addModule(ServerRuleModule.class) .addModule(StaffModModule.class, new StaffModModuleImpl()) .addModule(StopwatchModule.class, new StopwatchModuleImpl()) diff --git a/platform/folia/src/main/java/com/lunarclient/apollo/ApolloFoliaPlatform.java b/platform/folia/src/main/java/com/lunarclient/apollo/ApolloFoliaPlatform.java index dca57648c..e28530da7 100644 --- a/platform/folia/src/main/java/com/lunarclient/apollo/ApolloFoliaPlatform.java +++ b/platform/folia/src/main/java/com/lunarclient/apollo/ApolloFoliaPlatform.java @@ -64,6 +64,8 @@ import com.lunarclient.apollo.module.paynow.PayNowModuleImpl; import com.lunarclient.apollo.module.richpresence.RichPresenceModule; import com.lunarclient.apollo.module.richpresence.RichPresenceModuleImpl; +import com.lunarclient.apollo.module.serverlink.ServerLinkModule; +import com.lunarclient.apollo.module.serverlink.ServerLinkModuleImpl; import com.lunarclient.apollo.module.serverrule.ServerRuleModule; import com.lunarclient.apollo.module.staffmod.StaffModModule; import com.lunarclient.apollo.module.staffmod.StaffModModuleImpl; @@ -140,6 +142,7 @@ public void onEnable() { .addModule(PacketEnrichmentModule.class, new PacketEnrichmentImpl()) .addModule(PayNowModule.class, new PayNowModuleImpl()) .addModule(RichPresenceModule.class, new RichPresenceModuleImpl()) + .addModule(ServerLinkModule.class, new ServerLinkModuleImpl()) .addModule(ServerRuleModule.class) .addModule(StaffModModule.class, new StaffModModuleImpl()) .addModule(StopwatchModule.class, new StopwatchModuleImpl()) diff --git a/platform/minestom/src/main/java/com/lunarclient/apollo/ApolloMinestomPlatform.java b/platform/minestom/src/main/java/com/lunarclient/apollo/ApolloMinestomPlatform.java index fd1357a8d..559d4e5c4 100644 --- a/platform/minestom/src/main/java/com/lunarclient/apollo/ApolloMinestomPlatform.java +++ b/platform/minestom/src/main/java/com/lunarclient/apollo/ApolloMinestomPlatform.java @@ -67,6 +67,8 @@ import com.lunarclient.apollo.module.richpresence.RichPresenceModule; import com.lunarclient.apollo.module.richpresence.RichPresenceModuleImpl; import com.lunarclient.apollo.module.saturation.SaturationModule; +import com.lunarclient.apollo.module.serverlink.ServerLinkModule; +import com.lunarclient.apollo.module.serverlink.ServerLinkModuleImpl; import com.lunarclient.apollo.module.serverrule.ServerRuleModule; import com.lunarclient.apollo.module.staffmod.StaffModModule; import com.lunarclient.apollo.module.staffmod.StaffModModuleImpl; @@ -174,6 +176,7 @@ public static void init(ApolloMinestomProperties properties) { .addModule(PacketEnrichmentModule.class, new PacketEnrichmentImpl()) .addModule(PayNowModule.class, new PayNowModuleImpl()) .addModule(RichPresenceModule.class, new RichPresenceModuleImpl()) + .addModule(ServerLinkModule.class, new ServerLinkModuleImpl()) .addModule(SaturationModule.class) .addModule(ServerRuleModule.class) .addModule(StaffModModule.class, new StaffModModuleImpl()) diff --git a/platform/velocity/src/main/java/com/lunarclient/apollo/ApolloVelocityPlatform.java b/platform/velocity/src/main/java/com/lunarclient/apollo/ApolloVelocityPlatform.java index e975fae09..1b8501ed5 100644 --- a/platform/velocity/src/main/java/com/lunarclient/apollo/ApolloVelocityPlatform.java +++ b/platform/velocity/src/main/java/com/lunarclient/apollo/ApolloVelocityPlatform.java @@ -58,6 +58,8 @@ import com.lunarclient.apollo.module.paynow.PayNowModuleImpl; import com.lunarclient.apollo.module.richpresence.RichPresenceModule; import com.lunarclient.apollo.module.richpresence.RichPresenceModuleImpl; +import com.lunarclient.apollo.module.serverlink.ServerLinkModule; +import com.lunarclient.apollo.module.serverlink.ServerLinkModuleImpl; import com.lunarclient.apollo.module.serverrule.ServerRuleModule; import com.lunarclient.apollo.module.staffmod.StaffModModule; import com.lunarclient.apollo.module.staffmod.StaffModModuleImpl; @@ -196,6 +198,7 @@ public void onProxyInitialization(ProxyInitializeEvent event) { .addModule(NotificationModule.class, new NotificationModuleImpl()) .addModule(PayNowModule.class, new PayNowModuleImpl()) .addModule(RichPresenceModule.class, new RichPresenceModuleImpl()) + .addModule(ServerLinkModule.class, new ServerLinkModuleImpl()) .addModule(ServerRuleModule.class) .addModule(StaffModModule.class, new StaffModModuleImpl()) .addModule(StopwatchModule.class, new StopwatchModuleImpl())