This Minecraft mod enhances the game by providing a more lifelike simulation of animal interaction and breeding. It introduces additional attributes and characteristics to existing Minecraft animals, enabling them to exhibit more realistic behaviors and interactions. Currently, in Minecraft 1.21.1, Horses can be bred to produce more desirable foals, with higher jump strength and speed. This mod expands on this feature, allowing players to breed other animals, in a similar way, to create offspring with specific traits and characteristics.
This mod uses Minecraft version 1.21.1
If you want to contribute to the mod, use method 1.
- Download the Java JDK of version 21-LT that matches your system.
- Make sure to have a java compilier. We suggest IntelliJ IDEA, the community edition is free to use.
- Clone the repository
- Open the repository in IntelliJ
- Run Minecraft Client through Gradle
Fabric Modding Tutorial - Minecraft 1.21: Getting Started | #1
This mod requires Fabric Minecraft. Build the repository for a .jar file, and use it in the mods folder of your Minecraft world to playtest.
Currently, the mod includes an implementation for cows. To add a new mob, which we'll refer to as "NewMob", follow these steps:
- Navigate to the
mobsdirectory. - Create a new directory for "NewMob": main/java/com/geneticselection/mobs/newmob
In your main/java/com/geneticselection/mobs/newmob create a file named CustomMobEntity.java (replace Mob with your animal name).
Example below: main/java/com/geneticselection/mobs/Cows/CustomCowEntity.java
package com.geneticselection.mobs.Cows;
import com.geneticselection.ModEntities;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.passive.CowEntity;
import net.minecraft.entity.passive.PassiveEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUsage;
import net.minecraft.item.Items;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.world.World;
import java.util.Random;
public class CustomCowEntity extends CowEntity {
private int MaxHp;
private int MinMeat;
private int MaxMeat;
private int MinLeather;
private int MaxLeather;
public CustomCowEntity(EntityType<? extends CowEntity> entityType, World world) {
super(entityType, world);
Random random = new Random();
this.MaxHp = 5 + random.nextInt(11);
this.MinMeat = 1+ random.nextInt(2);
this.MaxMeat = MinMeat + random.nextInt(3);
this.MinLeather = random.nextInt(2);
this.MaxLeather = MinLeather + random.nextInt(2);
this.getAttributeInstance(EntityAttributes.GENERIC_MAX_HEALTH).setBaseValue(this.MaxHp);
}
@Override
public ActionResult interactMob(PlayerEntity player, Hand hand) {
ItemStack itemStack = player.getStackInHand(hand);
if (itemStack.isOf(Items.BUCKET) && !this.isBaby()) {
player.playSound(SoundEvents.ENTITY_COW_MILK, 1.0F, 1.0F);
ItemStack itemStack2 = ItemUsage.exchangeStack(itemStack, player, Items.MILK_BUCKET.getDefaultStack());
player.setStackInHand(hand, itemStack2);
return ActionResult.success(this.getWorld().isClient);
} else if (itemStack.isEmpty()) { // Check if the hand is empty
// Only display the stats on the server side to avoid duplication
if (!this.getWorld().isClient) {
player.sendMessage(Text.literal("Custom Cow Stats:"));
player.sendMessage(Text.literal("Max Health: " + MaxHp));
player.sendMessage(Text.literal("Min Meat: " + MinMeat));
player.sendMessage(Text.literal("Max Meat: " + MaxMeat));
player.sendMessage(Text.literal("Min Leather: " + MinLeather));
player.sendMessage(Text.literal("Max Leather: " + MaxLeather));
player.sendMessage(Text.literal("----------------------------------------------"));
}
return ActionResult.success(this.getWorld().isClient);
} else {
return super.interactMob(player, hand);
}
}
@Override
public void onDeath(DamageSource source) {
super.onDeath(source);
if (!this.getWorld().isClient) {
// Calculate the amount of meat to drop between MinMeat and MaxMeat
int meatAmount = MinMeat + this.getWorld().random.nextInt((MaxMeat - MinMeat) + 1);
this.dropStack(new ItemStack(Items.BEEF, meatAmount));
// Calculate the amount of leather to drop between MinLeather and MaxLeather
int leatherAmount = MinLeather + this.getWorld().random.nextInt((MaxLeather - MinLeather) + 1);
this.dropStack(new ItemStack(Items.LEATHER, leatherAmount));
}
}
@Override
public CustomCowEntity createChild(ServerWorld serverWorld, PassiveEntity mate) {
if (!(mate instanceof CustomCowEntity)) {
return (CustomCowEntity) EntityType.COW.create(serverWorld);
}
CustomCowEntity parent1 = this;
CustomCowEntity parent2 = (CustomCowEntity) mate;
int childMaxHp = (parent1.MaxHp + parent2.MaxHp) / 2;
int childMinMeat = (parent1.MinMeat + parent2.MinMeat) / 2;
int childMaxMeat = (parent1.MaxMeat + parent2.MaxMeat) / 2;
int childMinLeather = (parent1.MinLeather + parent2.MinLeather) / 2;
int childMaxLeather = (parent1.MaxLeather + parent2.MaxLeather) / 2;
CustomCowEntity child = new CustomCowEntity(ModEntities.CUSTOM_COW, serverWorld);
child.MaxHp = childMaxHp;
child.MinMeat = childMinMeat;
child.MaxMeat = childMaxMeat;
child.MinLeather = childMinLeather;
child.MaxLeather = childMaxLeather;
child.getAttributeInstance(EntityAttributes.GENERIC_MAX_HEALTH).setBaseValue(child.MaxHp);
return child;
}
}Your attributes, breeding logic, calculations, and drops will be done mostly in this file. Override default minecraft functions to how you see fit. For now, just create the basic super class and mess with the logic once you got everything set up.
Navagate to main\java\com\geneticselection\mobs\ModEntities.java, to register your custom mob. Do not create a new file, simply just add onto the commented section:
package com.geneticselection.mobs;
import com.geneticselection.GeneticSelection;
import com.geneticselection.mobs.Cows.CustomCowEntity;
import net.fabricmc.fabric.api.object.builder.v1.entity.FabricEntityTypeBuilder;
import net.minecraft.entity.EntityDimensions;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.SpawnGroup;
import net.minecraft.util.Identifier;
import net.minecraft.registry.Registry;
import net.minecraft.registry.Registries;
public class ModEntities{
public static final EntityType<CustomCowEntity> CUSTOM_COW = Registry.register(
Registries.ENTITY_TYPE,
Identifier.of(GeneticSelection.MOD_ID, "custom_cow"),
FabricEntityTypeBuilder.create(SpawnGroup.CREATURE, CustomCowEntity::new)
.dimensions(EntityDimensions.fixed(0.9F, 1.4F))
.build()
);
//register new mobs here by using the above format
}Copy the format of the provided example and change the variables as you need.
Navagate to main\java\com\geneticselection\mobs\ModModleLayers.java, to add your custom mobs model layer. Do not create a new file, simply just add onto the commented section:
package com.geneticselection.mobs;
import com.geneticselection.GeneticSelection;
import net.minecraft.client.render.entity.model.EntityModelLayer;
import net.minecraft.util.Identifier;
public class ModModleLayers {
public static final EntityModelLayer CUSTOM_COW = new EntityModelLayer(Identifier.of(GeneticSelection.MOD_ID,"custom_cow"), "main");
//add your new mobs here by using the above format
}Copy the format of the provided example and change the variables as you need.
Navagate to main\java\com\geneticselection\mobs\newmob and create a file named NewmobRenderer.java.
example below: main\java\com\geneticselection\mobs\Cows\CustomCowRenderer.java
package com.geneticselection.mobs.Cows;
import com.geneticselection.GeneticSelection;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.render.entity.MobEntityRenderer;
import net.minecraft.client.render.entity.model.CowEntityModel;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Identifier;
public class CustomCowRenderer extends MobEntityRenderer<CustomCowEntity, CowEntityModel<CustomCowEntity>> {
private static final Identifier TEXTURE = Identifier.of(GeneticSelection.MOD_ID, "textures/entity/minecraft-cow.png");
public CustomCowRenderer(EntityRendererFactory.Context context) {
super(context, new CowEntityModel<>(context.getPart(ModModleLayers.CUSTOM_COW)), 0.6f);
}
@Override
public Identifier getTexture(CustomCowEntity entity) {
return TEXTURE;
}
@Override
public void render(CustomCowEntity livingEntity, float f, float g, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i) {
super.render(livingEntity, f, g, matrixStack, vertexConsumerProvider, i);
}
}For your textures in "textures/entity/minecraft-cow.png", navagate to your main\resources\assets\genetic-selection\textures\entity and drop a png file of a texture you want for your mob. For example, the cow one main\resources\assets\genetic-selection\textures\entity\minecraft-cow.png. For the rest, copy the format of the provided example and change the variables as you need.
- Navagate to
main\java\com\geneticselection\GeneticSelection.java - Create a method that pertains to your mob
- Register the default attibutes to your mob
- Lower the spawn rate of the vanilla mobs and allow your custom mobs to spawn
- Set the spawning requirements for your mob if neede
- Call your method in onInitialize
Copy the format of the provided example and change the variables as you need.
ex: main\java\com\geneticselection\GeneticSelection.java
public void cowMethod(){
//Register the default attibutes to your mob
FabricDefaultAttributeRegistry.register(ModEntities.CUSTOM_COW, CustomCowEntity.createCowAttributes());
//lowers the spawn rate of default vanilla cows
BiomeModifications.addSpawn(
BiomeSelectors.foundInOverworld(),
SpawnGroup.CREATURE,
EntityType.COW, // Remove the original cow
0, // Spawn weight (higher = more frequent)
0, // No minimum group size
0 // No maximum group size
);
//adds custom cow to natural spawn
BiomeModifications.addSpawn(
BiomeSelectors.foundInOverworld(),
SpawnGroup.CREATURE,
ModEntities.CUSTOM_COW, // Add custom cow
20, // Spawn weight (higher = more frequent)
2, // Minimum group size
4 // Maximum group size
);
//restricts the cow spawn to grass blocks on the ground
SpawnRestriction.register(
ModEntities.CUSTOM_COW,
SpawnLocationTypes.ON_GROUND,
Heightmap.Type.MOTION_BLOCKING_NO_LEAVES,
(entityType, world, spawnReason, pos, random) ->
world.getBlockState(pos.down()).isOf(Blocks.GRASS_BLOCK)
);
}- Navagate to
main\java\com\geneticselection\GeneticSelectionClient.java - Create a method that pertains to your mob
- Register your mob
- register the model layer for your mob
- Call your method in onInitializeClient
Copy the format of the provided example and change the variables as you need.
ex: main\java\com\geneticselection\GeneticSelectionClient.java
public void cowMethod(){
//register your cow
EntityRendererRegistry.register(ModEntities.CUSTOM_COW, CustomCowRenderer::new);
//register your model layer for your cow
EntityModelLayerRegistry.registerModelLayer(ModModleLayers.CUSTOM_COW, CowEntityModel::getTexturedModelData);
}Made with contrib.rocks.
TonyJRPI https://github.com/TonyJRPI
winsonlin21 https://github.com/winsonlin21
corxgi https://github.com/corxgi
AnthonyLi88 https://github.com/AnthonyLi88
@samsthenerd (discord)