package choonster.testmod3.capability.maxhealth; import choonster.testmod3.Logger; import choonster.testmod3.TestMod3; import choonster.testmod3.api.capability.maxhealth.IMaxHealth; import choonster.testmod3.capability.CapabilityProviderSerializable; import choonster.testmod3.util.CapabilityUtils; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagFloat; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.CapabilityInject; import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.event.AttachCapabilitiesEvent; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerChangedDimensionEvent; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.MarkerManager; import javax.annotation.Nullable; /** * Capability for {@link IMaxHealth}. * * @author Choonster */ public final class CapabilityMaxHealth { /** * The {@link Capability} instance. */ @CapabilityInject(IMaxHealth.class) public static final Capability<IMaxHealth> MAX_HEALTH_CAPABILITY = null; /** * The default {@link EnumFacing} to use for this capability. */ public static final EnumFacing DEFAULT_FACING = null; /** * The ID of this capability. */ public static final ResourceLocation ID = new ResourceLocation(TestMod3.MODID, "MaxHealth"); public static final Marker LOG_MARKER = MarkerManager.getMarker("MaxHealth", Logger.MOD_MARKER); public static void register() { CapabilityManager.INSTANCE.register(IMaxHealth.class, new Capability.IStorage<IMaxHealth>() { @Override public NBTBase writeNBT(final Capability<IMaxHealth> capability, final IMaxHealth instance, final EnumFacing side) { return new NBTTagFloat(instance.getBonusMaxHealth()); } @Override public void readNBT(final Capability<IMaxHealth> capability, final IMaxHealth instance, final EnumFacing side, final NBTBase nbt) { instance.setBonusMaxHealth(((NBTTagFloat) nbt).getFloat()); } }, () -> new MaxHealth(null)); } /** * Get the {@link IMaxHealth} from the specified entity. * * @param entity The entity * @return The IMaxHealth */ @Nullable public static IMaxHealth getMaxHealth(final EntityLivingBase entity) { return CapabilityUtils.getCapability(entity, MAX_HEALTH_CAPABILITY, DEFAULT_FACING); } /** * Create a provider for the specified {@link IMaxHealth} instance. * * @param maxHealth The IMaxHealth * @return The provider */ public static ICapabilityProvider createProvider(final IMaxHealth maxHealth) { return new CapabilityProviderSerializable<>(MAX_HEALTH_CAPABILITY, DEFAULT_FACING, maxHealth); } /** * Format a max health value. * * @param maxHealth The max health value * @return The formatted text. */ public static String formatMaxHealth(final float maxHealth) { return ItemStack.DECIMALFORMAT.format(maxHealth); } /** * Event handler for the {@link IMaxHealth} capability. */ @SuppressWarnings("unused") @Mod.EventBusSubscriber private static class EventHandler { /** * Attach the {@link IMaxHealth} capability to all living entities. * * @param event The event */ @SubscribeEvent public static void attachCapabilities(final AttachCapabilitiesEvent<Entity> event) { if (event.getObject() instanceof EntityLivingBase) { final MaxHealth maxHealth = new MaxHealth((EntityLivingBase) event.getObject()); event.addCapability(ID, createProvider(maxHealth)); } } /** * Copy the player's bonus max health when they respawn after dying or returning from the end. * * @param event The event */ @SubscribeEvent public static void playerClone(final PlayerEvent.Clone event) { final IMaxHealth oldMaxHealth = getMaxHealth(event.getOriginal()); final IMaxHealth newMaxHealth = getMaxHealth(event.getEntityPlayer()); if (newMaxHealth != null && oldMaxHealth != null) { newMaxHealth.setBonusMaxHealth(oldMaxHealth.getBonusMaxHealth()); } } /** * Synchronise a player's max health to watching clients when they change dimensions. * * @param event The event */ @SubscribeEvent public static void playerChangeDimension(final PlayerChangedDimensionEvent event) { final IMaxHealth maxHealth = getMaxHealth(event.player); if (maxHealth != null) { maxHealth.synchronise(); } } } }