Skip to content

Using the API

Crystal Spider edited this page Dec 11, 2024 · 12 revisions

Fire Type

Since Fire Types are so important to identify Fires, there are several utilities in FireManager to handle them.
You can retrieve the list of all the registered ones, the list of all Fire Ids, or the list of all Mod Ids.
Similarly, there are methods to check whether a Fire Type/Fire Id/Mod Id are valid (correctly formatted) or registered within the API.
Finally, you can use FireManager#sanitize to make sure the Fire Type you pass is valid (returns FireManager#DEFAULT_FIRE_TYPE if not), or FireManager#ensure to also enforce the Fire Type is registered.

Ignite and Douse

All base cases are handled by this mod once a Fire is registered, for example you don't have to worry about setting an entity on fire when it goes into your fire source block.

However you may wish to set on a specific kind of fire a certain entity in a different situation from the base ones, for example with Torch hit! torch hits represent a new use case where handling setting on fire is needed.
To set on fire an entity while keeping this mod features you just need to call FireManager.setOnFire(Entity, float, ResourceLocation) passing it the entity you wish to set on fire, the amount of seconds the fire should last for and the Fire Type of the registered Fire.
Before Minecraft 1.21, the signature of that method was FireManager.setOnFire(Entity, int, ResourceLocation).

Removing any kind of fire from any entity is as easy as using base Minecraft method Entity.clearFire().

Hurting and Healing

There are 2 ways to hurt/heal an entity with your custom Fire:

  1. Set the entity on fire as explained above and let the mod handle the rest.
  2. Using FireManager.

Since 1.21

To hurt/heal an entity explicitly with FireManager there is a single method: FireManager#affect(Entity, ResourceLocation, BiFunction<Fire, Entity, DamageSource>).
The correct way to use it is to pass the entity you want to affect (hurt/heal), the Fire Type, and one of the Fire damage source getters. For example:

/**
 * This will affect the entity with the effects of the Fire identified by CUSTOM_FIRE_TYPE and using its "in fire" DamageSource.
 * THe provided DamageSource will be used only if the Fire actually hurts the entity.
 */
FireManager.affect(entity, CUSTOM_FIRE_TYPE, Fire::getInFire);

Before 1.21

Since there were only 2 possible damage sources, instead of having a single method to affect an entity there were 2:

  • FireManager.damageInFire(Entity, ResourceLocation).
  • FireManager.damageOnFire(Entity, ResourceLocation).

The only difference between damageInFire and damageOnFire is the use context:
damageInFire should be used when the entity is taking damage because it's inside or above a block considered as a fire source, like a campfire or a Fire block, while damageOnFire should be used when an entity is burning.
The API will take care of using the proper DamageSource, damage and choosing between hurting or healing.
You just need to pass to those methods the Entity you wish to hurt/heal and the Fire Type, and everything will work accordingly to the configuration of the registered Fire!

Fire Behavior

Fire Behaviors are a way to apply custom logic when an entity gets affected by your Fire.
Right before an entity is hurt or healed by your Fire, the custom behavior is applied.
A Fire Behavior returns a boolean that determines whether the default hurt/heal behavior should still apply.

Teleporting behavior example
// Registering your custom Fire.
public static final Fire CUSTOM_FIRE = FireManager.registerFire(FireManager.fireBuilder(CUSTOM_FIRE_TYPE)
  .setBehavior(entity -> {
    // This check determines whether to apply the behavior. The check is custom for this behavior example, change it to suit your needs.
    // Since 1.21.3, Fire behaviors are called server side only, so the check !livingEntity.level().isClientSide() would be redundant.
    if (entity.isOnFire() && entity instanceof LivingEntity livingEntity && !livingEntity.level().isClientSide()) {
      // The code below is essentially copy-pasted from the Chorus Fruit teleporting logic.
      Level level = livingEntity.level();
      for (int i = 0; i < 16; ++i) {
        double nextX = livingEntity.getX() + (livingEntity.getRandom().nextDouble() - 0.5) * 16.0;
        double nextY = Mth.clamp(livingEntity.getY() + (double) (livingEntity.getRandom().nextInt(16) - 8), level.getMinBuildHeight(), (level.getMinBuildHeight() + ((ServerLevel) level).getLogicalHeight() - 1));
        double nextZ = livingEntity.getZ() + (livingEntity.getRandom().nextDouble() - 0.5) * 16.0;
        if (livingEntity.isPassenger()) {
          livingEntity.stopRiding();
        }
        Vec3 position = livingEntity.position();
        if (livingEntity.randomTeleport(nextX, nextY, nextZ, true)) {
          level.gameEvent(GameEvent.TELEPORT, position, GameEvent.Context.of(livingEntity));
          SoundEvent soundEvent;
          SoundSource soundSource;
          if (livingEntity instanceof Fox) {
            soundEvent = SoundEvents.FOX_TELEPORT;
            soundSource = SoundSource.NEUTRAL;
          } else {
            soundEvent = SoundEvents.CHORUS_FRUIT_TELEPORT;
            soundSource = SoundSource.PLAYERS;
          }
          level.playSound(null, livingEntity.getX(), livingEntity.getY(), livingEntity.getZ(), soundEvent, soundSource);
          livingEntity.resetFallDistance();
          break;
        }
      }
    }
    // The return value can be omitted if true, if false it must be explicitly stated.
  })
  // Optionally change other Fire properties to suit your needs.
  .build()
);

