Spawn eggs were almost an afterthought in Bok’s Banging Butterflies. They worked, but the experience was rough. Not all entities had spawn eggs, and most eggs looked identical. With 61 butterfly and moth species, it was almost impossible for players to know what they were spawning.
Problems with Spawn Eggs
It was time to fix this. One of the big problems is that in Minecraft 1.21.5 onwards, spawn eggs no longer use the old textures. This makes sense, trying to identify each mob by two colours alone was becoming harder and harder as more mobs were added to the game.
So I decided to update the textures for the spawn eggs based on their species. But it seemed a daunting task. There are 61 species of butterfly and moth in the mod at the time of writing. And each species has four stages of growth: egg, caterpillar/larva, chrysalis/cocoon, and butterfly/moth. This means I would need to create 244 unique textures to cover all the mobs, 245 including the Butterfly Golem.
Obviously I didn’t want to spend hours and hours creating textures, especially as I’m not the best artist in the world. So, as a lazy programmer, I decided to cheat. I decided to figure out a way to generate the textures using a python script.
Cheating with Python
The solution I came up with was seemingly simple. I’d take the base egg texture, and overlay the icon for the mob on top of it. A Python script to do this is pretty simple if we use the Pillow library:
import os from PIL import Image def overlay_images(base_path, overlay_path, output_path): base_img = Image.open(base_path).convert('RGBA') overlay_img = Image.open(overlay_path).convert('RGBA') # Create the image overlay_final = Image.new('RGBA', base_img.size, (0, 0, 0, 0)) overlay_final.paste(overlay_img, (0, 0), overlay_img) # Save the image combined = Image.alpha_composite(base_img, overlay_final) combined.save(output_path) for x in os.listdir(): if x.endswith(".png") and x.startswith("caterpillar_"): overlay_images('spawn_egg.png', x, '../../item/spawn_egg/caterpillar/' + x[10:])
By running this script in the same folder as the caterpillar item textures I was able to batch generate textures instead of doing them by hand. Using the x[10:]
slice into the file name, I was able to trim the caterpillar_
prefix and leave files with just the name of the species:
I updated the item models to point to these new textures instead of the default texture. In code I had to set the spawn egg colours to white to avoid a tint being applied to the new textures. If you load into the game now, you can see what each species of caterpillar will look like before you spawn one in:

I repeated the same script for butterfly eggs, but there was a small problem. The default egg textures are actually too large, and most cover up the base texture completely. I decided to fix this by allowing the script to scale the textures before overlaying them on top of the base texture:
def overlay_images(base_path, overlay_path, output_path, scale=1.0): base_img = Image.open(base_path).convert('RGBA') overlay_img = Image.open(overlay_path).convert('RGBA') # Resize the image new_width = int(base_img.width * scale) new_height = int(base_img.height * scale) overlay_resized = overlay_img.resize((new_width, new_height), Image.Resampling.LANCZOS) # Ensure the overlay fits if overlay_resized.size > base_img.size: new_width = base_img.width new_height = base_img.height overlay_resized = overlay_resized.resize(base_img.size, Image.Resampling.LANCZOS) # Try and center the image position = ((base_img.width - new_width) // 2, (base_img.height - new_height) // 2) # Create the image overlay_final = Image.new('RGBA', base_img.size, (0, 0, 0, 0)) overlay_final.paste(overlay_img, position, overlay_img) # Save the image combined = Image.alpha_composite(base_img, overlay_final) combined.save(output_path)
This function also ensures that the image will fit within the original size of the base image, so even if the overlay was too big, it would shrink automatically. This script worked for creating butterfly egg textures, but there was a problem with chrysalises. Their textures weren’t centered, so even after this manipulation they were off-center in the final image.
To fix this, I added an optional offset to the function:
def overlay_images(base_path, overlay_path, output_path, offset=(0, 0), scale=1.0): # ... # Resize the image # ... # Ensure the overlay fits # ... # Center and offset the image position = (((base_img.width - new_width) // 2) + offset[0], ((base_img.height - new_height) // 2) + offset[1]) # Create the image # ... # Save the image # ...
This allowed me to tweak the position slightly, and generated some decent looking textures for the chrysalis spawn eggs:

