@@ -41,6 +41,17 @@ public static Component createCustomSprite(String path) {
4141 return Component .object (sprite (Key .key (path )));
4242 }
4343
44+ /**
45+ * Creates a sprite component from a custom path with atlas
46+ * @param atlas The atlas (e.g., "gui", "blocks")
47+ * @param path The sprite path
48+ * @return A Component containing the sprite
49+ */
50+ public static Component createCustomSprite (String atlas , String path ) {
51+ path = path .replaceAll ("^/+|/+$" , "" );
52+ return Component .object (sprite (Key .key ("minecraft" , atlas ), Key .key (path )));
53+ }
54+
4455 /**
4556 * Creates a sprite component from a full namespaced key
4657 * @param namespace The namespace (e.g., "minecraft")
@@ -73,35 +84,88 @@ public static Component createPlayerHeadSprite(String playerName) {
7384 /**
7485 * Creates a TagResolver for custom sprite placeholders in MiniMessage format.
7586 * Supports the following formats:
76- * - <sprite:path> - Creates a sprite from the given path (e.g., <sprite:hud/heart/full>)
87+ * - <sprite:path> - Creates a sprite from the given path (e.g., <sprite:item/diamond_sword>)
88+ * - <sprite:atlas/path> - Creates a sprite with atlas (e.g., <sprite:gui/hud/heart/full>)
7789 * - <sprite:namespace:path> - Creates a sprite with custom namespace (e.g., <sprite:mypack:custom/icon>)
90+ * - <sprite:namespace:atlas/path> - Full specification (e.g., <sprite:minecraft:gui/hud/heart/full>)
7891 *
7992 * @return A TagResolver that handles sprite tags
8093 */
8194 public static TagResolver spriteResolver () {
8295 return TagResolver .resolver ("sprite" , (args , ctx ) -> {
8396 String argument = args .popOr ("Missing sprite path" ).value ();
8497
85- // Check if it contains a namespace (has two colons)
86- String [] parts = argument .split (":" , 2 );
8798 Component spriteComponent ;
8899
89- if (parts .length == 2 && parts [1 ].contains (":" )) {
90- // Format: namespace:path (e.g., "minecraft:hud/heart/full")
91- String [] namespaceParts = parts [1 ].split (":" , 2 );
92- spriteComponent = createNamespacedSprite (parts [0 ], namespaceParts [1 ]);
93- } else if (parts .length == 2 ) {
94- // Format: namespace:path (e.g., "mypack:custom/icon")
95- spriteComponent = createNamespacedSprite (parts [0 ], parts [1 ]);
100+ // Check if it contains namespace separator (:)
101+ if (argument .contains (":" )) {
102+ String [] parts = argument .split (":" , 2 );
103+ String firstPart = parts [0 ];
104+ String secondPart = parts [1 ];
105+
106+ // Check if second part also contains a colon (namespace:atlas/path format)
107+ if (secondPart .contains (":" )) {
108+ // Format: namespace:atlas/path or namespace:path
109+ String [] subParts = secondPart .split (":" , 2 );
110+ // This is actually just namespace:path format, use default handling
111+ spriteComponent = createNamespacedSprite (firstPart , subParts [1 ]);
112+ } else if (secondPart .contains ("/" )) {
113+ // Check if this looks like an atlas/path format
114+ String [] pathParts = secondPart .split ("/" , 2 );
115+ String possibleAtlas = pathParts [0 ];
116+
117+ // Known atlases: gui, blocks, etc.
118+ if (isKnownAtlas (possibleAtlas )) {
119+ // Format: namespace:atlas/path
120+ String atlas = possibleAtlas ;
121+ String path = pathParts [1 ];
122+ spriteComponent = Component .object (sprite (
123+ Key .key (firstPart , atlas ),
124+ Key .key (path )
125+ ));
126+ } else {
127+ // Format: namespace:path (no atlas)
128+ spriteComponent = createNamespacedSprite (firstPart , secondPart );
129+ }
130+ } else {
131+ // Format: namespace:path (no slashes)
132+ spriteComponent = createNamespacedSprite (firstPart , secondPart );
133+ }
134+ } else if (argument .contains ("/" )) {
135+ // No namespace specified, check if first part is an atlas
136+ String [] pathParts = argument .split ("/" , 2 );
137+ String possibleAtlas = pathParts [0 ];
138+
139+ if (isKnownAtlas (possibleAtlas )) {
140+ // Format: atlas/path (e.g., gui/hud/heart/full)
141+ String atlas = possibleAtlas ;
142+ String path = pathParts [1 ];
143+ spriteComponent = createCustomSprite (atlas , path );
144+ } else {
145+ // Format: regular path (defaults to minecraft namespace, default atlas)
146+ spriteComponent = createCustomSprite (argument );
147+ }
96148 } else {
97- // Format: path (e.g., "hud/ heart/full ") - defaults to minecraft namespace
149+ // Format: simple path (e.g., "heart") - defaults to minecraft namespace
98150 spriteComponent = createCustomSprite (argument );
99151 }
100152
101153 return Tag .selfClosingInserting (spriteComponent );
102154 });
103155 }
104156
157+ /**
158+ * Checks if a string is a known Minecraft atlas
159+ * @param name The potential atlas name
160+ * @return true if it's a known atlas
161+ */
162+ private static boolean isKnownAtlas (String name ) {
163+ return switch (name ) {
164+ case "gui" , "blocks" , "items" , "particles" , "mob_effects" , "paintings" , "map_decorations" -> true ;
165+ default -> false ;
166+ };
167+ }
168+
105169 /**
106170 * Creates a TagResolver for item sprite placeholders.
107171 * Usage: <item_sprite> (requires an ItemStack to be provided separately)
0 commit comments