agentsclimarketplace

Fabric entities

Skill PSB1234/Fabric-Minecraft-Skill-1.20.1/fabric-entities

Complete reference for custom mob and entity creation in Fabric Minecraft 1.20.1 — entity classes, attributes, goal/AI systems, server registration, client renderer registration, spawn eggs, entity NBT, and spawn rules. Use this skill whenever the user asks about creating a custom mob, custom entity, entity AI, EntityType registration, DefaultAttributeContainer, EntityGoal, MobEntity, PathAwareEntity, renderer, EntityModelLayer, spawn egg, or entity spawn rules. Triggers on: "custom mob", "custom entity", "EntityType", "MobEntity", "PathAwareEntity", "entity AI", "entity goal", "GoalSelector", "EntityAttributes", "spawn egg", "entity renderer", "entity model", "EntityModelLayer", or "biome spawn rules". Part of the fabric-mc-modding skill family.From its SKILL.md

Install
npx -y skills add PSB1234/Fabric-Minecraft-Skill-1.20.1 --skill fabric-entities

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

10.8 KB, ~2.5k tokens by cl100k_base, as published. Nobody here has run it

Fabric Entities — 1.20.1 Reference


Entity Class Hierarchy — Pick the Right Base

Base ClassUse When
EntityPurely data/logic, not a living creature (e.g. projectile, marker)
LivingEntityHas health, can be damaged, but not a mob
MobEntityAI-controlled creature (base for all mobs)
PathAwareEntityMob that navigates terrain (most mobs)
AnimalEntityPassive animal with breeding
PassiveEntityPassive, no attack
HostileEntityAggressive mob
TameableEntityTameable (wolf/cat pattern)

1. Entity Class

public class MyMobEntity extends PathAwareEntity {

    public MyMobEntity(EntityType<? extends MyMobEntity> type, World world) {
        super(type, world);
    }

    // Register default attributes (health, speed, etc.)
    public static DefaultAttributeContainer.Builder createAttributes() {
        return MobEntity.createMobAttributes()
            .add(EntityAttributes.GENERIC_MAX_HEALTH, 20.0)
            .add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.25)
            .add(EntityAttributes.GENERIC_ATTACK_DAMAGE, 3.0)
            .add(EntityAttributes.GENERIC_FOLLOW_RANGE, 16.0)
            .add(EntityAttributes.GENERIC_ARMOR, 2.0);
    }

    // Configure AI goals
    @Override
    protected void initGoals() {
        // Targeting goals (higher priority = runs first)
        this.targetSelector.add(1, new ActiveTargetGoal<>(this, PlayerEntity.class, true));
        this.targetSelector.add(2, new RevengeGoal(this));

        // Behavior goals
        this.goalSelector.add(1, new SwimGoal(this));
        this.goalSelector.add(2, new MeleeAttackGoal(this, 1.2, false));
        this.goalSelector.add(3, new WanderAroundFarGoal(this, 0.8));
        this.goalSelector.add(4, new LookAtEntityGoal(this, PlayerEntity.class, 8.0f));
        this.goalSelector.add(5, new LookAroundGoal(this));
    }

    // NBT persistence
    @Override
    public void writeCustomDataToNbt(NbtCompound nbt) {
        super.writeCustomDataToNbt(nbt);
        nbt.putBoolean("my_flag", myFlag);
    }

    @Override
    public void readCustomDataFromNbt(NbtCompound nbt) {
        super.readCustomDataFromNbt(nbt);
        myFlag = nbt.getBoolean("my_flag");
    }

    // Entity sounds
    @Override protected SoundEvent getAmbientSound()  { return SoundEvents.ENTITY_ZOMBIE_AMBIENT; }
    @Override protected SoundEvent getHurtSound(DamageSource src) { return SoundEvents.ENTITY_ZOMBIE_HURT; }
    @Override protected SoundEvent getDeathSound()    { return SoundEvents.ENTITY_ZOMBIE_DEATH; }
    @Override protected void playStepSound(BlockPos pos, BlockState state) {
        playSound(SoundEvents.ENTITY_ZOMBIE_STEP, 0.15f, 1.0f);
    }

    private boolean myFlag;
}

