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
@@ -0,0 +1,79 @@
/*
* 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 java.util.Collections;
import java.util.List;
import lombok.Builder;
import lombok.Getter;

/**
* Represents the custom model data attached to an {@link ItemStackIcon}.
*
* <p>Mirrors the Minecraft 1.21.4 {@code CustomModelData} item component, which
* replaced the single integer value with four parallel lists.</p>
*
* @since 1.2.7
*/
@Getter
@Builder
public final class CustomModelData {

/**
* Returns the custom model data {@link Float} values.
*
* @return the custom model data floats
* @since 1.2.7
*/
@Builder.Default
List<Float> floats = Collections.emptyList();

/**
* Returns the custom model data {@link Boolean} flags.
*
* @return the custom model data flags
* @since 1.2.7
*/
@Builder.Default
List<Boolean> flags = Collections.emptyList();

/**
* Returns the custom model data {@link String} values.
*
* @return the custom model data strings
* @since 1.2.7
*/
@Builder.Default
List<String> strings = Collections.emptyList();

/**
* Returns the custom model data color {@link Integer} values.
*
* @return the custom model data colors
* @since 1.2.7
*/
@Builder.Default
List<Integer> colors = Collections.emptyList();

}
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,20 @@ public final class ItemStackIcon extends Icon {
* Returns the icon {@link Integer} custom model data.
*
* @return the icon custom model data
* @deprecated for removal since 1.2.7, use {@link ItemStackIcon#customModelDataObject} instead.
* @since 1.0.7
*/
@Deprecated
int customModelData;

/**
* Returns the icon {@link CustomModelData} object.
*
* @return the icon custom model data object
* @since 1.2.7
*/
@Nullable CustomModelData customModelDataObject;

/**
* Returns the icon {@link Profile}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.lunarclient.apollo.common.cuboid.Cuboid2D;
import com.lunarclient.apollo.common.cuboid.Cuboid3D;
import com.lunarclient.apollo.common.icon.AdvancedResourceLocationIcon;
import com.lunarclient.apollo.common.icon.CustomModelData;
import com.lunarclient.apollo.common.icon.Icon;
import com.lunarclient.apollo.common.icon.ItemStackIcon;
import com.lunarclient.apollo.common.icon.ResourceLocationIcon;
Expand Down Expand Up @@ -577,6 +578,11 @@ public static com.lunarclient.apollo.common.v1.ItemStackIcon toProtobuf(ItemStac
.setItemId(icon.getItemId())
.setCustomModelData(icon.getCustomModelData());

CustomModelData customModelData = icon.getCustomModelDataObject();
if (customModelData != null) {
builder.setCustomModelDataObject(NetworkTypes.toProtobuf(customModelData));
}

if (icon.getItemName() != null) {
builder.setItemName(icon.getItemName());
}
Expand All @@ -602,13 +608,51 @@ public static ItemStackIcon fromProtobuf(com.lunarclient.apollo.common.v1.ItemSt
.itemId(icon.getItemId())
.customModelData(icon.getCustomModelData());

if (icon.hasCustomModelDataObject()) {
builder.customModelDataObject(NetworkTypes.fromProtobuf(icon.getCustomModelDataObject()));
}

if (icon.hasProfile()) {
builder.profile(NetworkTypes.fromProtobuf(icon.getProfile()));
}

return builder.build();
}

/**
* Converts a {@link CustomModelData} object to a
* {@link com.lunarclient.apollo.common.v1.CustomModelData} proto message.
*
* @param object the custom model data
* @return the proto custom model data message
* @since 1.2.7
*/
public static com.lunarclient.apollo.common.v1.CustomModelData toProtobuf(CustomModelData object) {
return com.lunarclient.apollo.common.v1.CustomModelData.newBuilder()
.addAllFloats(object.getFloats())
.addAllFlags(object.getFlags())
.addAllStrings(object.getStrings())
.addAllColors(object.getColors())
.build();
}

/**
* Converts a {@link com.lunarclient.apollo.common.v1.CustomModelData}
* proto message to a {@link CustomModelData} object.
*
* @param message the custom model data message
* @return the custom model data object
* @since 1.2.7
*/
public static CustomModelData fromProtobuf(com.lunarclient.apollo.common.v1.CustomModelData message) {
return CustomModelData.builder()
.floats(message.getFloatsList())
.flags(message.getFlagsList())
.strings(message.getStringsList())
.colors(message.getColorsList())
.build();
}

/**
* Converts a {@link Profile} object to a
* {@link com.lunarclient.apollo.common.v1.Profile} proto message.
Expand Down
32 changes: 28 additions & 4 deletions docs/developers/lightweight/json/object-util.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -88,19 +88,21 @@ public static JsonObject createBlockLocationObject(@NotNull Location location) {
Icon-related methods

```java
public static JsonObject createItemStackIconObject(@Nullable String itemName, int itemId, int customModelData) {
return JsonUtil.createItemStackIconObject(itemName, itemId, customModelData, null);
public static JsonObject createItemStackIconObject(@Nullable String itemName, int itemId) {
return JsonUtil.createItemStackIconObject(itemName, itemId, null, null);
}

public static JsonObject createItemStackIconObject(@Nullable String itemName, int itemId, int customModelData, @Nullable JsonObject profile) {
public static JsonObject createItemStackIconObject(@Nullable String itemName, int itemId, @Nullable JsonObject customModelData, @Nullable JsonObject profile) {
JsonObject itemIconObject = new JsonObject();
if (itemName != null) {
itemIconObject.addProperty("item_name", itemName);
} else {
itemIconObject.addProperty("item_id", itemId);
}

itemIconObject.addProperty("custom_model_data", customModelData);
if (customModelData != null) {
itemIconObject.add("custom_model_data_object", customModelData);
}

if (profile != null) {
itemIconObject.add("profile", profile);
Expand All @@ -111,6 +113,28 @@ public static JsonObject createItemStackIconObject(@Nullable String itemName, in
return iconObject;
}

public static JsonObject createCustomModelDataObject(List<Float> floats, List<Boolean> flags, List<String> strings, List<Integer> colors) {
JsonObject customModelDataObject = new JsonObject();

JsonArray floatsArray = new JsonArray();
floats.forEach(floatsArray::add);
customModelDataObject.add("floats", floatsArray);

JsonArray flagsArray = new JsonArray();
flags.forEach(flagsArray::add);
customModelDataObject.add("flags", flagsArray);

JsonArray stringsArray = new JsonArray();
strings.forEach(stringsArray::add);
customModelDataObject.add("strings", stringsArray);

JsonArray colorsArray = new JsonArray();
colors.forEach(colorsArray::add);
customModelDataObject.add("colors", colorsArray);

return customModelDataObject;
}

public static JsonObject createProfileObject(@Nullable UUID id, @NotNull String texture, @NotNull String signature) {
JsonObject profileObject = new JsonObject();
if (id != null) {
Expand Down
6 changes: 3 additions & 3 deletions docs/developers/lightweight/protobuf.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Available fields for each message, including their types, are available on the B
<dependency>
<groupId>com.lunarclient</groupId>
<artifactId>apollo-protos</artifactId>
<version>0.1.6</version>
<version>0.1.7</version>
</dependency>
</dependencies>
```
Expand All @@ -41,7 +41,7 @@ Available fields for each message, including their types, are available on the B
}

dependencies {
api 'com.lunarclient:apollo-protos:0.1.6'
api 'com.lunarclient:apollo-protos:0.1.7'
}
```
</Tab>
Expand All @@ -55,7 +55,7 @@ Available fields for each message, including their types, are available on the B
}

dependencies {
api("com.lunarclient:apollo-protos:0.1.6")
api("com.lunarclient:apollo-protos:0.1.7")
}
```
</Tab>
Expand Down
22 changes: 17 additions & 5 deletions docs/developers/lightweight/protobuf/object-util.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -97,26 +97,38 @@ public static Location toBukkitPlayerLocation(JsonObject message) {
Icon-related methods

```java
public static ItemStackIcon createItemStackIconProto(@Nullable String itemName, int itemId, int customModelData) {
return ProtobufUtil.createItemStackIconProto(itemName, itemId, customModelData, null);
public static ItemStackIcon createItemStackIconProto(@Nullable String itemName, int itemId) {
return ProtobufUtil.createItemStackIconProto(itemName, itemId, null, null);
}

public static ItemStackIcon createItemStackIconProto(@Nullable String itemName, int itemId, int customModelData, @Nullable Profile profile) {
public static ItemStackIcon createItemStackIconProto(@Nullable String itemName, int itemId, @Nullable CustomModelData customModelData, @Nullable Profile profile) {
ItemStackIcon.Builder iconBuilder = ItemStackIcon.newBuilder()
.setItemId(itemId)
.setCustomModelData(customModelData);
.setItemId(itemId);

if (itemName != null) {
iconBuilder.setItemName(itemName);
}

if (customModelData != null) {
iconBuilder.setCustomModelDataObject(customModelData);
}

if (profile != null) {
iconBuilder.setProfile(profile);
}

return iconBuilder.build();
}

public static CustomModelData createCustomModelDataProto(List<Float> floats, List<Boolean> flags, List<String> strings, List<Integer> colors) {
return CustomModelData.newBuilder()
.addAllFloats(floats)
.addAllFlags(flags)
.addAllStrings(strings)
.addAllColors(colors)
.build();
}

public static Profile createProfileProto(@Nullable UUID id, String texture, String signature) {
Profile.Builder builder = Profile.newBuilder()
.setTexture(texture)
Expand Down
12 changes: 6 additions & 6 deletions docs/developers/modules/cooldown.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ public void displayCooldownItemExample(Player viewer) {
.setName("enderpearl-cooldown")
.setDuration(ProtobufUtil.createDurationProto(Duration.ofSeconds(15)))
.setIcon(Icon.newBuilder()
.setItemStack(ProtobufUtil.createItemStackIconProto("ENDER_PEARL", 0, 0))
.setItemStack(ProtobufUtil.createItemStackIconProto("ENDER_PEARL", 0))
.build())
.build();

Expand All @@ -232,7 +232,7 @@ public void displayCooldownWithStyleExample(Player viewer) {
.setName("book-cooldown")
.setDuration(ProtobufUtil.createDurationProto(Duration.ofSeconds(30)))
.setIcon(Icon.newBuilder()
.setItemStack(ProtobufUtil.createItemStackIconProto("BOOK", 0, 0))
.setItemStack(ProtobufUtil.createItemStackIconProto("BOOK", 0))
.build())
.setStyle(CooldownStyle.newBuilder()
.setCircleStartColor(ProtobufUtil.createColorProto(new Color(255, 85, 85))) // ApolloColors.RED
Expand All @@ -255,7 +255,7 @@ public void displayCooldownWithPlayerTextureExample(Player viewer) {
.setDuration(ProtobufUtil.createDurationProto(Duration.ofSeconds(15)))
.setIcon(Icon.newBuilder()
.setItemStack(ProtobufUtil.createItemStackIconProto(
"PLAYER_HEAD", 0, 0,
"PLAYER_HEAD", 0, null,
ProtobufUtil.createProfileProto(
UUID.fromString("f17627d8-1a97-487b-92ea-c04f413394bd"),
"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOWQ4MjUwNWJjZjNiYTU5YzJiZTdlMmQzNmY0ZTJiZGE4MzZmMmZkMTk0YjYyMTJhMmExYzRiNGEyYTQ3MWUifX19",
Expand Down Expand Up @@ -322,7 +322,7 @@ public void displayCooldownItemExample(Player viewer) {
message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.cooldown.v1.DisplayCooldownMessage");
message.addProperty("name", "enderpearl-cooldown");
message.addProperty("duration", JsonUtil.createDurationObject(Duration.ofSeconds(15)));
message.add("icon", JsonUtil.createItemStackIconObject("ENDER_PEARL", 0, 0));
message.add("icon", JsonUtil.createItemStackIconObject("ENDER_PEARL", 0));

JsonPacketUtil.sendPacket(viewer, message);
}
Expand All @@ -336,7 +336,7 @@ public void displayCooldownWithStyleExample(Player viewer) {
message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.cooldown.v1.DisplayCooldownMessage");
message.addProperty("name", "book-cooldown");
message.addProperty("duration", JsonUtil.createDurationObject(Duration.ofSeconds(30)));
message.add("icon", JsonUtil.createItemStackIconObject("BOOK", 0, 0));
message.add("icon", JsonUtil.createItemStackIconObject("BOOK", 0));

JsonObject style = new JsonObject();
style.add("circle_start_color", JsonUtil.createColorObject(new Color(255, 85, 85))); // ApolloColors.RED
Expand All @@ -358,7 +358,7 @@ public void displayCooldownWithPlayerTextureExample(Player viewer) {
message.addProperty("name", "player-head-cooldown");
message.addProperty("duration", JsonUtil.createDurationObject(Duration.ofSeconds(15)));
message.add("icon", JsonUtil.createItemStackIconObject(
"PLAYER_HEAD", 0, 0,
"PLAYER_HEAD", 0, null,
JsonUtil.createProfileObject(
UUID.fromString("f17627d8-1a97-487b-92ea-c04f413394bd"),
"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOWQ4MjUwNWJjZjNiYTU5YzJiZTdlMmQzNmY0ZTJiZGE4MzZmMmZkMTk0YjYyMTJhMmExYzRiNGEyYTQ3MWUifX19",
Expand Down
Loading
Loading