// 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
#pragma pedantic

#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;
}