2. Register Entity Type

public class ModEntities {
    public static EntityType<MyMobEntity> MY_MOB;

    public static void register() {
        MY_MOB = FabricEntityTypeBuilder.createMob()
            .entityFactory(MyMobEntity::new)
            .defaultAttributes(MyMobEntity::createAttributes)
            .spawnGroup(SpawnGroup.MONSTER)           // MONSTER / CREATURE / AMBIENT / WATER_CREATURE / MISC
            .dimensions(EntityDimensions.fixed(0.6f, 1.95f)) // width, height in blocks
            .build();

        Registry.register(Registries.ENTITY_TYPE,
            new Identifier("mymod", "my_mob"), MY_MOB);
    }
}

Register in onInitialize():

ModEntities.register();
// Also register default attributes:
FabricDefaultAttributeRegistry.register(ModEntities.MY_MOB, MyMobEntity.createAttributes());

3. Entity Model (client-only)

@Environment(EnvType.CLIENT)
public class MyMobModel<T extends MyMobEntity> extends EntityModel<T> {

    public static final ModelLayer MODEL_LAYER =
        new ModelLayer(new Identifier("mymod", "my_mob"), "main");

    private final ModelPart root;
    private final ModelPart head;
    private final ModelPart body;

    public MyMobModel(ModelPart root) {
        this.root = root;
        this.head = root.getChild("head");
        this.body = root.getChild("body");
    }

    // Define the model hierarchy
    public static TexturedModelData getTexturedModelData() {
        ModelData data = new ModelData();
        ModelPartData parts = data.getRoot();

        parts.addChild("head",
            ModelPartBuilder.create()
                .uv(0, 0).cuboid(-4f, -8f, -4f, 8, 8, 8),
            ModelTransform.pivot(0f, 0f, 0f));

        parts.addChild("body",
            ModelPartBuilder.create()
                .uv(16, 16).cuboid(-4f, 0f, -2f, 8, 12, 4),
            ModelTransform.pivot(0f, 0f, 0f));

        return TexturedModelData.of(data, 64, 32);
    }

    @Override
    public void setAngles(T entity, float limbAngle, float limbDistance,
            float animationProgress, float headYaw, float headPitch) {
        head.yaw   = headYaw   * (float)(Math.PI / 180);
        head.pitch = headPitch * (float)(Math.PI / 180);
        // animate limbs for walking:
        body.roll  = (float)Math.sin(limbAngle * 0.6662f) * limbDistance * 0.5f;
    }

    @Override
    public void render(MatrixStack matrices, VertexConsumer vertexConsumer,
            int light, int overlay, float red, float green, float blue, float alpha) {
        root.render(matrices, vertexConsumer, light, overlay, red, green, blue, alpha);
    }
}

4. Entity Renderer (client-only)

@Environment(EnvType.CLIENT)
public class MyMobRenderer extends MobEntityRenderer<MyMobEntity, MyMobModel<MyMobEntity>> {

    private static final Identifier TEXTURE =
        new Identifier("mymod", "textures/entity/my_mob.png");

    public MyMobRenderer(EntityRendererFactory.Context ctx) {
        super(ctx, new MyMobModel<>(ctx.getPart(MyMobModel.MODEL_LAYER)), 0.5f); // shadow radius
        // Add feature renderers (e.g. armor, overlay):
        // addFeature(new MyFeatureRenderer(this));
    }

    @Override
    public Identifier getTexture(MyMobEntity entity) {
        return TEXTURE;
    }
}

Register in onInitializeClient():

// Register model layer
EntityModelLayerRegistry.registerModelLayer(
    MyMobModel.MODEL_LAYER, MyMobModel::getTexturedModelData);

// Register entity renderer
EntityRendererRegistry.register(ModEntities.MY_MOB, MyMobRenderer::new);

