create-mekanism-modular/src/main/java/eu/abdelbaki/cmmodular/WaterBreathing.java

68 lines
3.0 KiB
Java

package eu.abdelbaki.cmmodular;
import net.minecraft.core.registries.Registries;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.entity.ai.attributes.Attribute;
import net.minecraft.world.entity.ai.attributes.RangedAttribute;
import net.neoforged.bus.api.EventPriority;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.entity.EntityAttributeModificationEvent;
import net.neoforged.neoforge.event.entity.living.LivingBreatheEvent;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredRegister;
/**
* Sea serpent fang armour lets its wearer breathe underwater, which is what Ice
* and Fire's own Tide Guardian armour does and the only reason to hunt the
* thing.
*
* <p>There is no attribute for it and MIAPI has no property for it either - the
* closest data can get is a fake Respiration enchantment, which only postpones
* drowning. So this follows the pattern {@link FireImmunity} and
* {@link VacuumSeal} already set: an attribute of this mod's own that the
* material grants like any other, and a listener here that watches for it.
*
* <p>Half a lung per module, as with {@link VacuumSeal}: the fang grants 0.5 in
* each armour slot and nothing in hand, so it takes two worn pieces of it -
* two sockets, two pieces built of it, or a socketed piece that is both - to
* breathe, and a fang weapon breathes not at all. What a fang is worth in hand
* is {@link WaterCombat}'s.
*
* <p>It answers the same event {@link VacuumSeal} does but only underwater, so
* a fang is a fang and not half a spacesuit.
*/
public final class WaterBreathing {
private static final DeferredRegister<Attribute> ATTRIBUTES =
DeferredRegister.create(Registries.ATTRIBUTE, CMModular.MOD_ID);
/** At or above 1 the bearer never drowns; each worn fang module is 0.5. */
public static final DeferredHolder<Attribute, Attribute> WATER_BREATHING =
ATTRIBUTES.register("water_breathing", id -> new RangedAttribute(
"attribute.cmmodular.water_breathing", 0.0D, 0.0D, 1.0D).setSyncable(true));
private WaterBreathing() {
}
static void register(IEventBus modBus) {
ATTRIBUTES.register(modBus);
modBus.addListener(WaterBreathing::attachToEntities);
// Last, so it answers after whatever said there was no air.
NeoForge.EVENT_BUS.addListener(EventPriority.LOWEST, WaterBreathing::onBreathe);
}
/** Attributes only exist on an entity if they were added to its type. */
private static void attachToEntities(EntityAttributeModificationEvent event) {
event.getTypes().forEach(type -> event.add(type, WATER_BREATHING));
}
private static void onBreathe(LivingBreatheEvent event) {
if (event.canBreathe() || !event.getEntity().isEyeInFluid(FluidTags.WATER)) {
return;
}
if (EquipmentAttributes.value(event.getEntity(), WATER_BREATHING) >= 1.0D) {
event.setCanBreathe(true);
}
}
}