// MorgenGrauen MUDlib
//
// thing/moving.c -- object moving
//
// $Id: moving.c 8892 2014-08-04 19:48:28Z Zesstra $

#pragma strict_types
#pragma save_types
#pragma range_check
#pragma no_clone

#include <defines.h>
#include <moving.h>
#include <properties.h>
#define NEED_PROTOTYPES
#include <thing/properties.h>

// Das Objekt bewegen.
// Rueckgabe 1 ist Erfolg, <=0 ist Fehler

// a) P_NODROP/P_NOGET-Behandlung.
// b) zum Ueberschreiben
protected int PreventMove(object dest, object oldenv, int method) {
  int tmp;
  
  // M_NOCHECK? -> Bewegung eh erlaubt (und Rueckgabewert wuerde ignoriert)
  if ((method&M_NOCHECK)) {
    // Bei M_NOCHECK zwar Prevent* aufrufen, aber das Resultat ignorieren
    if (oldenv) oldenv->PreventLeave(this_object(),dest);
    dest->PreventInsert(this_object());

    return 0; // das wars, rest ist egal.
  }

  // P_NODROP verhindert weggeben
  if ((method & (M_PUT|M_GIVE)) && QueryProp(P_NODROP))
      return ME_CANT_BE_DROPPED;

  // P_NOGET verhindert nehmen
  if ((method & (M_GET|M_GIVE)) && QueryProp(P_NOGET))
      return ME_CANT_BE_TAKEN;

  // Gewicht ermitteln
  if ( !(tmp = (int)QueryProp(P_TOTAL_WEIGHT)) )
      tmp = (int)QueryProp(P_WEIGHT);
        
  // Ist das Objekt nicht zu schwer?
  if ( (tmp = (int)dest->MayAddWeight(tmp)) < 0) {
      if ( tmp == -2 ) return ME_TOO_HEAVY_FOR_ENV;
      return ME_TOO_HEAVY;
  }

  // Ist das Zielobjekt schon voll?
  if ( !dest->MayAddObject(this_object()) )
      return TOO_MANY_OBJECTS;

  // Darf hinausbewegt werden?
  if ( oldenv && oldenv->PreventLeave(this_object(), dest) )
      return ME_CANT_LEAVE_ENV;

  // Darf hineinbewegt werden?
  if ( dest->PreventInsert(this_object()) )
      return ME_CANT_BE_INSERTED;

  return(0);
}

// zum Ueberschreiben...
protected void NotifyMove(object dest, object oldenv, int method) {
}

public varargs int move( object|string dest, int method )
{
  object oldenv;
  int tmp;
  string fn,vc;
  mixed sens;

  if (!objectp(dest) && !stringp(dest))
      raise_error(sprintf("Wrong argument 1 to move(). 'dest' must be a "
            "string or object! Argument was: %.100O\n",
            dest));

  // Jetzige Umgebung merken
  oldenv = environment();

  // Bewegung in Para-Welt-Raeume?
  // tmp ist die Ziel-Parallelweltnummer
  if (!environment()||!living(environment())||
      !intp(tmp =(int)environment()->Query(P_PARA)))
    tmp=0;
    
  // Wenn das Objekt von einem in der Parawelt befindlichen Spieler
  // oder NPC bewegt wird, sollte es auch wieder in der Parawelt landen.
  // Um Rechenzeit zu sparen, wird angenommen, dass bei Bewegungen in
  // das Inv oder Env des Spielers 'dest' als Objekt uebergeben wird,
  // wohingegen bei Bewegungen in Nachbarraeume (die eigentlich nur
  // interessant sind) 'dest' als Filename angegeben wird.
  if (tmp&&!objectp(dest)&&!environment(dest)) {
      // Falls der Zielraum nicht schon explizit in der Parallelwelt ist,
      // neuen Zielraum suchen. Aber nur, wenn das Ziel kein Clone ist. Sonst
      // buggt, wenn man versucht, nach raum#42^para zu bewegen.
      if (!IS_PARA(dest) && strrstr(dest,"#")==-1) {
        fn=dest+"^"+tmp;

        // Der Parawelt-Raum wird nur zum Ziel, wenn er a) existiert
        // und b) auch von Spielern betreten werden darf. Letzteres
        // Kriterium kann nur mit im Objekt gesetzter Property
        // P_TESTPLAYER umgangen werden.
          if ( (find_object(fn) || ((file_size(fn+".c")>0||
                  (file_size(vc=implode(explode(fn,"/")[0..<2],"/")+
                  "/virtual_compiler.c")>0 &&
                  !catch(tmp=(int)call_other(vc,"QueryValidObject",fn);
                    publish) && tmp>0)) &&
                  !catch(load_object( fn );publish))) &&
              (!fn->QueryProp(P_NO_PLAYERS) || QueryProp(P_TESTPLAYER)) )
           dest = fn;
      }
  }
    
  // dest auf Objekt normieren.
  if (stringp(dest))
      dest = load_object(dest);
    
  // testen, ob das Objekt bewegt werden will
  if (tmp=PreventMove(dest, oldenv, method)) {
      // auf gueltigen Fehler pruefen, wer weiss, was Magier da evtl.
      // versehentliche zurueckgeben.
      if (VALID_MOVE_ERROR(tmp))
        return(tmp);
      else
        return(ME_DONT_WANT_TO_BE_MOVED);
  }

  // Sensitive Objekte muessen entfernt werden
  sens = QueryProp(P_SENSITIVE);

  if (sens && environment())
  {
    environment()->RemoveSensitiveObject( this_object() );
    if (!objectp(ME))
      return ME_WAS_DESTRUCTED;
  }
  // Bewegen
  move_object(ME, dest);

  //falls (sich) das objekt im init() zerstoert (wurde). (Die u. stehenden
  //Funktionsaufrufe werden dann vom Driver eh groesstenteils ignoriert.)
  if (!objectp(this_object())) return(ME_WAS_DESTRUCTED);

  // Objekt informieren. ;-)
  NotifyMove(environment(), oldenv, method);

  // Alte Umgebung informieren
  if (oldenv) oldenv->NotifyLeave(this_object(), dest);

  // Wenn das Objekt eine Umgebung hat, selbige informieren
  if (environment()) {
    if (sens)
    {
      environment()->InsertSensitiveObject(this_object(),sens);
      if (!objectp(ME)) return ME_WAS_DESTRUCTED;
    }
    environment()->NotifyInsert(this_object(), oldenv);
  }
  //wurde das Objekt vielleicht noch zerstoert?
  if (!objectp(ME)) return(ME_WAS_DESTRUCTED);
  
  //scheint wohl alles ok zu sein.
  return MOVE_OK;
}

// Das Objekt zerstoeren
public varargs int remove(int silent)
{
    if (environment() ) {
        if(QueryProp(P_SENSITIVE))
                environment()->RemoveSensitiveObject(this_object());
        environment()->NotifyRemove(this_object());
    }
    if (objectp(this_object()))
        destruct(this_object());
    return 1;
}

public string NotifyDestruct(object caller) {
  // Lichtsystem mit der aenderung versorgen. :-/
  foreach(object env : all_environment() || ({})) {
      // Ja. Man ruft die _set_xxx()-Funktionen eigentlich nicht direkt auf.
      // Aber das Lichtsystem ist schon *so* rechenintensiv und gerade der
      // P_LAST_CONTENT_CHANGE-Cache wird *so* oft benoetigt, dass es mir
      // da um jedes bisschen Rechenzeit geht.
      // Der Zweck heiligt ja bekanntlich die Mittel. ;-)
      //
      // Tiamak
      env->_set_last_content_change();
  }
  return 0;
}