5. Spawn Egg Item

// In ModItems.register():
Registry.register(Registries.ITEM,
    new Identifier("mymod", "my_mob_spawn_egg"),
    new SpawnEggItem(ModEntities.MY_MOB,
        0x3B3B3B,   // primary shell color (hex int)
        0xFF5733,   // secondary spot color
        new FabricItemSettings())
);

Add to loot tables / creative tab as needed.


6. Natural Spawning Rules

// In onInitialize() — add spawn rules to existing biomes
BiomeModifications.addSpawn(
    BiomeSelectors.foundInOverworld(),
    SpawnGroup.MONSTER,
    ModEntities.MY_MOB,
    5,    // weight (relative to other mobs)
    1,    // minGroupSize
    3     // maxGroupSize
);

// Set spawn conditions (e.g. only on stone at night)
SpawnRestriction.register(
    ModEntities.MY_MOB,
    SpawnLocationTypes.ON_GROUND,
    Heightmap.Type.MOTION_BLOCKING_NO_LEAVES,
    MobEntity::canMobSpawn   // or custom predicate
);

Custom Goal / AI

public class MyCustomGoal extends Goal {

    private final MyMobEntity mob;
    private int cooldown;

    public MyCustomGoal(MyMobEntity mob) {
        this.mob = mob;
        setControls(EnumSet.of(Control.MOVE, Control.LOOK));
    }

    @Override
    public boolean canStart() {
        return mob.getTarget() != null && cooldown <= 0;
    }

    @Override
    public void start() {
        cooldown = 40;
    }

    @Override
    public void tick() {
        cooldown--;
        LivingEntity target = mob.getTarget();
        if (target != null) {
            mob.getLookControl().lookAt(target, 30f, 30f);
            // custom attack logic...
        }
    }

    @Override
    public boolean shouldContinue() {
        return cooldown > 0 && mob.getTarget() != null;
    }
}

Tracked Data (Synced Fields)

For data that must be visible on the client (e.g. animation state, variant):

public class MyMobEntity extends PathAwareEntity {

    private static final TrackedData<Boolean> ENRAGED =
        DataTracker.registerData(MyMobEntity.class, TrackedDataHandlerRegistry.BOOLEAN);

    @Override
    protected void initDataTracker() {
        super.initDataTracker();
        dataTracker.startTracking(ENRAGED, false);
    }

    public boolean isEnraged() {
        return dataTracker.get(ENRAGED);
    }

    public void setEnraged(boolean enraged) {
        dataTracker.set(ENRAGED, enraged);
    }
}

Common Mistakes

  • FabricDefaultAttributeRegistry.register() missing — causes crash on entity spawn.
  • Model layer not registeredEntityModelLayerRegistry.registerModelLayer() must be called client-side before rendering.
  • Entity not spawning naturally — check BiomeModifications.addSpawn is called and SpawnRestriction allows the block/light conditions.
  • Spawn egg NPE — ensure the entity type is fully registered before creating the SpawnEggItem.
  • Tracked data crashinitDataTracker() must call super first and register all tracked data.

Scripts

ScriptWhat it does
scripts/add_entity.pyScaffold entity class, model, renderer + print registration snippets
python scripts/add_entity.py \
  --mod-id mymod --group com.example \
  --entity-id crystal_golem --name "Crystal Golem" \
  --base PathAwareEntity

References

FileWhen to load
references/ai-goals.mdFull goal class listing (movement, attack, target, look, flee, special goals), goal priority guidelines, and EntityAttributes table

Related Skills

  • fabric-mc-modding — project structure, general registration
  • fabric-rendering — custom renderers and particle effects
  • fabric-mixins — hooking into existing entity logic
  • fabric-datagen — generating lang entries, loot tables for entities

What ships with it: 2 files

15.8 KB alongside SKILL.md, 1 of them executable

references/

scripts/

Keep looking

Skills are one crate of 326,861. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.