The final problem now was how to generate the textures for butterfly spawn eggs. This one wasn’t going to be easy. I had some textures I might be able to use, but each had their problems. The bottled butterflies were half covered by the glass bottle texture. The scroll textures had opacity applied to the butterfly colours. Neither were good candidates for pumping into this script.
So I decided the best solution was to simply use the base textures for the butterfly entities. If I could pull out just the wings, rotate and scale them correctly, then I could easily generate textures for the spawn eggs.
So I typed away and experimented with cropping and rotating the image until I came out with this script:
import os from PIL import Image def overlay_images(base_path, overlay_path, output_path, crop_start=(0, 0), crop_size=(16, 16), offset=(0, 0), scale=1.0, rotate=0): base_img = Image.open(base_path).convert('RGBA') overlay_img = Image.open(overlay_path).convert('RGBA') # Crop the image overlay_cropped = overlay_img.crop((crop_start[0], crop_start[1], crop_start[0] + crop_size[0], crop_start[1] + crop_size[1])) # Rotate the image overlay_rotated = overlay_cropped.rotate(rotate, expand=True) # Resize the image new_width = int(base_img.width * scale) new_height = int(base_img.height * scale) overlay_resized = overlay_rotated.resize((new_width, new_height), Image.Resampling.LANCZOS) # Ensure the overlay fits if overlay_resized.size > base_img.size: new_width = base_img.width new_height = base_img.height overlay_resized = overlay_resized.resize(base_img.size, Image.Resampling.LANCZOS) position = (((base_img.width - new_width) // 2) + offset[0], ((base_img.height - new_height) // 2) + offset[1]) # Offset the image overlay_final = Image.new('RGBA', base_img.size, (0, 0, 0, 0)) overlay_final.paste(overlay_resized, position, overlay_resized) # Save the image combined = Image.alpha_composite(base_img, overlay_final) combined.save(output_path) for x in os.listdir(): if x.endswith(".png") and x.startswith("butterfly_"): overlay_images( 'spawn_egg.png', x, '../../item/spawn_egg/butterfly/' + x[10:], crop_start=(10, 0), crop_size=(17, 20), rotate=90, scale=0.8, offset=(0, 1))
Once I had the cropping and rotating implemented, it was simply a matter of trial and error until I got something that looked nice. And I’m really happy with the end result:

It’s amazing to me that you can see what the butterfly looks like before you spawn it. Even newcomers to the mod don’t need to know the species’ names. They can just pick their favorite design.
With all this work done, it was time to create a new release, but after doing all this work it left me with some ideas.
Texture Generation Pipeline
I’m genuinely happy with the way these textures came out. I want to implement this into my data generation pipeline so these textures will get generated automatically. Not only that, it’s left me wanting to generate more textures rather than creating them manually.
Right now I have to create 9 textures for each butterfly I implement:
- Butterfly Entity
- Bottled Butterfly Item
- Scroll Gui
- Scroll Item
- Chrysalis Entity
- Caterpillar Entity
- Caterpillar Item
- Bottled Caterpillar Item
- Egg Entity/Item
Looking at that list there are 5 textures that could potentially be generated automatically:
- Bottled Butterfly Item
Scale down and rotate the wings from the butterfly entity texture and overlay the bottle texture on top. - Scroll GUI
Scale up the butterfly texture and overlay it onto the scroll. Then overlay the nail texture on top of that,. - Scroll Item
Essentially the same as the spawn egg texture, except using a different base texture. - Caterpillar Item
Select colours from the Caterpillar Entity texture and place them in the correct position for this texture. - Bottled Caterpillar Item
Scaled down Caterpillar Item texture, with a bottle texture overlayed on top.
This would mean that I would only need to generate 4 textures for each new species and auto-generate the rest. The generated textures would probably look better as well.
So that’s what I’ll be working on next. So enjoy the new spawn eggs for now, and keep an eye out for better looking item textures in future versions of Bok’s Banging Butterflies!
If you have your own tricks for making Minecraft textures, or ideas for features in Bok’s Banging Butterflies, feel free to drop a comment or open an issue.