Skip to content

Architecture

Better Ecology uses a data-driven architecture for vanilla mob behavior modification with minimal per-mob code. All behavior derives from YAML/JSON profiles and archetypes, compiled once on reload, and dispatched through unified hooks.

Design Principles

  1. Single source of truth: YAML profiles and archetypes
  2. Minimal mixins: One Mob mixin plus one Animal mixin
  3. Handle-based systems: Each subsystem is a handle that enables itself via config
  4. Performance: Parse once, cache aggressively, avoid per-tick heavy work

Data Layout

File Locations

Type Path
Base template data/better-ecology/templates/mod_registry.yaml
Mob profiles data/<namespace>/mobs/**/<mob>.yaml or .yml
Archetypes data/<namespace>/archetypes/<path>.yaml

Profile Structure

Profiles can include archetypes for reusable behavior templates:

archetypes:
  - "better-ecology:passive/grazer"
  - "better-ecology:herd/diurnal"

Merge Rules

Order: base template -> archetypes (in listed order) -> mob profile

Overlay Semantics: - null does not override - Empty list does not override - Non-empty list replaces - Maps merge recursively

If identity.mob_id is missing or invalid, the profile is skipped with a warning.

Runtime Flow

1. Reload Phase

  1. EcologyResourceReloader reads YAMLs on datapack reload
  2. Builds EcologyProfile objects
  3. EcologyProfileRegistry.reload() stores profiles, resolves handles, increments generation

2. Entity Lifecycle

  1. MobEcologyMixin attaches EcologyComponent to every Mob
  2. Goal registration: EcologyHooks.onRegisterGoals() (idempotent)
  3. Tick: EcologyHooks.onTick()
  4. NBT: EcologyHooks.onSave() / EcologyHooks.onLoad()

3. Food Checks

AnimalEcologyMixin redirects Animal.mobInteract isFood check to EcologyHooks.overrideIsFood(...)

Core Classes

Class Purpose
EcologyProfile Merged map with typed getters and cached values
EcologyMerge Deep merge with null/empty list rules
EcologyProfileLoader Reads base, profiles, archetypes; normalizes YAML
EcologyProfileRegistry Profile map, handle cache, generation counter
EcologyComponent Per-mob cache, handle NBT tags, goal registration flag
EcologyHandle System interface (goals, tick, NBT, food override)
EcologyHandleRegistry Register and resolve handles per profile
EcologyHooks Mixin dispatch for lifecycle, NBT, food override
EcologyResourceReloader Fabric resource reload listener
EcologyBootstrap Registers handles and reload listener
EcologyAccess Mixin-access interface for component access
AnimalItemStorage Shared component for animals that carry items

Mixins

MobEcologyMixin

Inject Points: - <init> after registerGoals() call - registerGoals tail (secondary safeguard) - tick tail - addAdditionalSaveData tail - readAdditionalSaveData tail

Rationale: Many mobs override registerGoals() without calling super, so the constructor hook is the only universal point. The hook is idempotent to avoid double registration.

AnimalEcologyMixin

Redirect: - Animal.mobInteract call to isFood(ItemStack) -> EcologyHooks.overrideIsFood(...)

NBT Format

Root key: BetterEcology

Per-handle format:

BetterEcology.<handle_id> -> CompoundTag

Each handle reads/writes only its own tag.

Handle Model

Each handle: 1. supports(profile) - Checks if config fields are present 2. registerGoals() - Adds vanilla goals using config values 3. tick() - Updates internal state or performs actions 4. readNbt()/writeNbt() - Persists handle state

Example: DietHandle

Reads: - player_interaction.player_breeding.items - diet.food_sources.primary entries with type: ITEM

Supports: - Item IDs and tags (#tag) - Caches item and tag sets per profile - overrideIsFood() returns true when stack matches

Performance Guardrails

  • No YAML parsing during tick
  • Profile caches per reload
  • Handle caches per profile
  • Use interval ticks for expensive logic

Dependencies

  • SnakeYAML (org.yaml:snakeyaml)
  • Fabric API resource reload listener

Source Reference

Key Minecraft classes: - Mob.java - registerGoals, tick, NBT - Animal.java - mobInteract, isFood - ResourceManager.java - Resource loading

See Also