protected void processGravity(SimpleGravityKillTracker gravity, PlayerDeath death) {
    Player p = death.getVictim();

    if (gravity.attacks.containsKey(p)) {
      Attack attack = gravity.attacks.remove(p);
      if (gravity.wasAttackFatal(attack, death.getCause(), 200)) {
        EntityDamageEvent.DamageCause damageCause = death.getCause();

        death.setAction(DeathMessageUtils.getCauseOfAttack(attack.cause));
        death.setFrom(DeathMessageUtils.getWhereFrom(attack.from));
        death.setTo(DeathMessageUtils.getWhereTo(attack.from, damageCause));
        death.setKiller(attack.attacker);
      }
    }
  }
  @Override
  public void onEnable() {
    // basic operation listeners
    this.registerEvents(new LifetimeListener());
    this.registerEvents(new WorldListener(Trackers.getManager()));

    EntityDamageEventListener damageEventListener = new EntityDamageEventListener();
    damageEventListener.register(this);

    // initialize timer
    this.tickTimer = new TickTimer(this);
    this.tickTimer.start();

    // tracker setup
    TrackerManager tm = Trackers.getManager();

    ExplosiveTracker explosiveTracker = new SimpleExplosiveTracker();
    SimpleGravityKillTracker gravityKillTracker =
        new SimpleGravityKillTracker(this, this.tickTimer);

    explosiveTracker.enable();
    gravityKillTracker.enable();

    this.registerEvents(new ExplosiveListener(explosiveTracker));
    this.registerEvents(new GravityListener(this, gravityKillTracker, this.tickTimer));

    tm.setTracker(ExplosiveTracker.class, explosiveTracker);
    tm.setTracker(SimpleGravityKillTracker.class, gravityKillTracker);

    DispenserTracker dispenserTracker = new SimpleDispenserTracker();
    dispenserTracker.enable();

    this.registerEvents(new DispenserListener(dispenserTracker));
    tm.setTracker(DispenserTracker.class, dispenserTracker);

    ProjectileDistanceTracker projectileDistanceTracker = new SimpleProjectileDistanceTracker();
    projectileDistanceTracker.enable();

    this.registerEvents(new ProjectileDistanceListener(projectileDistanceTracker));
    tm.setTracker(ProjectileDistanceTracker.class, projectileDistanceTracker);

    OwnedMobTracker ownedMobTracker = new SimpleOwnedMobTracker();
    ownedMobTracker.enable();

    this.registerEvents(new OwnedMobListener(ownedMobTracker));
    tm.setTracker(OwnedMobTracker.class, ownedMobTracker);

    AnvilTracker anvilTracker = new SimpleAnvilTracker();
    anvilTracker.enable();

    this.registerEvents(new AnvilListener(anvilTracker));
    tm.setTracker(AnvilTracker.class, anvilTracker);

    // register damage resolvers
    DamageResolverManager drm = DamageResolvers.getManager();

    drm.register(new BlockDamageResolver());
    drm.register(new FallDamageResolver());
    drm.register(new LavaDamageResolver());
    drm.register(new MeleeDamageResolver());
    drm.register(new ProjectileDamageResolver(projectileDistanceTracker));
    drm.register(new TNTDamageResolver(explosiveTracker, dispenserTracker));
    drm.register(new VoidDamageResolver());
    drm.register(new GravityDamageResolver(gravityKillTracker, this.tickTimer));
    drm.register(
        new DispensedProjectileDamageResolver(projectileDistanceTracker, dispenserTracker));
    drm.register(new OwnedMobDamageResolver(ownedMobTracker));
    drm.register(new AnvilDamageResolver(anvilTracker));

    // debug
    // this.registerEvents(new DebugListener());
  }