// Path: src/main/java/tc/oc/tracker/DamageAPI.java
// public final class DamageAPI {
//     private DamageAPI() { }
// 
//     /**
//      * Inflicts the given damage on an entity.
//      *
//      * This method will call the appropriate damage method and fire an {@link EntityDamageEvent}.
//      *
//      * @param entity Entity to inflict damage upon
//      * @param damage Amount of half-hearts of damage to inflict
//      * @param info {@link DamageInfo} object that details the type of damage
//      * @return the final {@link Damage} object (never null)
//      *
//      * @throws NullPointerException if entity or info is null
//      * @throws IllegalArgumentExcpetion if hearts is less than zero
//      */
//     public static @Nonnull Damage inflictDamage(@Nonnull LivingEntity entity, int damage, @Nonnull DamageInfo info) {
//         Preconditions.checkNotNull(entity, "living entity");
//         Preconditions.checkArgument(damage >= 0, "damage must be greater than or equal to zero");
//         Preconditions.checkNotNull(info, "damage info");
// 
//         DamageAPIHelper helper = DamageAPIHelper.get();
// 
//         EntityDamageEvent event = new EntityDamageEvent(entity, DamageCause.CUSTOM, damage);
//         helper.setEventDamageInfo(event, info);
// 
//         Bukkit.getPluginManager().callEvent(event);
// 
//         if(event.isCancelled()) {
//             return null;
//         }
// 
//         entity.damage(event.getDamage());
// 
//         helper.setEventDamageInfo(event, null);
// 
//         return helper.getOurEvent(event).toDamageObject();
//     }
// }
// 
// Path: src/main/java/tc/oc/tracker/DamageInfo.java
// public interface DamageInfo {
//     /**
//      * Gets the living entity most responsible for this damage.
//      *
//      * @return Resolved damager or null if none exists
//      */
//     @Nullable LivingEntity getResolvedDamager();
// }
// 
// Path: src/main/java/tc/oc/tracker/damage/resolvers/DamageAPIResolver.java
// public class DamageAPIResolver implements DamageResolver {
//     /** @see DamageResolvers#resolve */
//     public @Nullable DamageInfo resolve(@Nonnull LivingEntity entity, @Nonnull Lifetime lifetime, @Nonnull EntityDamageEvent damageEvent) {
//         return DamageAPIHelper.get().getEventDamageInfo(damageEvent);
//     }
// 
//     static {
//         DamageResolvers.getManager().register(new DamageAPIResolver());
//     }
// }
// 
// Path: src/main/java/tc/oc/tracker/event/EntityDamageEvent.java
// public class EntityDamageEvent extends Event implements Cancellable {
//     private final @Nonnull LivingEntity entity;
//     private final @Nonnull Lifetime lifetime;
//     private int damage;
//     private final @Nonnull Location location;
//     private final @Nonnull Instant time;
//     private final @Nonnull DamageInfo info;
//     private boolean cancelled = false;
// 
//     public EntityDamageEvent(@Nonnull LivingEntity entity, @Nonnull Lifetime lifetime, int damage, @Nonnull Location location, @Nonnull Instant time, @Nonnull DamageInfo info) {
//         Preconditions.checkNotNull(entity, "entity");
//         Preconditions.checkNotNull(lifetime, "lifetime");
//         Preconditions.checkArgument(damage >= 0, "damage must be greater than or equal to zero");
//         Preconditions.checkNotNull(location, "location");
//         Preconditions.checkNotNull(time, "time");
//         Preconditions.checkNotNull(info, "damage info");
// 
//         this.entity = entity;
//         this.lifetime = lifetime;
//         this.damage = damage;
//         this.location = location.clone();
//         this.time = time;
//         this.info = info;
//     }
// 
//     public @Nonnull LivingEntity getEntity() {
//         return this.entity;
//     }
// 
//     public @Nonnull Lifetime getLifetime() {
//         return this.lifetime;
//     }
// 
//     public int getDamage() {
//         return this.damage;
//     }
// 
//     public void setDamage(int damage) {
//         Preconditions.checkArgument(damage >= 0, "damage must be greater than or equal to zero");
// 
//         this.damage = damage;
//     }
// 
//     public @Nonnull Location getLocation() {
//         return this.location;
//     }
// 
//     public @Nonnull Instant getTime() {
//         return this.time;
//     }
// 
//     public @Nonnull DamageInfo getInfo() {
//         return this.info;
//     }
// 
//     public @Nonnull Damage toDamageObject() {
//         return new SimpleDamage(this.damage, this.location, this.time, this.info);
//     }
// 
//     public boolean isCancelled() {
//         return this.cancelled;
//     }
// 
//     public void setCancelled(boolean cancel) {
//         this.cancelled = cancel;
//     }
// 
//     // Bukkit event junk
//     public static final HandlerList handlers = new HandlerList();
// 
//     @Override
//     public HandlerList getHandlers() {
//         return handlers;
//     }
// 
//     public static HandlerList getHandlerList() {
//         return handlers;
//     }
// }


