/** notify all observers */
  public void notifyObservers(ObserverType type, Object... object) {
    List<ActionObserver> tempOnceused = Collections.emptyList();
    lock.lock();
    try {
      if (onceUsedObservers.size() > 0) {
        tempOnceused = new ArrayList<ActionObserver>();
        Iterator<ActionObserver> iterator = onceUsedObservers.iterator();
        while (iterator.hasNext()) {
          ActionObserver observer = iterator.next();
          if (observer.getObserverType().matchesObserver(type)) {
            if (observer.tryUse()) {
              tempOnceused.add(observer);
              iterator.remove();
            }
          }
        }
      }
    } finally {
      lock.unlock();
    }

    // notify outside of lock
    for (ActionObserver observer : tempOnceused) {
      notifyAction(type, observer, object);
    }

    if (observers.size() > 0) {
      for (ActionObserver observer : observers) {
        if (observer.getObserverType().matchesObserver(type)) {
          notifyAction(type, observer, object);
        }
      }
    }
  }
 /**
  * Once used observer add to observerController. If observer notify will be removed.
  *
  * @param observer
  */
 public void attach(ActionObserver observer) {
   observer.makeOneTimeUse();
   lock.lock();
   try {
     onceUsedObservers.add(observer);
   } finally {
     lock.unlock();
   }
 }
 private void notifyAction(ObserverType type, ActionObserver observer, Object... object) {
   switch (type) {
     case ATTACK:
       observer.attack((Creature) object[0]);
       break;
     case ATTACKED:
       observer.attacked((Creature) object[0]);
       break;
     case DEATH:
       observer.died((Creature) object[0]);
       break;
     case EQUIP:
       observer.equip((Item) object[0], (Player) object[1]);
       break;
     case UNEQUIP:
       observer.unequip((Item) object[0], (Player) object[1]);
       break;
     case MOVE:
       observer.moved();
       break;
     case SKILLUSE:
       observer.skilluse((Skill) object[0]);
       break;
     case DOT_ATTACKED:
       observer.dotattacked((Creature) object[0], (Effect) object[1]);
       break;
     case ITEMUSE:
       observer.itemused((Item) object[0]);
       break;
     case NPCDIALOGREQUEST:
       observer.npcdialogrequested((Npc) object[0]);
       break;
     case ABNORMALSETTED:
       observer.abnormalsetted((AbnormalState) object[0]);
       break;
     case SUMMONRELEASE:
       observer.summonrelease();
       break;
   }
 }