Retrieving Fire Properties

There are two ways to retrieve Fire Property values:

  • getProperty(ResourceLocation, Function<Fire, T>):
    Takes in a Fire Type and a Fire property getter and returns the value.
    If no Fire is registered with the given Fire Type, returns the default value for that property.
    Use example:

    float damage = FireManager.getProperty(CUSTOM_FIRE_TYPE, Fire::getDamage);
  • getPropertyList(Function<Fire, T>):
    Takes in a Fire property getter and returns the list of the property values from all registered Fires.

Retrieving Fire Components

There are several ways to work with Fire Components.

For methods that require a Fire Type, the default will be the Vanilla Fire if no specific Fire is registered with the provided Fire Type.
Furthermore, in this section, type generic definitions and return values are included in the method signatures for clarity, unlike other parts of this wiki.

  • <R, T extends R> T getComponent(ResourceLocation fireType, Fire.Component<R, T> component):
    Retrieves from the Fire the value associated with the specified component, or null if the specified component is not mapped for the Fire.
    For example, calling it with Fire.Component#SOURCE_BLOCK will return the Block instance for the fire source block.

  • <R, T extends R> T getRequiredComponent(ResourceLocation fireType, Fire.Component<R, T> component):
    Same as the method above, but will throw a NullPointerException if the specified component is not mapped for the Fire.

  • ResourceLocation getComponentId(ResourceLocation fireType, Fire.Component<?, ?> component):
    Retrieves from the Fire the ID (ResourceLocation) of the specified component, or null if the specified component is not mapped for the Fire.
    For example, calling it with Fire.Component#SOURCE_BLOCK will return the ID (ResourceLocation) of the fire source block.

  • String getComponentPath(ResourceLocation fireType, Fire.Component<?, ?> component):
    Same as the method above, but retrieves only the path of the ID.

  • List<ResourceLocation> getComponentIdList(Fire.Component<?, ?> component):
    Returns the list of the Fire Component IDs from all registered Fires.

  • <R, T extends R> List<T> getComponentList(Fire.Component<R, T> component):
    Returns the list of the Fire Component values from all registered Fires.

Retrieving Damage Sources

Since 1.21

To retrieve any Fire DamageSource there is a single, simple method to call:
getDamageSource(Entity, ResourceLocation, BiFunction<Fire, Entity, DamageSource>).
It takes the entity to retrieve the damage source from, a Fire Type, and a Fire damage source getter.
Returns the damage source value for that Fire or the default one if no Fire was registered with the given Fire Type. Use example:

DamageSource source = FireManager.getDamageSource(entity, CUSTOM_FIRE_TYPE, Fire::getInFire);

Before 1.21

There are two methods:

  • getInFireDamageSourceFor(Entity, ResourceLocation)
  • getOnFireDamageSourceFor(Entity, ResourceLocation)

Both take in the entity to retrieve the damage source from and a Fire Type.
They return the "in fire"/"on fire" DamageSource of the Fire registered with the given Fire Type.
Returns the damage source value for that Fire or the default one if no Fire was registered with the given Fire Type.

Handling NBTs

There is an NBT to save and load the Fire Type on entities: FireManager#FIRE_TYPE_TAG.

There are two methods used to write and read a Fire Type from NBTs:

  • writeNbt(CompoundTag, ResourceLocation):
    Writes to an NBT the given Fire Type.

  • readNbt(CompoundTag):
    Reads a Fire Type from the given NBT.