import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import tc.oc.tracker.DamageAPI;
import tc.oc.tracker.DamageInfo;
import tc.oc.tracker.damage.resolvers.DamageAPIResolver;
import tc.oc.tracker.event.EntityDamageEvent;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
package tc.oc.tracker.plugin;





/**
 * Helper class for the {@link DamageAPI} and Tracker plugin to properly handle
 * damage inflicted through the API.
 *
 * Class is intended for internal use only. Methods are not guaranteed to
 * respect versioning contract.
 */
public final class DamageAPIHelper {
    /**
     * Gets the singleton DamageAPIHelper instance.
     *
     * @return DamageAPIHelper instance (never null)
     */
    public static @Nonnull DamageAPIHelper get() {
        return inst;
    }
    private static final @Nonnull DamageAPIHelper inst = new DamageAPIHelper();

    /**
     * Fetches the given {@link DamageInfo} object specified by
     * {@link DamageAPI#inflictDamage} so it can be fetched by the
     * {@link DamageAPIResolver} when plugins who listen to the Bukkit event
     * ask for it.
     *
     * @param event EntityDamageEvent to fetch the given damage for
     * @return Stored damage info or null if none is stored
     *
     * @throws NullPointerException if event is null
     */
// Path: src/main/java/tc/oc/tracker/DamageAPI.java
// public final class DamageAPI {
//     private DamageAPI() { }
// 
//     /**
//      * Inflicts the given damage on an entity.
//      *
//      * This method will call the appropriate damage method and fire an {@link EntityDamageEvent}.
//      *
//      * @param entity Entity to inflict damage upon
//      * @param damage Amount of half-hearts of damage to inflict
//      * @param info {@link DamageInfo} object that details the type of damage
//      * @return the final {@link Damage} object (never null)
//      *
//      * @throws NullPointerException if entity or info is null
//      * @throws IllegalArgumentExcpetion if hearts is less than zero
//      */
//     public static @Nonnull Damage inflictDamage(@Nonnull LivingEntity entity, int damage, @Nonnull DamageInfo info) {
//         Preconditions.checkNotNull(entity, "living entity");
//         Preconditions.checkArgument(damage >= 0, "damage must be greater than or equal to zero");
//         Preconditions.checkNotNull(info, "damage info");
// 
//         DamageAPIHelper helper = DamageAPIHelper.get();
// 
//         EntityDamageEvent event = new EntityDamageEvent(entity, DamageCause.CUSTOM, damage);
//         helper.setEventDamageInfo(event, info);
// 
//         Bukkit.getPluginManager().callEvent(event);
// 
//         if(event.isCancelled()) {
//             return null;
//         }
// 
//         entity.damage(event.getDamage());
// 
//         helper.setEventDamageInfo(event, null);
// 
//         return helper.getOurEvent(event).toDamageObject();
//     }
// }
// 
// Path: src/main/java/tc/oc/tracker/DamageInfo.java
// public interface DamageInfo {
//     /**
//      * Gets the living entity most responsible for this damage.
//      *
//      * @return Resolved damager or null if none exists
//      */
//     @Nullable LivingEntity getResolvedDamager();
// }
// 
// Path: src/main/java/tc/oc/tracker/damage/resolvers/DamageAPIResolver.java
// public class DamageAPIResolver implements DamageResolver {
//     /** @see DamageResolvers#resolve */
//     public @Nullable DamageInfo resolve(@Nonnull LivingEntity entity, @Nonnull Lifetime lifetime, @Nonnull EntityDamageEvent damageEvent) {
//         return DamageAPIHelper.get().getEventDamageInfo(damageEvent);
//     }
// 
//     static {
//         DamageResolvers.getManager().register(new DamageAPIResolver());
//     }
// }
// 
// Path: src/main/java/tc/oc/tracker/event/EntityDamageEvent.java
// public class EntityDamageEvent extends Event implements Cancellable {
//     private final @Nonnull LivingEntity entity;
//     private final @Nonnull Lifetime lifetime;
//     private int damage;
//     private final @Nonnull Location location;
//     private final @Nonnull Instant time;
//     private final @Nonnull DamageInfo info;
//     private boolean cancelled = false;
// 
//     public EntityDamageEvent(@Nonnull LivingEntity entity, @Nonnull Lifetime lifetime, int damage, @Nonnull Location location, @Nonnull Instant time, @Nonnull DamageInfo info) {
//         Preconditions.checkNotNull(entity, "entity");
//         Preconditions.checkNotNull(lifetime, "lifetime");
//         Preconditions.checkArgument(damage >= 0, "damage must be greater than or equal to zero");
//         Preconditions.checkNotNull(location, "location");
//         Preconditions.checkNotNull(time, "time");
//         Preconditions.checkNotNull(info, "damage info");
// 
//         this.entity = entity;
//         this.lifetime = lifetime;
//         this.damage = damage;
//         this.location = location.clone();
//         this.time = time;
//         this.info = info;
//     }
// 
//     public @Nonnull LivingEntity getEntity() {
//         return this.entity;
//     }
// 
//     public @Nonnull Lifetime getLifetime() {
//         return this.lifetime;
//     }
// 
//     public int getDamage() {
//         return this.damage;
//     }
// 
//     public void setDamage(int damage) {
//         Preconditions.checkArgument(damage >= 0, "damage must be greater than or equal to zero");
// 
//         this.damage = damage;
//     }
// 
//     public @Nonnull Location getLocation() {
//         return this.location;
//     }
// 
//     public @Nonnull Instant getTime() {
//         return this.time;
//     }
// 
//     public @Nonnull DamageInfo getInfo() {
//         return this.info;
//     }
// 
//     public @Nonnull Damage toDamageObject() {
//         return new SimpleDamage(this.damage, this.location, this.time, this.info);
//     }
// 
//     public boolean isCancelled() {
//         return this.cancelled;
//     }
// 
//     public void setCancelled(boolean cancel) {
//         this.cancelled = cancel;
//     }
// 
//     // Bukkit event junk
//     public static final HandlerList handlers = new HandlerList();
// 
//     @Override
//     public HandlerList getHandlers() {
//         return handlers;
//     }
// 
//     public static HandlerList getHandlerList() {
//         return handlers;
//     }
// }


// Path: src/main/java/tc/oc/tracker/plugin/DamageAPIHelper.java
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import tc.oc.tracker.DamageAPI;
import tc.oc.tracker.DamageInfo;
import tc.oc.tracker.damage.resolvers.DamageAPIResolver;
import tc.oc.tracker.event.EntityDamageEvent;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;

package tc.oc.tracker.plugin;





/**
 * Helper class for the {@link DamageAPI} and Tracker plugin to properly handle
 * damage inflicted through the API.
 *
 * Class is intended for internal use only. Methods are not guaranteed to
 * respect versioning contract.
 */
public final class DamageAPIHelper {
    /**
     * Gets the singleton DamageAPIHelper instance.
     *
     * @return DamageAPIHelper instance (never null)
     */
    public static @Nonnull DamageAPIHelper get() {
        return inst;
    }
    private static final @Nonnull DamageAPIHelper inst = new DamageAPIHelper();

    /**
     * Fetches the given {@link DamageInfo} object specified by
     * {@link DamageAPI#inflictDamage} so it can be fetched by the
     * {@link DamageAPIResolver} when plugins who listen to the Bukkit event
     * ask for it.
     *
     * @param event EntityDamageEvent to fetch the given damage for
     * @return Stored damage info or null if none is stored
     *
     * @throws NullPointerException if event is null
     */
    public @Nullable DamageInfo getEventDamageInfo(@Nonnull org.bukkit.event.entity.EntityDamageEvent event) {