Your browser must have JavaScript enabled in order to view this page.
 >  >
 
Welcome Guest#215 Login/register    Go to Bottom
Go to Top

Source for file DpObject.php

Documentation is available at DpObject.php

  1. <?php
  2. /**
  3.  * The standard object which is built upon by all other objects
  4.  *
  5.  * DutchPIPE version 0.4; PHP version 5
  6.  *
  7.  * LICENSE: This source file is subject to version 1.0 of the DutchPIPE license.
  8.  * If you did not receive a copy of the DutchPIPE license, you can obtain one at
  9.  * http://dutchpipe.org/license/1_0.txt or by sending a note to
  10.  * license@dutchpipe.org, in which case you will be mailed a copy immediately.
  11.  *
  12.  * @package    DutchPIPE
  13.  * @subpackage dpuniverse_std
  14.  * @author     Lennert Stock <ls@dutchpipe.org>
  15.  * @copyright  2006, 2007 Lennert Stock
  16.  * @license    http://dutchpipe.org/license/1_0.txt  DutchPIPE License
  17.  * @version    Subversion: $Id: DpObject.php 311 2007-09-03 12:48:09Z ls $
  18.  * @link       http://dutchpipe.org/manual/package/DutchPIPE
  19.  */
  20.  
  21. /**
  22.  * The DutchPIPE property and coinherit system which all objects extend on
  23.  */
  24. inherit(DPUNIVERSE_STD_PATH 'DpProperties.php');
  25.  
  26. /**
  27.  * Gets moving constants
  28.  */
  29.  
  30. /**
  31.  * Gets events constants
  32.  */
  33. inherit(DPUNIVERSE_INCLUDE_PATH 'events.php');
  34.  
  35. /**
  36.  * Gets action constants
  37.  */
  38. inherit(DPUNIVERSE_INCLUDE_PATH 'actions.php');
  39.  
  40. /**
  41.  * Gets title type constants
  42.  */
  43. inherit(DPUNIVERSE_INCLUDE_PATH 'title_types.php');
  44.  
  45. /**
  46.  * Gets mass constants
  47.  */
  48.  
  49. /**
  50.  * The standard object which is built upon by all other objects
  51.  *
  52.  * Creates the following DutchPIPE properties:<br />
  53.  *
  54.  * - string <b>uniqueId</b> - Unique Id for this instance, for example
  55.  *   'object_436'
  56.  * - integer <b>resetTime</b> - UNIX timestamp of next reset
  57.  * - string <b>location</b> - Location in dpuniverse, for example
  58.  *   '/page/manual.php'
  59.  * - string <b>sublocation</b> - Optional sublocation, for example
  60.  *   'introduction'
  61.  * - int|float <b>credits</b> - Credits contained, integer or float depending
  62.  *   on type, initially 0
  63.  * - string <b>template</b> - Optional replacement for dpdefault.tpl,
  64.  *   absolute path on server
  65.  * - string <b>title</b> - Title for this object, "beer", used for object
  66.  *   labels, etc.
  67.  * - string <b>titleDefinite</b> - Definite title for this object, "the beer"
  68.  * - string <b>titleIndefinite</b> - Indefinite title for this object, "a beer"
  69.  * - string <b>titleType</b> - Type of this object's title
  70.  * - string <b>titleImg</b> - URL for the avatar or other image representing
  71.  *   this object
  72.  * - int <b>titleImgWidth</b> - Width of the title image in pixels, you can
  73.  *   optionally set this by hand for extra speed but it is not mandatory
  74.  * - int <b>titleImgHeight</b> - Height of the title image in pixels, you can
  75.  *   optionally set this by hand for extra speed but it is not mandatory
  76.  * - boolean <b>isDraggable</b> - Can we be dragged on the screen by a given
  77.  *   user? Experimental
  78.  * - string <b>body</b> - HTML content of this object
  79.  * - integer <b>creationTime</b> - UNIX timestamp when this object instance was
  80.  *   created
  81.  * - integer <b>lastEventTime</b> - UNIX timestamp of last event, used by
  82.  *   cleanup mechanism
  83.  * - string <b>navigationTrailHtml</b> - HTML with a navigation trail for this
  84.  *   page
  85.  * - int|float <b>value</b> - Monetary value, integer or float depending on
  86.  *   type, initially 0
  87.  * - boolean <b>isRemoved</b> - TRUE if removed from universe but not destructed
  88.  *   yet by PHP
  89.  * - integer <b>lastActionTime</b> - UNIX timestamp of last action performed by
  90.  *   this object
  91.  *
  92.  * @package    DutchPIPE
  93.  * @subpackage dpuniverse_std
  94.  * @author     Lennert Stock <ls@dutchpipe.org>
  95.  * @copyright  2006, 2007 Lennert Stock
  96.  * @license    http://dutchpipe.org/license/1_0.txt  DutchPIPE License
  97.  * @version    Release: 0.2.1
  98.  * @link       http://dutchpipe.org/manual/package/DutchPIPE
  99.  */
  100. class DpObject extends DpProperties
  101. {
  102.     /**
  103.      * Public ids for this object, 'beer', 'cool beer'
  104.      *
  105.      * @var        array 
  106.      * @access     private
  107.      */
  108.     private $mIds array();
  109.  
  110.     /**
  111.      * Actions defined by this object, see addAction
  112.      *
  113.      * @var        array 
  114.      * @access     private
  115.      */
  116.     private $mActions array();
  117.  
  118.     /**
  119.      * Aliases used for actions, for example 'exa' for 'examine'
  120.      *
  121.      * @var        array 
  122.      * @access     private
  123.      */
  124.     private $mActionAliases array();
  125.  
  126.     /**
  127.      * Image map areas, enables actions to be defined on areas of images
  128.      *
  129.      * @var        array 
  130.      * @access     private
  131.      */
  132.     private $mMapAreas array();
  133.  
  134.     /**
  135.      * Clickable actions on definable areas of images
  136.      *
  137.      * @var        array 
  138.      * @access     private
  139.      */
  140.     private $mMapAreaActions array();
  141.  
  142.     /**
  143.      * 'Items' on this object which can be examined
  144.      *
  145.      * @var        array 
  146.      * @access     private
  147.      */
  148.     private $mItems array();
  149.  
  150.     /**
  151.      * Aliases used for items
  152.      *
  153.      * @var        array 
  154.      * @access     private
  155.      */
  156.     private $mItemAliases array();
  157.  
  158.     /**
  159.      * Objects to be checked for presence in our inventory during reset
  160.      *
  161.      * @var        array 
  162.      * @access     private
  163.      */
  164.     private $mCheckPresentObjects array();
  165.  
  166.     /**
  167.      * Array of strings with method names which the DutchPIPE client may call
  168.      *
  169.      * @var        array 
  170.      * @access     private
  171.      * @see        addValidClientCall, removeValidClientCall, isValidClientCall
  172.      * @since      DutchPIPE 0.4.0
  173.      */
  174.     private $mValidClientCalls array();
  175.  
  176.     /**
  177.      * Creates this object
  178.      *
  179.      * Called by the universe object when the object is created.
  180.      * Calls {@link createDpObject()} in the inheriting class.
  181.      *
  182.      * :WARNING: Use get_current_dpuniverse()->newDpObject only to create
  183.      * objects, do not use 'new'.
  184.      *
  185.      * :WARNING: It is unlikely you need to call this function directly
  186.      *
  187.      * @access     private
  188.      * @param      string    $unique_id   A unique id for this object
  189.      * @param      int       $reset_time  The UNIX reet time for this object
  190.      * @param      string    $location    Location, e.g. /page/cms.php
  191.      * @param      string    $sublocation Sublocation, e.g. 96
  192.      * @see        __construct2, createDpObject
  193.      */
  194.     final function __construct($unique_id$reset_time$location,
  195.             $sublocation FALSE)
  196.     {
  197.         /* This method may only be called once, at creation time */
  198.         if (isset($this->creationTime)) {
  199.             return;
  200.         }
  201.  
  202.         /*
  203.          * Sets a unique internal id for this object
  204.          *
  205.          * This method is called by __construct with a string such as
  206.          * 'object_628' to set a unique id. This id is used in HTML output as
  207.          * the id of the DIV element spanning this object's HTML appearance, by
  208.          * the AJAX engine to operate on the object, et cetera.
  209.          *
  210.          * WARNING: Don't call this method. Only __construct should call it.
  211.          */
  212.         $this->uniqueId new_dp_property('object_' $unique_id);
  213.  
  214.         $this->resetTime new_dp_property($reset_time);
  215.         $this->location new_dp_property($location);
  216.  
  217.         if (FALSE !== $sublocation{
  218.             $this->sublocation new_dp_property($sublocation);
  219.         }
  220.  
  221.         /* Standard setup calls to set some default values */
  222.  
  223.         $this->credits new_dp_property(0);
  224.  
  225.         /*
  226.          * Path to non-default XHTML template file for this object, if any
  227.          */
  228.         $this->template new_dp_property(NULL);
  229.  
  230.         $this->addId(dp_text('object'));
  231.  
  232.         /*
  233.          * Title, 'Cool, fresh beer'
  234.          */
  235.         $this->title new_dp_property(NULL);
  236.  
  237.         /*
  238.          * Definite title, 'The cool, fresh beer'
  239.          */
  240.         $this->titleDefinite new_dp_property(NULL);
  241.  
  242.         /*
  243.          * Indefinite title, 'A cool, fresh beer'
  244.          */
  245.         $this->titleIndefinite new_dp_property(NULL);
  246.  
  247.         /*
  248.          * Type of title, 'A beer', 'The beer', etc.
  249.          */
  250.         $this->titleType new_dp_property(DPUNIVERSE_TITLE_TYPE_INDEFINITE);
  251.  
  252.         /*
  253.          * Path to the avatar or object image
  254.          */
  255.         $this->titleImg new_dp_property(DPUNIVERSE_IMAGE_URL 'object.gif');
  256.         $this->titleImgWidth new_dp_property(NULL);
  257.         $this->titleImgHeight new_dp_property(NULL);
  258.  
  259.         $this->isDraggable new_dp_property(TRUE);
  260.  
  261.         /*
  262.          * The long description or page content
  263.          */
  264.         $this->body new_dp_property(
  265.             dp_text('You see nothing special.<br />'));
  266.  
  267.         $this->creationTime new_dp_property(time()FALSE);
  268.         $this->lastEventTime new_dp_property(time());
  269.  
  270.         $this->navigationTrailHtml new_dp_property(NULLFALSE);
  271.         $this->value new_dp_property(0);
  272.  
  273.         $this->addValidClientCall('getActionsMenu');
  274.         $this->addValidClientCall('reportMove');
  275.     }
  276.  
  277.     /**
  278.      * Creates this object, continued
  279.      *
  280.      * Called by the universe object when the object is created.
  281.      * Calls {@link createDpObject()} in the inheriting class.
  282.      *
  283.      * :WARNING: It is unlikely you need to call this function directly
  284.      *
  285.      * @access     private
  286.      * @see        __construct, createDpObject
  287.      */
  288.     final function __construct2()
  289.     {
  290.         /* Call CreateDpObjects for objects that extend on this object */
  291.         $this->createDpObject();
  292.  
  293.         if (!isset($this->title)) {
  294.             $this->title dp_text('initialized object');
  295.             $this->titleDefinite dp_text('the initialized object');
  296.             $this->titleIndefinite dp_text('an initialized object');
  297.         }
  298.  
  299.         $this->resetDpObject();
  300.     }
  301.  
  302.     /**
  303.      * Sets this object up at the time it is created
  304.      *
  305.      * An empty function which can be redefined by the class extending on
  306.      * DpObject. When the object is created, it has no title, HTML body, etc.,
  307.      * so here methods such as $this->setTitle() are called.
  308.      * Building blocks extending on DpObject may define their own create
  309.      * function. For example, DpPage defines createDpPage.
  310.      *
  311.      * @see        resetDpObject
  312.      */
  313.     function createDpObject()
  314.     {
  315.     }
  316.  
  317.     /**
  318.      * Resets this object
  319.      *
  320.      * Called by the universe object at regular intervals as defined in
  321.      * {@link dpuniverse-ini.php}. Calls the method 'resetDpObject' in this
  322.      * object. You can redefine that function to periodically do stuff such as
  323.      * alter the state of this object.
  324.      *
  325.      * @access     private
  326.      * @see        resetDpObject
  327.      */
  328.     final function __reset()
  329.     {
  330.         $this->resetDpObject();
  331.     }
  332.  
  333.     /**
  334.      * Resets this object
  335.      *
  336.      * Called by this object at regular intervals as defined in
  337.      * dpuniverse-ini.php. An empty function which can be redefined by the
  338.      * class extending on DpObject. To be used to periodically do stuff such as
  339.      * alter the state of this object.
  340.      *
  341.      * @see        createDpObject
  342.      */
  343.     function resetDpObject()
  344.     {
  345.     }
  346.  
  347.     /**
  348.      * Called by PHP when this object is destroyed, handles events
  349.      *
  350.      * Called by PHP when this object is destroyed. removeDpObject should be
  351.      * called in this object to remove it from the universe. Don't use
  352.      * unset to remove objects. On a PHP level, __destruct will then be called
  353.      * in this object.
  354.      *
  355.      * Calls the event method in this object and its environment, if any, when
  356.      * defined, using constants from events.php.
  357.      *
  358.      * Triggers the EVENT_LEFT_INV event in the environment of this object with
  359.      * "from" ($this) and "to" (0) parameters:
  360.      * $environment->event(EVENT_LEFT_INV, $this, 0);
  361.      *
  362.      * Triggers the EVENT_CHANGED_ENV event in this object with "from" (the
  363.      * environment) and "to" (0) parameters:
  364.      * $this->event(EVENT_CHANGED_ENV, $environment, 0);
  365.      *
  366.      * If the object had no environment, the above two events are not called,
  367.      * instead the EVENT_CHANGED_ENV event is triggered in this object with only
  368.      * a "from" (0) parameter:
  369.      * $this->event(EVENT_CHANGED_ENV, 0);
  370.      *
  371.      * Last, the EVENT_DESTROYING_OBJ event is triggered in this object:
  372.      * $this->event(EVENT_DESTROYING_OBJ);
  373.      *
  374.      * @see        removeDpObject, events.php
  375.      */
  376.     function __destruct()
  377.     {
  378.         if (!isset($this->isRemoved|| TRUE !== $this->isRemoved{
  379.             $this->removeDpObject();
  380.         }
  381.  
  382.         echo sprintf(dp_text("__destruct() called in object %s (%s).\n"),
  383.             $this->uniqueId,
  384.             $this->getTitle(DPUNIVERSE_TITLE_TYPE_INDEFINITE));
  385.     }
  386.  
  387.     /**
  388.      * Removes this object from the universe
  389.      *
  390.      * The object is destroyed and no longer part of the universe. Don't use
  391.      * unset to remove objects. Removes the object from browsers viewing the
  392.      * same environment. On a PHP level, __destruct will then be called in this
  393.      * object.
  394.      *
  395.      * @see        __destruct
  396.      */
  397.     function removeDpObject()
  398.     {
  399.         echo dp_text("removeDpObject() called in object " $this->title
  400.             . ".\n");
  401.  
  402.         foreach ($this->mCheckPresentObjects as $key => &$ob{
  403.             unset($this->mCheckPresentObjects[$key]);
  404.         }
  405.  
  406.         $this->mCheckPresentObjects array();
  407.         $this->mActions array();
  408.         $this->mActionAliases array();
  409.  
  410.         $env $this;
  411.         while (FALSE !== $env->getEnvironment()) {
  412.             $env $env->getEnvironment();
  413.         }
  414.         $env->tell('<removeDpElement id="' $this->uniqueId
  415.             . '">&#160;</removeDpElement>');
  416.  
  417.         $this->isRemoved new_dp_property(TRUE);
  418.  
  419.         if (FALSE !== ($env $this->getEnvironment())) {
  420.             $env->event(EVENT_LEFT_INV$this0);
  421.             $this->event(EVENT_CHANGED_ENV$env0);
  422.         }
  423.         else {
  424.             $this->event(EVENT_CHANGED_ENV0);
  425.         }
  426.  
  427.         $this->event(EVENT_DESTROYING_OBJ);
  428.  
  429.         /* :TODO: Move all users somewhere so they don't get destroyed */
  430.         $inv $this->getInventory();
  431.  
  432.         foreach ($inv as &$ob{
  433.             if ($ob->isUser{
  434.                 $ob->moveDpObject(DPUNIVERSE_PAGE_PATH 'index.php');
  435.             else {
  436.                 $ob->removeDpobject();
  437.             }
  438.         }
  439.         get_current_dpuniverse()->removeDpObject($this);
  440.         DpProperties::removeDpProperties();
  441.         unset($this);
  442.     }
  443.  
  444.     /**
  445.      * Moves this object into the inventory of another object
  446.      *
  447.      * @param   mixed   &$target_ob path or object to move into to
  448.      * @param   boolean $simple     skip some checks
  449.      * @return  int     TRUE for success, an error code for failure
  450.      */
  451.     function moveDpObject(&$target_ob$simple FALSE)
  452.     {
  453.         /* Retrieve the target object, or fail */
  454.         if ((!is_string($target_ob&& !is_object($target_ob))
  455.                 || (is_string($target_ob)
  456.                 && !($target_ob =
  457.                     get_current_dpuniverse()->getDpObject($target_ob)))) {
  458.             return E_MOVEOBJECT_BADDEST;
  459.         }
  460.         if (isset($this->isLiving&& TRUE === $this->isLiving{
  461.             $this->lastActionTime !isset($this->lastActionTime)
  462.                 ? new_dp_property(time()) time();
  463.         }
  464.  
  465.         $curr_env $this->getEnvironment();
  466.  
  467.         /* Do more checking? */
  468.         if (FALSE === $simple{
  469.             /* Checks if the living carrying this object may not drop it: */
  470.             if (FALSE !== $curr_env && $curr_env->isLiving
  471.                     && (bool)$curr_env->noDrop{
  472.                 return E_MOVEOBJECT_NODROP;
  473.             }
  474.  
  475.             /* Checks if target is neither a page nor a living */
  476.             if (FALSE !== $target_ob->getEnvironment(&&
  477.                     FALSE === $target_ob->isLiving{
  478.                 /*
  479.                  * Checks if the object may be inserted into containers, for
  480.                  * instance, drinks could disallow this, to prevent 'spilling':
  481.                  */
  482.                 if (method_exists($this'preventInsert')
  483.                         && (bool)$this->preventInsert()) {
  484.                     return E_MOVEOBJECT_NOSRCINS;
  485.                 }
  486.  
  487.                 /* Checks if the target is a container, or fail */
  488.                 if (FALSE === ((bool)$target_ob->isContainer)) {
  489.                     return E_MOVEOBJECT_NODSTINS;
  490.                 }
  491.             }
  492.  
  493.             /* Checks if the object may be taken by livings */
  494.             if ($target_ob->isLiving && (bool)$this->noTake{
  495.                 return E_MOVEOBJECT_NOGET;
  496.             }
  497.  
  498.             if (WEIGHT_TYPE_NONE !== WEIGHT_TYPE{
  499.                 if (isset($this->weight&& isset($target_ob->maxWeightCarry)
  500.                         && $this->weight 0
  501.                         && $target_ob->weightCarry $this->weight >
  502.                         $target_ob->maxWeightCarry{
  503.                     return E_MOVEOBJECT_HEAVY;
  504.                 }
  505.             }
  506.             if (VOLUME_TYPE_NONE !== VOLUME_TYPE{
  507.                 if (isset($this->volume&& isset($target_ob->maxVolumeCarry)
  508.                         && $this->volume 0
  509.                         && $target_ob->volumeCarry $this->volume >
  510.                         $target_ob->maxVolumeCarry{
  511.                     return E_MOVEOBJECT_VOLUME;
  512.                 }
  513.             }
  514.         }
  515.  
  516.         /*
  517.          * If we're moving to a new environment, check for user defined
  518.          * functions to prevent movement
  519.          */
  520.         if ($curr_env !== $target_ob{
  521.             if (method_exists($this'preventMove'&& ($move_err =
  522.                     $this->preventMove($curr_env$target_ob))) {
  523.                 return $move_err;
  524.             }
  525.             if (!is_null($curr_env)) {
  526.                 if (method_exists($this'preventLeave'&& ($move_err =
  527.                         (int)$curr_env->preventLeave($this$target_ob))) {
  528.                     return $move_err;
  529.                 }
  530.             }
  531.             if (method_exists($this'preventEnter'&& ($move_err =
  532.                     (int)$target_ob->preventEnter($this$curr_env))) {
  533.                 return $move_err;
  534.             }
  535.         }
  536.  
  537.         /* Move the object */
  538.         get_current_dpuniverse()->moveDpObject($this$target_ob);
  539.  
  540.         /* Post-movement stuff */
  541.         if ($curr_env !== $target_ob{
  542.             $this->event(EVENT_CHANGED_ENV$curr_env$target_ob);
  543.             if ($this->isRemoved{
  544.                 return E_MOVEOBJECT_REMOVED;
  545.             }
  546.             if (FALSE !== ($curr_env)) {
  547.                 $old_page $curr_env;
  548.                 while (FALSE !== $old_page->getEnvironment()) {
  549.                     $old_page $old_page->getEnvironment();
  550.                 }
  551.                 $curr_env->event(EVENT_LEFT_INV$this$target_ob);
  552.             }
  553.             $new_page $target_ob;
  554.             while (FALSE !== $new_page->getEnvironment()) {
  555.                 $new_page $new_page->getEnvironment();
  556.             }
  557.  
  558.             $abstract_class FALSE === $target_ob->getEnvironment()
  559.                 ? 'dpobject' 'dpobject2';
  560.  
  561.             if (isset($old_page&& $old_page === $new_page{
  562.                 $new_page->tell(array(
  563.                     'abstract' => '<moveDpElement id="'
  564.                         . $this->uniqueId
  565.                         . '" where="' $target_ob->uniqueId
  566.                         . '" class="' $abstract_class
  567.                         . '">&#160;</moveDpElement>'));
  568.                 if ($target_ob === $new_page{
  569.                     $new_page->tell(array(
  570.                         'graphical' => '<addDpElement id="'
  571.                             . $this->uniqueId '" where="'
  572.                             . $target_ob->uniqueId
  573.                             . '" class="title_img draggable" '
  574.                             . 'css="width: '
  575.                             . (DPSERVER_OBJECT_IMAGE_MAX_WIDTH 5)
  576.                             . 'px; height: '
  577.                             . (DPSERVER_OBJECT_IMAGE_MAX_HEIGHT 26'px">'
  578.                             . $this->getAppearance(1FALSE$new_page,
  579.                             'graphical''</addDpElement>'));
  580.                 else {
  581.                     $new_page->tell(array(
  582.                         'graphical' => '<removeDpElement id="'
  583.                         . $this->uniqueId
  584.                         . '">&#160;</removeDpElement>'));
  585.                 }
  586.             }
  587.             else {
  588.                 if (isset($old_page)) {
  589.                     $old_page->tell('<removeDpElement id="'
  590.                         . $this->uniqueId
  591.                         . '">&#160;</removeDpElement>');
  592.                 }
  593.                 if ($target_ob === $new_page{
  594.                     $new_page->tell(array('abstract' => '<addDpElement id="'
  595.                         . $this->uniqueId '" where="'
  596.                         . $target_ob->uniqueId '" class="'
  597.                         . $abstract_class '">' $this->getAppearance(1,
  598.                         FALSE$new_page'abstract''</addDpElement>',
  599.                         'graphical' => '<addDpElement id="'
  600.                         . $this->uniqueId '" where="'
  601.                         . $target_ob->uniqueId
  602.                         . '" class="title_img draggable" '
  603.                         . 'css="width: '
  604.                         . (DPSERVER_OBJECT_IMAGE_MAX_WIDTH 5)
  605.                         . 'px; height: '
  606.                         . (DPSERVER_OBJECT_IMAGE_MAX_HEIGHT 26'px">'
  607.                         . $this->getAppearance(1FALSE$new_page'graphical')
  608.                         . '</addDpElement>')$this);
  609.                 }
  610.             }
  611.             $target_ob->event(EVENT_ENTERED_INV$this$curr_env);
  612.             $dest_all $target_ob->getInventory();
  613.             foreach ($dest_all as &$ob{
  614.                 $ob->event(EVENT_ENTERED_ENV$this$curr_env);
  615.             }
  616.         }
  617.  
  618.         if (!isset($this->_GET|| !isset($this->_GET['getdivs'])) {
  619.             $body = isset($this->_GET&& isset($this->_GET['ajax'])
  620.                 /* Back/forward button is used */
  621.                 ? $target_ob->getAppearanceInventory(0TRUENULL,
  622.                     $this->displayMode'<div class="dpclr">&nbsp;</div>'
  623.                 : $target_ob->getAppearance(0TRUENULL,
  624.                     $this->displayMode);
  625.             if (FALSE !== $body{
  626.                 $template_path is_null($target_ob->template''
  627.                     : ' template="' $target_ob->template '"';
  628.                 $this->tell('<div id="'
  629.                     . (isset($this->_GET&& isset($this->_GET['ajax'])
  630.                     ? 'dpinventory' '"' 'dppage' '"' $template_path)
  631.                     . '>' $body '</div>');
  632.                 $this->tell('<inputpersistent persistent="'
  633.                     . (!$this->inputPersistent 'off' $this->inputPersistent)
  634.                     . '">&nbsp;</inputpersistent>');
  635.  
  636.                 if ($this->isUser && ($type $target_ob->isMovingArea)) {
  637.                     if (!isset($this->_GET|| !isset($this->_GET['ajax'])) {
  638.                         $this->tell('<script type="text/javascript" src="'
  639.                             . DPUNIVERSE_WWW_URL
  640.                             . 'interface/iutil.js"></script>');
  641.                         $this->tell('<script type="text/javascript" src="'
  642.                             . DPUNIVERSE_WWW_URL
  643.                             . 'interface/idrag.js"></script>');
  644.                     }
  645.                     $containment $type === "containment : 'parent',\n"
  646.                         : '';
  647.                     $cssfix $type == '.dpinventory, .dpinventory2'
  648.                         : '.dpinventory';
  649.                     $this->tell("<script>
  650. function init_drag() {
  651.     if (\$.iDrag == undefined) return;
  652.     \$('div.draggable').DraggableDestroy();
  653.     \$('div.draggable').Draggable({
  654.         handle: 'img.draggable',
  655.         zIndex: 1000,
  656.         ghosting: true,
  657.         opacity: 0.7,{$containment}
  658.         onChange : function() { stopdrag(this) }
  659.     });
  660.     \$('{$cssfix}').css('position', 'relative');
  661.     \$('{$cssfix}').css('overflow', 'hidden');
  662. }
  663. \$(function(){init_drag();});</script>\n");
  664.                 }
  665.             }
  666.         }
  667.  
  668.         return TRUE;
  669.     }
  670.  
  671.     /**
  672.      * Checks if an object is present in this object's inventory
  673.      *
  674.      * If $what is a string, searches for an object with that id. If $what is an
  675.      * object, searches for that object. Searches are done in the inventory of
  676.      * this object.
  677.      *
  678.      * @param      mixed     $what       string (id) or object to search for
  679.      * @return     boolean   TRUE if $what is in our inventory, FALSE otherwise
  680.      */
  681.     function isPresent($what)
  682.     {
  683.         return get_current_dpuniverse()->isPresent($what$this);
  684.     }
  685.  
  686.     /**
  687.      * Makes sure an object is present in this object's inventory
  688.      *
  689.      * Replenishes this object's inventory up to $number instances of $what.
  690.      * This method is usually called from the reset method of pages and npc's.
  691.      *
  692.      * If $what is a string, searches for an object with that id. If $what is an
  693.      * object, searches for that object. Searches are done in the inventory of
  694.      * this object.
  695.      *
  696.      * A $number can be given to search for more objects instead of just one.
  697.      * For example, it could check for the presence of 5 roses, and if there
  698.      * are only 3, create another 2.
  699.      *
  700.      * If $mustBeHere is FALSE (it is TRUE by default), it will not replenish
  701.      * objects which are still in another part of the universe, instead of
  702.      * having been destroyed. For example, the 2 missing roses could have been
  703.      * taken by a user who is now on another page, and with this argument set
  704.      * to FALSE, no extra objects will be created.
  705.      *
  706.      * If $mustBeHere is TRUE, $moveHere can be set to TRUE (it is FALSE by
  707.      * default) to move objects which still exist but are located in another
  708.      * part of the universe, back to this object, its original location.
  709.      *
  710.      * @param      mixed     $what       string (id) or object to search for
  711.      * @param      int       $number     number of such objects to search for
  712.      * @param      boolean   $mustBeHere search only here for object?
  713.      * @param      boolean   $moveHere   replenish from objects elsewhere?
  714.      */
  715.     function makePresent($what$number 1$mustBeHere TRUE,
  716.             $moveHere FALSE)
  717.     {
  718.         $found 0;
  719.         if (count($this->mCheckPresentObjects)) {
  720.             $keys array_keys($this->mCheckPresentObjects);
  721.             foreach ($keys as $key{
  722.                 if (!isset($this->mCheckPresentObjects[$key])) {
  723.                     continue;
  724.                 }
  725.                 if (empty($this->mCheckPresentObjects[$key])
  726.                         || $this->mCheckPresentObjects[$key]->isRemoved{
  727.                     unset($this->mCheckPresentObjects[$key]);
  728.                     continue;
  729.                 }
  730.                 $ob $this->mCheckPresentObjects[$key];
  731.                 if ((is_object($what&& $ob === $what)
  732.                         || (is_string($what&& $ob->location === $what)) {
  733.                     if ($mustBeHere{
  734.                         if (!$this->isPresent($ob)) {
  735.                             if ($moveHere{
  736.                                 $ob->moveDpObject($this);
  737.                                 if (++$found === $number{
  738.                                     return;
  739.                                 }
  740.                             }
  741.                         elseif (++$found === $number{
  742.                             return;
  743.                         }
  744.                     }
  745.                     elseif (++$found === $number{
  746.                         return;
  747.                     }
  748.                 }
  749.             }
  750.         }
  751.         while ($found $number{
  752.             $ob get_current_dpuniverse()->newDpObject($what);
  753.             $ob->moveDpObject($this);
  754.             $this->mCheckPresentObjects[=$ob;
  755.             $found++;
  756.         }
  757.     }
  758.  
  759.     /**
  760.      * Gets the object reference to the environment of this object
  761.      *
  762.      * @return     mixed     object reference or FALSE for no environment
  763.      */
  764.     function &getEnvironment()
  765.     {
  766.         return get_current_dpuniverse()->getEnvironment($this);
  767.     }
  768.  
  769.     /**
  770.      * Gets an array with object references to all objects in our inventory
  771.      *
  772.      * If this object contains no other objects, an empty array is returned.
  773.      *
  774.      * @return     array     object references to objects in our inventory
  775.      */
  776.     function &getInventory()
  777.     {
  778.         return get_current_dpuniverse()->getInventory($this);
  779.     }
  780.  
  781.     /**
  782.      * Calls the given method after the given number of seconds
  783.      *
  784.      * Use this to perform delayed method calls in this object. Note that
  785.      * functions such as get_current_dpuser() can be totally different when the
  786.      * method is called. Also note that the actual delay is not exact science.
  787.      *
  788.      * @param      string    $method     name of method to call in this object
  789.      * @param      int       $secs       delay in seconds
  790.      */
  791.     function setTimeout($method$secs)
  792.     {
  793.         if (func_num_args(<= 2{
  794.             get_current_dpuniverse()->setTimeout($this$method$secs);
  795.         else {
  796.             $args func_get_args();
  797.  
  798.             call_user_func_array(array(get_current_dpuniverse()'setTimeout'),
  799.                 array_merge(array(&$this$method$secs),
  800.                 array_slice($args2)));
  801.         }
  802.     }
  803.  
  804.     /**
  805.      * Tells data (message, window, location, ...) to this object
  806.      *
  807.      * Tells a message to this object, for instance a chat line. Handled by
  808.      * by default.
  809.      *
  810.      * @param      string    $data      message string
  811.      */
  812.     function tell($data)
  813.     {
  814.     }
  815.  
  816.     /**
  817.      * Sets an array of names used to refer to this object
  818.      *
  819.      * Overwrites previous set ids. Ids are case insensitive and all turned
  820.      * into lowercase.
  821.      *
  822.      * @param      array     $ids        array of name strings
  823.      * @see        addId(), removeId(), getIds(), isId()
  824.      */
  825.     function setIds($ids)
  826.     {
  827.         $this->mIds array();
  828.         foreach ($ids as $id{
  829.             $this->mIds[dp_strtolower($id)TRUE;
  830.         }
  831.     }
  832.  
  833.     /**
  834.      * Adds one or more ids for this object
  835.      *
  836.      * A single id can be added at a time, or an array with ids can be given,
  837.      * or multiple arguments can be given (strings or array of strings).
  838.      *
  839.      * @param      string|array $id     name string or array of name strings
  840.      * @see        setIds(), removeId(), getIds(), isId()
  841.      */
  842.     function addId($id)
  843.     {
  844.         if ($sz func_num_args()) {
  845.             for ($i 0$i $sz$i++{
  846.                 $ids func_get_arg($i);
  847.                 if (FALSE === is_array($ids)) {
  848.                     if (dp_strlen($ids)) {
  849.                         $this->mIds[dp_strtolower($ids)TRUE;
  850.                     }
  851.                 else {
  852.                     foreach ($ids as $id{
  853.                         if (dp_strlen($id)) {
  854.                             $this->mIds[dp_strtolower($id)TRUE;
  855.                         }
  856.                     }
  857.                 }
  858.             }
  859.         }
  860.     }
  861.  
  862.     /**
  863.      * Removes one or more ids for this object
  864.      *
  865.      * A single id can be removed at a time, or an array with ids can be given,
  866.      * or multiple arguments can be given (strings or array of strings).
  867.      *
  868.      * @param      string|array $id     name string or array of name strings
  869.      * @see        setIds(), addId(), getIds(), isId()
  870.      */
  871.     function removeId($id)
  872.     {
  873.         if ($sz func_num_args()) {
  874.             for ($i 0$i $sz && sizeof($this->mIds)$i++{
  875.                 $ids func_get_arg($i);
  876.                 if (FALSE === is_array($ids)) {
  877.                     if (dp_strlen($ids&& isset($this->mIds[$ids])) {
  878.                         unset($this->mIds[$ids]);
  879.                     }
  880.                 else {
  881.                     foreach ($ids as $id{
  882.                         if (dp_strlen($id&& isset($this->mIds[$id])) {
  883.                             unset($this->mIds[$id]);
  884.                         }
  885.                     }
  886.                 }
  887.             }
  888.         }
  889.     }
  890.  
  891.     /**
  892.      * Gets the array of ids for this object, or an empty array for no ids
  893.      *
  894.      * @return     array     array of name strings
  895.      * @see        setIds(), addId(), removeId(), isId()
  896.      */
  897.     function getIds()
  898.     {
  899.         return $this->mIds;
  900.     }
  901.  
  902.     /**
  903.      * Checks if the given id is a valid id for this object
  904.      *
  905.      * For example, a barkeeper object was set up like this:
  906.      * $this->addId('barkeeper');
  907.      * Now isId('barkeeper') called in this object will return TRUE, but
  908.      * 'the barkeeper' and 'a barkeeper' will also return TRUE.
  909.      * The disable the last behaviour, set $checkWithArticle to FALSE.
  910.      *
  911.      * @param      string    $id                name string to check
  912.      * @param      string    $checkWithArticle  also check ids with articles
  913.      * @return     boolean   TRUE if the id is valid, FALSE otherwise
  914.      * @see        setIds(), addId(), removeId(), getIds()
  915.      */
  916.     function isId($id$checkWithArticle TRUE)
  917.     {
  918.         $id trim($id);
  919.         return dp_strlen($id&& (isset($this->mIds[$id dp_strtolower($id)])
  920.             || $id == dp_strtolower($this->title))
  921.             || $id == $this->uniqueId
  922.             || ($checkWithArticle && $this->_isIdWithArticle($id));
  923.     }
  924.  
  925.     /**
  926.      * Checks if the given id is a valid id when articles are stripped off
  927.      *
  928.      * Strips off 'a', 'an' and 'the' (for English), and checks is the remainder
  929.      * is a valid id for this object.
  930.      *
  931.      * @access     private
  932.      * @param      string    $id                name string to check
  933.      * @return     boolean   TRUE if the id is valid, FALSE otherwise
  934.      * @see        isId()
  935.      */
  936.     private function _isIdWithArticle($id)
  937.     {
  938.         $articles explode('#'dp_text('a#an#the'));
  939.         $space_pos dp_strpos($id' ');
  940.         if (FALSE === $space_pos{
  941.             return FALSE;
  942.         }
  943.  
  944.         $first_word dp_substr($id0$space_pos);
  945.         $rest dp_substr($id$space_pos 1);
  946.         return in_array($first_word$articles&& $this->isId($restFALSE);
  947.     }
  948.  
  949.     /**
  950.      * Sets the title for this object, "beer", used for object labels, etc.
  951.      *
  952.      * This title is used for object labels, page titles, messages, et cetera.
  953.      * Objects are visualized using two mechanisms: the object's "title" and
  954.      * the object's "body". The title is used when the object is nearby, for
  955.      * instance in the environment of a user that sees it. The body is used
  956.      * when we're in the object (a page) or examining the object. In other
  957.      * words, the object's title is a very abstract way to describe the object
  958.      * when looking at it from a greater distance.
  959.      *
  960.      * In plain language, this function controls the avatar or object image,
  961.      * and the label under it.
  962.      *
  963.      * The $title should be a short description like "beer" without "a" or "the"
  964.      * in front.
  965.      *
  966.      * The $title_img should be a URL to the image shown to represent this
  967.      * object.
  968.      *
  969.      * The second argument, $type, should be a constant as defined in
  970.      * include/title_types.php and is used by the framework to, for example,
  971.      * construct lines such as "Lennert takes a cool, fresh beer" instead of
  972.      * "A Lennert takes a cool fresh, beer" or "The Lennert takes a cool, fresh
  973.      * beer".
  974.      *
  975.      * DPUNIVERSE_TITLE_TYPE_INDEFINITE - the title is indefinite, "a beer"
  976.      * DPUNIVERSE_TITLE_TYPE_DEFINITE - the title is definite, "the hulk"
  977.      * DPUNIVERSE_TITLE_TYPE_NAME - the title is a name, "Lennert"
  978.      * DPUNIVERSE_TITLE_TYPE_PLURAL - the title is plural, "sweets" (not yet
  979.      * implemented)
  980.      *
  981.      * @param      string    $title      short description, "beer"
  982.      * @param      string    $titleType  noun type, use the constants above
  983.      * @param      string    $titleImg   URL to avatar or object image
  984.      */
  985.     public function setTitle($title$titleType FALSE$titleImg FALSE)
  986.     {
  987.         $this->setDpProperty('title'$title);
  988.         $this->titleDefinite NULL;
  989.         $this->titleIndefinite NULL;
  990.  
  991.         if (FALSE !== $titleType{
  992.             $this->titleType $titleType;
  993.         }
  994.  
  995.         if (FALSE !== $titleImg{
  996.             $this->titleImg $titleImg;
  997.         }
  998.     }
  999.  
  1000.     /**
  1001.      * Gets the object's title with optional prefixes such as 'a' and 'the'
  1002.      *
  1003.      * Gets the title as set with setTitle, for example "barkeeper" if no $type
  1004.      * is given.
  1005.      *
  1006.      * If $type is DPUNIVERSE_TITLE_TYPE_INDEFINITE, "a ..." or "an ..." is
  1007.      * put in front if the object's title type has been set to indefinite. So
  1008.      * for a barkeeper this returns "a barkeeper", for me it returns "Lennert".
  1009.      *
  1010.      * If $type is DPUNIVERSE_TITLE_TYPE_DEFINITE, "the" is put in front if the
  1011.      * object's title type is not DPUNIVERSE_TITLE_TYPE_NAME. So for a barkeeper
  1012.      * this returns "the barkeeper", for me it returns "Lennert".
  1013.      *
  1014.      * @param      string    $type       noun type, use the constants above
  1015.      * @return     string    the object's title
  1016.      */
  1017.     public function getTitle($type NULL)
  1018.     {
  1019.         switch ($type{
  1020.         case DPUNIVERSE_TITLE_TYPE_INDEFINITE:
  1021.             switch ($this->getTitleType()) {
  1022.             case DPUNIVERSE_TITLE_TYPE_DEFINITE:
  1023.                 return !is_null($this->titleDefinite$this->titleDefinite
  1024.                     : sprintf(dp_text('the %s')$this->getDpProperty('title'));
  1025.             case DPUNIVERSE_TITLE_TYPE_NAMEcase DPUNIVERSE_TITLE_TYPE_PLURAL:
  1026.                 return $this->getDpProperty('title');
  1027.             default:
  1028.                 if (!is_null($this->titleIndefinite)) {
  1029.                     return $this->titleIndefinite;
  1030.                 }
  1031.                 $title $this->getDpProperty('title');
  1032.                 return (FALSE === dp_strpos(dp_text('aeioux'),
  1033.                     dp_strtolower($title{0}))
  1034.                     ? sprintf(dp_text('a %s')$title)
  1035.                     : sprintf(dp_text('an %s')$title));
  1036.             }
  1037.         case DPUNIVERSE_TITLE_TYPE_DEFINITE:
  1038.             switch ($this->getTitleType()) {
  1039.             case DPUNIVERSE_TITLE_TYPE_NAME:
  1040.                 return $this->getDpProperty('title');
  1041.             default:
  1042.                 return !is_null($this->titleDefinite$this->titleDefinite
  1043.                     : sprintf(dp_text('the %s')$this->getDpProperty('title'));
  1044.             }
  1045.         default:
  1046.             return $this->getDpProperty('title');
  1047.         }
  1048.     }
  1049.  
  1050.     /**
  1051.      * Sets the HTML content of this object
  1052.      *
  1053.      * If this is a page, this defines the page content. For other objects, it
  1054.      * defines what you see when examining the object or moving into the object
  1055.      * (which makes the object behave like a page).
  1056.      *
  1057.      * When a single argument is given, sets the HTML content to the given text.
  1058.      *
  1059.      * Pairs of arguments can be given to set the content in other ways, with
  1060.      * the second argument the type, and the first the data (what the data is
  1061.      * depends on the type).
  1062.      *
  1063.      * Types are:
  1064.      * string (default, raw data)
  1065.      * file (read content of given filename)
  1066.      *
  1067.      * Examples:
  1068.      * $this->setBody('Hello world');
  1069.      * $this->setBody('helloworld.html', 'file');
  1070.      * $this->setBody('Prefix', 'string', 'helloworld.html', 'file', 'Postfix',
  1071.      *     'string')
  1072.      *
  1073.      * When a file is read, the following strings are replaced by their
  1074.      * corresponding constants:
  1075.      * /dpclient.php, /page/ and /images/
  1076.      *
  1077.      * Instead of text or a path, a method to call whenever the body property is
  1078.      * requested can be given using an array two elements: an object and a
  1079.      * method name. Depending on the type, the method should return text or a
  1080.      * path.
  1081.      *
  1082.      * @param       string    $body       content data or method
  1083.      * @param       string    $type       content type
  1084.      * @see         getBody
  1085.      */
  1086.     public function setBody($body$type 'text')
  1087.     {
  1088.         $num_args func_num_args();
  1089.         if (== $num_args{
  1090.             $this->setDpProperty('body'$body);
  1091.             return;
  1092.         }
  1093.         $tmp array();
  1094.         for ($i 0$i $num_args$i += 2{
  1095.             $tmp[array(func_get_arg($i)func_get_arg($i 1));
  1096.         }
  1097.         $this->setDpProperty('body'$tmp);
  1098.     }
  1099.  
  1100.     /**
  1101.      * Gets the HTML content of this object
  1102.      *
  1103.      * @return     string    HTML content of this object
  1104.      * @see        setBody
  1105.      */
  1106.     public function getBody()
  1107.     {
  1108.         $body $this->getDpProperty('body');
  1109.         parse_dp_callable($body$this);
  1110.  
  1111.         if (!is_array($body)) {
  1112.             return $this->getMapAreaHtml("\n" $body;
  1113.         }
  1114.  
  1115.         $rval '';
  1116.  
  1117.         foreach ($body as &$b{
  1118.             $data $b[0];
  1119.             parse_dp_callable($data$this);
  1120.             $type $b[1];
  1121.             if ($type === 'text'{
  1122.                 $rval .= $data;
  1123.             }
  1124.             elseif ($type === 'file'{
  1125.                 $tmp dp_file_get_contents($data);
  1126.  
  1127.                 if (FALSE !== $tmp{
  1128.                     $rval .= str_replace(array('/dpclient.php',
  1129.                         '/page/''/images/'),
  1130.                         array(DPSERVER_CLIENT_URLDPUNIVERSE_PAGE_PATH,
  1131.                         DPUNIVERSE_IMAGE_URL)$tmp);
  1132.                 }
  1133.             elseif ($type === 'url'{
  1134.                 /* Experimental, ignore */
  1135.                 $rval .= $this->getBodyUrl($data);
  1136.             }
  1137.         }
  1138.         return $this->getMapAreaHtml("\n" $rval;
  1139.     }
  1140.  
  1141.     /**
  1142.      * Gets the HTML content of this object
  1143.      *
  1144.      * Experimental, ignore.
  1145.      *
  1146.      * @access     private
  1147.      * @param      string    $url             location of contents
  1148.      * @return     string    HTML content of this object
  1149.      */
  1150.     private function _getBodyUrl($url)
  1151.     {
  1152.         echo dp_text("Getting mailman contents\n");
  1153.  
  1154.         inherit(DPUNIVERSE_STD_PATH 'mailman.php');
  1155.  
  1156.         $config array
  1157.         (
  1158.             'url_var_name'             => 'q',
  1159.             'flags_var_name'           => 'hl',
  1160.             'get_form_name'            => '__script_get_form',
  1161.             'proxy_url_form_name'      => 'poxy_url_form',
  1162.             'proxy_settings_form_name' => 'poxy_settings_form',
  1163.             'max_file_size'            => -1
  1164.         );
  1165.         $flags '0011100000';
  1166.         $PHProxy =  new PHProxy($config$flags);
  1167.         $PHProxy->start_transfer($data);
  1168.         $tmp $PHProxy->return_response();
  1169.  
  1170.         /*
  1171.         $fp = fopen($data, "rb");
  1172.  
  1173.         if (!$fp) {
  1174.            return false;
  1175.         }
  1176.  
  1177.         $tmp = "";
  1178.         while (! feof($fp)) {
  1179.            $tmp .= fread($fp, 4096);
  1180.         }
  1181.  
  1182.         $meta_data = stream_get_meta_data($fp);
  1183.         fclose($fp);
  1184.         foreach($meta_data['wrapper_data'] as $response) {
  1185.             $tmp .= htmlentities($response) . '<br />';
  1186.         }
  1187.         */
  1188.         $pos1 stripos($tmp'<title>');
  1189.         $pos2 stripos($tmp'</title>');
  1190.         $len dp_strlen($tmp);
  1191.         if (FALSE !== $pos1 && FALSE !== $pos2{
  1192.             $this->setTitle($tmp2 dp_substr($tmp$pos1 7$pos2 -
  1193.                 ($pos1 7)));
  1194.             $this->setNavigationTrail(array(DPUNIVERSE_NAVLOGO''),
  1195.                 $tmp2);
  1196.         }
  1197.         $tmp str_replace(array('/mailman2/''="100%"'),
  1198.             array('/mailman/''="90%"')$tmp);
  1199.         $rval .= $tmp;
  1200.     }
  1201.  
  1202.     /**
  1203.      * Gets the HTML "appearance" of this object
  1204.      *
  1205.      * Gets HTML to represent the object to another objects. That is, other
  1206.      * objects call this method in order to "see" it, and HTML is returned. How
  1207.      * an object is seen depends on how the object is related to the object that
  1208.      * is viewing it in terms of "physical" location.
  1209.      *
  1210.      * In other words, a level of 0 means this object is seen by something in
  1211.      * its inventory (a user sees a page). Level 1 means this object is seen by
  1212.      * an object in its environment (a user sees another user). Level 2 means
  1213.      * this object is in the inventory of the object that is seeing it.
  1214.      *
  1215.      * @param      int       $level           level of visibility
  1216.      * @param      boolean   $include_div     include div with id around HTML?
  1217.      * @param      object    $from            experimental
  1218.      * @param      string    $displayMode     'abstract' or 'graphical'
  1219.      * @param      boolean   $displayTitlebar display title bar for pages?
  1220.      * @param      boolean   $elementId       to be used as html element id
  1221.      * @return     string    HTML "appearance" of this object
  1222.      * @see        getAppearanceTitle
  1223.      */
  1224.     public function getAppearance($level 0$include_div TRUE,
  1225.             $from NULL$displayMode 'abstract',
  1226.             $displayTitlebar TRUE$elementId 'dppage')
  1227.     {
  1228.         $user get_current_dpobject();
  1229.         if (empty($user)) {
  1230.             $user get_current_dpuser();
  1231.         }
  1232.         $body $inventory '';
  1233.         $titlebar '';
  1234.         if (=== $level{
  1235.             if (TRUE === $displayTitlebar{
  1236.                 $template_path is_null($this->template''
  1237.                     : ' template="' $this->template '"';
  1238.                 $navtrail $this->getNavigationTrailHtml();
  1239.                 if (FALSE === $user{
  1240.                     $titlebar $navtrail;
  1241.                 else {
  1242.                     $login_link !isset($user->isRegistered)
  1243.                         || TRUE !== $user->isRegistered
  1244.                         ? '<a href="' DPSERVER_CLIENT_URL '?location='
  1245.                         . DPUNIVERSE_PAGE_PATH'login.php" style='
  1246.                         . '"padding-left: 4px">' dp_text('Login/register')
  1247.                         . '</a>'
  1248.                         : '<a href="' DPSERVER_CLIENT_URL '?location='
  1249.                         . DPUNIVERSE_PAGE_PATH 'login.php&amp;act=logout" '
  1250.                         . 'style="padding-left: 4px">' dp_text('Logout')
  1251.                         . '</a>';
  1252.                     $bottom dp_text('Go to Bottom');
  1253.                     $titlebar '<div id="titlebarleft">' .
  1254.                         $navtrail '</div><div id='
  1255.                         . '"titlebarright">&#160;<div id="dploginout">'
  1256.                         .sprintf(dp_text('Welcome %s')'<span id="username">'
  1257.                         . $user->title '</span>')
  1258.                         . ' <span id="loginlink">'
  1259.                         . $login_link '</span>&#160;&#160;&#160;&#160;'
  1260.                         . '<img id="butbottom" src="' DPUNIVERSE_IMAGE_URL
  1261.                         . 'bottom.gif" '
  1262.                         . 'align="absbottom" width="11" height="11" border="0" '
  1263.                         . 'alt="' $bottom '" title="' $bottom '" '
  1264.                         . 'onclick="_gel(\'dpaction\').focus(); '
  1265.                         . 'scroll(0, 999999)" /></div></div>';
  1266.                 }
  1267.                 $titlebar '<div id="titlebar">' $titlebar '</div>';
  1268.             else {
  1269.                 $template_path '';
  1270.             }
  1271.  
  1272.             $body '<div id="' $elementId '"' $template_path
  1273.                 . '><div id="' $elementId '_inner1">' $titlebar
  1274.                 . '<div class="' $elementId '_inner2" id="' $elementId
  1275.                 . '_inner2">' '<div id="dppage_body">'
  1276.                 . ($displayTitlebar === -'' $this->getBody()
  1277.                 . '</div><br />');
  1278.  
  1279.             $inventory $this->getAppearanceInventory($level$include_div,
  1280.                 $from$displayMode$displayTitlebar$elementId)
  1281.                 . '<div class="dpclr">&nbsp;</div>';
  1282.  
  1283.             if (isset($this->isLiving&& TRUE === $this->isLiving{
  1284.                 $reguser_age $inactive_time $session_age '';
  1285.                 if ($displayTitlebar !== -1{
  1286.                     if (isset($this->isUser&& TRUE === $this->isUser{
  1287.                         $session_age (get_current_dpobject()
  1288.                             && get_current_dpobject(=== $this
  1289.                             ? (!isset($this->isRegistered)
  1290.                                 || TRUE !== $this->isRegistered
  1291.                                 ? dp_text("You have been %s on this site.",
  1292.                                 $this->sessionAge)
  1293.                                 : dp_text("This session, you have been %s on this site.",
  1294.                                 $this->sessionAge))
  1295.                             : (!isset($this->isRegistered)
  1296.                                 || TRUE !== $this->isRegistered ucfirst(
  1297.                                 dp_text("%s has been %s on this site.",
  1298.                                 $this->getTitle(DPUNIVERSE_TITLE_TYPE_DEFINITE),
  1299.                                 $this->sessionAge))
  1300.                                 : dp_text("This session, %s has been %s on this site.",
  1301.                                 $this->getTitle(DPUNIVERSE_TITLE_TYPE_DEFINITE),
  1302.                                 $this->sessionAge))) '<br /><br />';
  1303.                     }
  1304.  
  1305.                     $reguser_age !isset($this->isRegistered)
  1306.                         || TRUE !== $this->isRegistered
  1307.                         ? '' (get_current_dpobject()
  1308.                         && get_current_dpobject(=== $this ?
  1309.                         dp_text("In total, you have been %s on this site.",
  1310.                         $this->age)
  1311.                         : dp_text("In total, %s has been %s on this site.",
  1312.                         $this->getTitle(DPUNIVERSE_TITLE_TYPE_DEFINITE),
  1313.                         $this->age)) '<br /><br />';
  1314.  
  1315.                     $inactive_time !isset($this->isInactive)
  1316.                         || TRUE !== $this->isInactive ''
  1317.                         : dp_text('%s has been inactive for %s.',
  1318.                         $this->getTitle(DPUNIVERSE_TITLE_TYPE_DEFINITE),
  1319.                         $this->inactive'<br /><br />';
  1320.                 }
  1321.  
  1322.                 return $body $session_age $reguser_age $inactive_time .
  1323.                     (get_current_dpobject(&& get_current_dpobject(=== $this
  1324.                     ? dp_text('You are carrying:')
  1325.                     : ucfirst(dp_text('%s is carrying:',
  1326.                         $this->getTitle(DPUNIVERSE_TITLE_TYPE_DEFINITE))))
  1327.                     . '<br />'
  1328.                     . ($inventory == '' dp_text('Nothing'$inventory)
  1329.                     . '</div></div></div>';
  1330.             }
  1331.             $body .= $inventory '</div></div></div>';
  1332.             return $body;
  1333.         elseif (=== $level{
  1334.             $status !isset($this->status|| FALSE === $this->status
  1335.                 ? '' ' (' $this->status ')';
  1336.  
  1337.             if (is_null($from)) {
  1338.                 $from $user;
  1339.             }
  1340.  
  1341.             if ($displayMode === 'graphical' && isset($this->titleImg)) {
  1342.                 $title_img $this->getAppearanceTitle($user);
  1343.  
  1344.                 return FALSE === $include_div $title_img
  1345.                     : '<div id="' $this->uniqueId '" '
  1346.                     . 'class="title_img' ($from !== $this '' '_me')
  1347.                     . ' draggable" style="width: '
  1348.                     . (DPSERVER_OBJECT_IMAGE_MAX_WIDTH 5)
  1349.                     . 'px; height: ' (DPSERVER_OBJECT_IMAGE_MAX_HEIGHT 26)
  1350.                     . 'px">' $title_img '</div>';
  1351.             }
  1352.  
  1353.             $body $from === $this '<span class="me">'
  1354.                 . ucfirst($this->getTitle(DPUNIVERSE_TITLE_TYPE_INDEFINITE))
  1355.                 . $status '</span>'
  1356.                 : ucfirst($this->getTitle(DPUNIVERSE_TITLE_TYPE_INDEFINITE))
  1357.                 . $status;
  1358.  
  1359.             $inv $this->getInventory();
  1360.             foreach ($inv as &$ob{
  1361.                 $inventory .= $ob->getAppearance($level 1$include_div,
  1362.                     $from$displayMode);
  1363.             }
  1364.  
  1365.             return FALSE === $include_div $body $inventory
  1366.                 : '<div id="' $this->uniqueId
  1367.                 . '" class="dpobject" onclick="get_actions(\''
  1368.                 . $this->uniqueId '\', event)">'
  1369.                 . $body $inventory '</div>';
  1370.         elseif (=== $level{
  1371.             $status !isset($this->status|| FALSE === $this->status
  1372.                 ? '' ' (' $this->status ')';
  1373.             return FALSE === $include_div
  1374.                 ? ucfirst($this->getTitle(DPUNIVERSE_TITLE_TYPE_INDEFINITE))
  1375.                 . $status
  1376.                 : '<div id="' $this->uniqueId
  1377.                 . '" class="dpobject2" onclick="get_actions(\''
  1378.                 . $this->uniqueId '\')">'
  1379.                 . ucfirst($this->getTitle(DPUNIVERSE_TITLE_TYPE_INDEFINITE))
  1380.                 . $status '</div>';
  1381.         }
  1382.         return $body (=== dp_strlen($inventory"" $inventory)
  1383.             . '</div></div></div>';
  1384.     }
  1385.  
  1386.     /**
  1387.      * Gets the graphical appearance in HTML for this object
  1388.      *
  1389.      * Returns the HTML with the image and the title of the object. The method
  1390.      * filterAppearance($level, &$from, $appearance, &$user) is called in the
  1391.      * environments of the object if defined. $level is 1, $from is an array
  1392.      * starting with this object, followed by elements defining a path to the
  1393.      * current object being called, $appearance the default appearance HTML and
  1394.      * $user the user for which we're getting the appearance of the object. If
  1395.      * you define it, it should return a string with the HTML for the
  1396.      * appearance, just like getAppearanceTitle does itself.
  1397.      *
  1398.      * @param      object    &$user        performer of actions
  1399.      * @return     string    the graphical appearance in HTML for this object
  1400.      * @see        getAppearanceTitle
  1401.      * @since      DutchPIPE 0.3.0
  1402.      */
  1403.     function getAppearanceTitle(&$user)
  1404.     {
  1405.  
  1406.         $status !isset($this->status|| FALSE === $this->status
  1407.             ? '' ' (' $this->status ')';
  1408.         $title_pre $title_post '';
  1409.         $title_img_class "dpimage";
  1410.         if ($this->isDraggable($user)) {
  1411.             $title_img_class .= ' draggable';
  1412.         }
  1413.         if ($this->isInactive{
  1414.             $title_img_class .= ' dpinactive';
  1415.             $title_pre '<span class="dpinactive_txt">';
  1416.             $title_post '</span>';
  1417.         }
  1418.         $alt dp_text('Click me!');
  1419.  
  1420.         $width_html FALSE === ($width $this->getTitleImgWidth()) ''
  1421.             : ' width="' $width '"';
  1422.         $height_html =  FALSE === ($height $this->getTitleImgHeight()) ''
  1423.             : ' height="' $height '"';
  1424.         $margin_top FALSE === $height
  1425.             || $height >= DPSERVER_OBJECT_IMAGE_MAX_HEIGHT ''
  1426.             : ' style="margin-top: '
  1427.             . (DPSERVER_OBJECT_IMAGE_MAX_HEIGHT $height'px"';
  1428.  
  1429.         $img_title '<img src="' $this->titleImg '" '
  1430.             . 'border="0"' $width_html $height_html $margin_top
  1431.             . ' class="' $title_img_class '" ' 'onclick="get_actions(\''
  1432.             . $this->uniqueId '\', event)" ' 'alt="' $alt '" title="'
  1433.             . $alt '" /> <br />' $title_pre  /* IE6 needs space before br */
  1434.             . ucfirst($this->getTitleDPUNIVERSE_TITLE_TYPE_INDEFINITE))
  1435.             . $status $title_post;
  1436.  
  1437.         $env =$this;
  1438.         $from array();
  1439.         do {
  1440.             $from[$env;
  1441.             if (method_exists($env'filterAppearance')) {
  1442.                 $img_title $env->filterAppearance(1$from$img_title,
  1443.                     $user);
  1444.             }
  1445.  
  1446.             $env $env->getEnvironment();
  1447.         while ($env);
  1448.  
  1449.         return $img_title;
  1450.     }
  1451.  
  1452.     /**
  1453.      * Gets the HTML "appearance" of all objects in this object's inventory
  1454.      *
  1455.      * Gets HTML to represents the all objects in this object's inventory using
  1456.      * getAppearance.
  1457.      *
  1458.      * @param      int       $level           level of visibility of this object
  1459.      * @param      boolean   $include_div     include div with id around HTML?
  1460.      * @param      object    $from            expiremental
  1461.      * @param      string    $displayMode     'abstract' or 'graphical'
  1462.      * @return     string    HTML "appearances" of this object's inventory
  1463.      */
  1464.     function getAppearanceInventory($level 0$include_div TRUE,
  1465.             $from NULL$displayMode 'abstract'$displayTitlebar TRUE,
  1466.             $elementId 'dppage')
  1467.     {
  1468.         $inv $this->getInventory();
  1469.         $inventory '';
  1470.         foreach ($inv as &$ob{
  1471.             $inventory .= $ob->getAppearance($level 1$include_div$from,
  1472.                 $displayMode$displayTitlebar$elementId);
  1473.         }
  1474.         $div_id 'dppage' === $elementId 'dpinventory' 'dpobinv';
  1475.  
  1476.         return $inventory == '' ''
  1477.             : "<div id=\"$div_id\"><div class=\"dpinventory2\" id=\""
  1478.                 . "{$this->uniqueId}\">$inventory</div><div class=\"dpclr\">"
  1479.                 . "&nbsp;</div></div>";
  1480.     }
  1481.  
  1482.     /**
  1483.      * Gets a HTML navigation trail for this object
  1484.      *
  1485.      * By default, a 'Home' link is always present.
  1486.      *
  1487.      * @return     string    HTML for navigation trail
  1488.      */
  1489.     function getNavigationTrailHtml()
  1490.     {
  1491.         return '<div id="navlink">' . DPUNIVERSE_NAVLOGO . '</div>';
  1492.     }
  1493.  
  1494.     /**
  1495.      * Adds an examinable 'item' to this object
  1496.      *
  1497.      * 'Items' in objects allow you to perform some basic actions, such as
  1498.      * examine, without making new objects.
  1499.      *
  1500.      * For example, consider this page with the following description:<br />
  1501.      * You are in front of a house. You see a sign.
  1502.      *
  1503.      * The following call will make the house examinable:<br />
  1504.      * <code>add_item('house', 'It is a big, brick house.<br />');</code>
  1505.      *
  1506.      * The $item can be an identifier string or an array with strings with
  1507.      * identifiers, for example array('house', 'brick house'). Such aliases can
  1508.      * be used from the command line, for example 'examine brick house'.
  1509.      *
  1510.      * The $description should be a string with the textual description.
  1511.      *
  1512.      * The $method is optional and should be a string containing a method or an
  1513.      * array with two elements: an object to call and a string with the method.
  1514.      * This method is called at runtime to obtain the description. It should be
  1515.      * defined like this:<br />
  1516.      * <code>function <methodName>($item)</code>
  1517.      * and return a string.<br />
  1518.      * When the $description is NULL, only the result from this method will be
  1519.      * shown. With the $description is a normal string, the result of the method
  1520.      * is appended. When the description has the %s token in it, the result of
  1521.      * the method is inserted there. Example:<br />
  1522.      * <code>add_item('door', 'A solid door. It is %s.', 'getOpenOrClosed');</code>
  1523.      *
  1524.      * The optional $mapArea can be given to make this item accessible on an
  1525.      * imagemap, so people can click on it to examine it. Otherwise the item
  1526.      * can only be examined by using the command line. It should be a map area
  1527.      * id if you set one earlier with setMapArea, or an array with the arguments
  1528.      * to setMapArea to define a new one (see setMapArea documentation for more
  1529.      * information).
  1530.      *
  1531.      * If a map area is used, the action on the imagemap is labelled 'examine'.
  1532.      * This can be overruled by supplying $mapAreaActionMenu, which should be
  1533.      * a string with an alternative label.
  1534.      *
  1535.      * @param      mixed     $item              string or array of strings with
  1536.      *                                          item ids
  1537.      * @param      string    $description       item description
  1538.      * @param      mixed     $method            method for dynamic description
  1539.      * @param      mixed     $mapArea           imagemap area id or definition
  1540.      * @param      mixed     $mapAreaActionMenu action to appear on menu
  1541.      * @see        getItem, getItemDescription, getItems, addAction, setMapArea
  1542.      * @since      DutchPIPE 0.2.0
  1543.      */
  1544.     function addItem($item, $description, $method = NULL, $mapArea = NULL,
  1545.             $mapAreaActionMenu = NULL)
  1546.     {
  1547.         if (is_array($item)) {
  1548.             $tmp = $item[0];
  1549.             if (1 < ($sz = sizeof($item))) {
  1550.                 for ($i = 1; $i < $sz; $i++) {
  1551.                     $this->mItemAliases[$item[$i]] $tmp;
  1552.                 }
  1553.             }
  1554.             $item = $tmp;
  1555.         }
  1556.         $this->mItems[$itemarray($description$method);
  1557.  
  1558.         if (is_null($mapArea)) {
  1559.             return;
  1560.         }
  1561.         if (is_array($mapArea)) {
  1562.             call_user_func_array(array(&$this, 'setMapArea'), $mapArea);
  1563.             $mapArea = $mapArea[1];
  1564.         }
  1565.         if (is_null($mapAreaActionMenu)) {
  1566.             $mapAreaActionMenu = dp_text('examine');
  1567.         }
  1568.         $this->addMapAreaAction($mapArea$mapAreaActionMenu,
  1569.             sprintf(dp_text("examine %s")$item));
  1570.     }
  1571.  
  1572.     /**
  1573.      * Gets an array with data about an item
  1574.      *
  1575.      * An array is returned with two elements: the item description and the item
  1576.      * method. Either can be NULL. If the item was not found, FALSE is returned.
  1577.      *
  1578.      * @param      string    $item            the item id to search for
  1579.      * @return     array     array with data about the given item, or FALSE
  1580.      * @see        addItem, getItemDescription, getItems, addAction, setMapArea
  1581.      * @since      DutchPIPE 0.2.0
  1582.      */
  1583.     function getItem($item)
  1584.     {
  1585.         if (isset($this->mItems[$item])) {
  1586.             return $this->mItems[$item];
  1587.         } elseif (isset($this->mItemAliases[$item])) {
  1588.             return $this->mItems[$this->mItemAliases[$item]];
  1589.         }
  1590.  
  1591.         $articles = explode('#', dp_text('a#an#the'));
  1592.         $space_pos = dp_strpos($item, ' ');
  1593.         if (FALSE !== $space_pos) {
  1594.             $first_word = dp_substr($item, 0, $space_pos);
  1595.             $rest = dp_substr($item, $space_pos + 1);
  1596.             if (in_array($first_word, $articles)) {
  1597.                 return $this->getItem($item);
  1598.             }
  1599.         }
  1600.         return FALSE;
  1601.     }
  1602.  
  1603.     /**
  1604.      * Gets the description of a given item
  1605.      *
  1606.      * Returns the description of the given item, or FALSE if no such item was
  1607.      * found. Items can be added with a method to call (see addItem), here this
  1608.      * method is processed.
  1609.      *
  1610.      * @param      string    $item            the item id to search for
  1611.      * @return     mixed     string with description or FALSE
  1612.      * @see        addItem, getItem, getItems, addAction, setMapArea
  1613.      * @since      DutchPIPE 0.2.0
  1614.      */
  1615.     function getItemDescription($item)
  1616.     {
  1617.         if (isset($this->mItems[$item])) {
  1618.             $item_data =& $this->mItems[$item];
  1619.         } elseif (isset($this->mItemAliases[$item])) {
  1620.             $item_data =& $this->mItems[$this->mItemAliases[$item]];
  1621.         } else {
  1622.             $articles = explode('#', dp_text('a#an#the'));
  1623.             $space_pos = dp_strpos($item, ' ');
  1624.             if (FALSE !== $space_pos) {
  1625.                 $first_word = dp_substr($item, 0, $space_pos);
  1626.                 $rest = dp_substr($item, $space_pos + 1);
  1627.                 if (in_array($first_word, $articles)) {
  1628.                     return $this->getItemDescription($item);
  1629.                 }
  1630.             }
  1631.  
  1632.             return FALSE;
  1633.         }
  1634.  
  1635.         $description = $item_data[0];
  1636.         $method = $item_data[1];
  1637.  
  1638.         if (is_null($method)) {
  1639.             return $description;
  1640.         }
  1641.  
  1642.         $method_description = !is_array($method) ? $this->{$method}($item)
  1643.             : $method[0]->{$method[1]}($item);
  1644.  
  1645.         if (is_null($description) || '' === $description) {
  1646.             return $method_description;
  1647.         }
  1648.  
  1649.         $combined_description = sprintf($description, $method_description);
  1650.  
  1651.         return $combined_description != $description ? $combined_description :
  1652.             $description . $method_description;
  1653.     }
  1654.  
  1655. /**    
  1656.      * Gets an array with all item data added to this object
  1657.      *
  1658.      * @return     array     all items added to this object
  1659.      * @see        addItem, getItem, getItemDescription, addAction, setMapArea
  1660.      * @since      DutchPIPE 0.2.0
  1661.      */
  1662.     function getItems()
  1663.     {
  1664.         return $this->mItems;
  1665.     }
  1666.  
  1667. /**    
  1668.      * Adds an action to the object
  1669.      *
  1670.      * Use this method to have actions added to the menus you get when clicking
  1671.      * on items (the "action menu"), and at the same time to add actions you can
  1672.      * type. See DpLiving.php for some good examples.
  1673.      *
  1674.      * Because of the complexity of this method, it has its own manual page.
  1675.      * See {@tutorial DutchPIPE/actions.pkg} for further information.
  1676.      *
  1677.      * @param      mixed     $actionMenu        title of clickable menu item
  1678.      * @param      mixed     $actionVerb        alternative verb to type
  1679.      * @param      mixed     $actionMethod      method called to perform action
  1680.      * @param      mixed     $actionOperant     on who/what does it have effect?
  1681.      * @param      mixed     $actionTarget      where should menu item appear?
  1682.      * @param      mixed     $actionAuthorized  who may perform this action?
  1683.      * @param      mixed     $actionScope       who sees action to begin with?
  1684.      * @param      mixed     $mapArea           imagemap area id or definition
  1685.      * @param      string    $mapAreaAction     specific action to use
  1686.      * @see        removeAction, getActionData,  getActionsMenu, setMapArea
  1687.      * @tutorial   DutchPIPE/actions.pkg
  1688.      */
  1689.     final public function addAction($actionMenu, $actionVerb, $actionMethod,
  1690.             $actionOperant = DP_ACTION_OPERANT_MENU,
  1691.             $actionTarget = DP_ACTION_TARGET_SELF,
  1692.             $actionAuthorized = DP_ACTION_AUTHORIZED_ALL,
  1693.             $actionScope = DP_ACTION_SCOPE_ALL,
  1694.             $mapArea = NULL,
  1695.             $mapAreaAction = NULL)
  1696.     {
  1697.         if (is_array($actionVerb)) {
  1698.             $tmp = $actionVerb[0];
  1699.             if (!isset($this->mActions[$tmp])) {
  1700.                 $new_key = 0;
  1701.             } else {
  1702.                 end($this->mActions[$tmp]);
  1703.                 $new_key = key($this->mActions[$tmp]) + 1;
  1704.                 reset($this->mActions[$tmp]);
  1705.             }
  1706.             if (1 < ($sz = sizeof($actionVerb))) {
  1707.                 for ($i = 1; $i < $sz; $i++) {
  1708.                     if (!isset($this->mActionAliases[$actionVerb[$i]])) {
  1709.                         $this->mActionAliases[$actionVerb[$i]] = array();
  1710.                     }
  1711.                     $this->mActionAliases[$actionVerb[$i]][] =
  1712.                         array($tmp, $new_key);
  1713.                 }
  1714.             }
  1715.             $actionVerb = $tmp;
  1716.         }
  1717.  
  1718.         if (!isset($this->mActions[$actionVerb])) {
  1719.             $this->mActions[$actionVerb] = array();
  1720.         }
  1721.         $this->mActions[$actionVerb][] = array($actionMenu, $actionMethod,
  1722.             $actionOperant, $actionTarget, $actionAuthorized, $actionScope,
  1723.             $mapArea, $mapAreaAction);
  1724.         end($this->mActions[$actionVerb]);
  1725.         if (!is_null($mapArea)) {
  1726.             if (is_array($mapArea)) {
  1727.                 call_user_func_array(array(&$this, 'setMapArea'), $mapArea);
  1728.                 $mapArea = $mapArea[1];
  1729.             }
  1730.             if (is_null($mapAreaAction)) {
  1731.                 $mapAreaAction = "{$actionVerb} {$this->uniqueId}";
  1732.             }
  1733.  
  1734.             $this->addMapAreaAction($mapArea$actionMenu,
  1735.                 $mapAreaAction$actionVerb,
  1736.                 key($this->mActions[$actionVerb]));
  1737.         }
  1738.     }
  1739.  
  1740.     /**
  1741.      * Removes the given action.
  1742.      *
  1743.      * Removes the action associated to the given $actionVerb. If the action was
  1744.      * linked to an imagemap area, provide the area id with $mapAreaId to
  1745.      * delete this information as well.
  1746.      *
  1747.      * @param      boolean   $actionVerb  alternative command to type
  1748.      * @param      string    $mapAreaId   imagemap area id
  1749.      * @see        addAction, getActionData, getActionsMenu
  1750.      * @since      DutchPIPE 0.2.0
  1751.      */
  1752.     final public function removeAction($actionVerb, $mapAreaId = NULL)
  1753.     {
  1754.         $action_nr = -1;
  1755.         if (isset($this->mActionAliases[$actionVerb])) {
  1756.             $actionVerb = $this->mActionAliases[$actionVerb][0];
  1757.             $action_nr = $this->mActionAliases[$actionVerb][1];
  1758.         }
  1759.  
  1760.         if (isset($this->mActions[$actionVerb])) {
  1761.             if (isset($this->mActions[$actionVerb][$action_nr])) {
  1762.                 $this->_removeAction($actionVerb, $action_nr);
  1763.             }
  1764.             foreach ($this->mActions[$actionVerb] as
  1765.                     $action_nr => &$action_data) {
  1766.                 $this->_removeAction($actionVerb, $action_nr, $mapAreaId);
  1767.             }
  1768.         }
  1769.     }
  1770.  
  1771.     /**
  1772.      * Helper method for removeAction
  1773.      *
  1774.      * @access     private
  1775.      * @param      boolean   $actionVerb  alternative command to type
  1776.      * @param      integer   &$action_nr  index of the verb in alternatives list
  1777.      * @param      string    $mapAreaId   imagemap area id
  1778.      * @see        removeAction
  1779.      * @since      DutchPIPE 0.2.0
  1780.      */
  1781.     private function _removeAction($actionVerb, $actionNr, $mapAreaId = NULL)
  1782.     {
  1783.         $action_data =& $this->mActions[$actionVerb][$actionNr];
  1784.  
  1785.         $map_area_id = $action_data[6];
  1786.         if (is_null($mapAreaId) || (!is_null($map_area_id)
  1787.                 && $mapAreaId === $map_area_id)) {
  1788.             if (!is_null($map_area_id)) {
  1789.                 $this->removeMapAreaAction($map_area_id,
  1790.                     $action_data[0],
  1791.                     $action_data[7]);
  1792.             }
  1793.             unset($this->mActions[$actionVerb][$actionNr]);
  1794.             if (0 === count($this->mActions[$actionVerb])) {
  1795.                 unset($this->mActions[$actionVerb]);
  1796.             }
  1797.         }
  1798.     }
  1799.  
  1800.     /**
  1801.      * Gets data of one, multiple or all actions
  1802.      *
  1803.      * Without arguments, an array is returned with each element of pair
  1804.      * consisting of:
  1805.      * verb => array(menulabel, method, operant, target, authorized, scope)
  1806.      * with operant one of DP_ACTION_OPERANT_, target one of DP_ACTION_TARGET_,
  1807.      * authorized one of DP_ACTION_AUTHORIZED_ and scope one of DP_ACTION_SCOPE_
  1808.      * from dpuniverse/include/actions.php, for example:
  1809.      * 'read' => array('read me!', 'actionRead', DP_ACTION_OPERANT_MENU,
  1810.      *     DP_ACTION_TARGET_SELF, DP_ACTION_AUTHORIZED_ALL, DP_ACTION_SCOPE_ALL)
  1811.      *
  1812.      * You can narrow the result set down by supplying a verb, in which case an
  1813.      * array with one or more results is returned, or FALSE if the given verb is
  1814.      * not defined as an action.
  1815.      *
  1816.      * Narrow it down further by giving a number, usually 0, to get the data at
  1817.      * the index of the array you would get without supplying a number.
  1818.      *
  1819.      * @param      boolean   $actionVerb  alternative command to type
  1820.      * @param      integer   &$actionNr   index of the verb in alternatives list
  1821.      * @return     array     array with actions, can be empty
  1822.      * @see        addAction, removeAction, getActionsMenu
  1823.      * @since      DutchPIPE 0.2.1
  1824.      */
  1825.     final function getActionData($actionVerb = NULL, $actionNr = NULL)
  1826.     {
  1827.         if (is_null($actionVerb)) {
  1828.             return $this->mActions;
  1829.         }
  1830.  
  1831.         if (!isset($this->mActions[$actionVerb])) {
  1832.             return FALSE;
  1833.         }
  1834.  
  1835.         if (is_null($actionNr)) {
  1836.             return $this->mActions[$actionVerb];
  1837.         }
  1838.  
  1839.         if (!isset($this->mActions[$actionVerb][$actionNr])) {
  1840.             return FALSE;
  1841.         }
  1842.  
  1843.         return $this->mActions[$actionVerb][$actionNr];
  1844.     }
  1845.  
  1846.     /**
  1847.      * Tells the current user the HTML with the action menu for this object
  1848.      *
  1849.      * @see        addAction, removeAction, getActionData, getTargettedActions
  1850.      */
  1851.     function getActionsMenu()
  1852.     {
  1853.         /*
  1854.          * A checksum is bounced back so the client can find the right
  1855.          * response
  1856.          */
  1857.         if (!($user = get_current_dpuser())
  1858.                 || !isset($user->_GET['checksum'])) {
  1859.             return;
  1860.         }
  1861.  
  1862.         $user->lastActionTime = !isset($user->lastActionTime)
  1863.             ? new_dp_property(time()) : time();
  1864.  
  1865.         if (!($rval = $this->_getActionsMenuLevels($user))) {
  1866.             return;
  1867.         }
  1868.         list($lvl_titles, $lvl_cnt, $lvl_last_title) = $rval;
  1869.  
  1870.         if (!isset($user->_GET['map_name'])
  1871.                 || !isset($user->_GET['map_area_id'])) {
  1872.             $actions = $this->getTargettedActions($user,
  1873.                 is_null($lvl_last_title) ? NULL : $lvl_titles);
  1874.         } else {
  1875.             $actions = $this->getTargettedActions($user,
  1876.                 (is_null($lvl_last_title) ? NULL : $lvl_titles),
  1877.                 $user->_GET['map_area_id']);
  1878.             /*
  1879.              * For map area actions, when there's only one action, don't show a
  1880.              * menu, but execute action immediately
  1881.              */
  1882.             if (1 === count($actions) && 0 === $lvl_cnt) {
  1883.                 reset($actions);
  1884.                 $user->_GET['menuaction'] = '1';
  1885.                 $user->performAction($actions[key($actions)][0]);
  1886.                 return;
  1887.             }
  1888.         }
  1889.  
  1890.         if (!count($actions)) {
  1891.             return;
  1892.         }
  1893.  
  1894.         $action_menu = '';
  1895.  
  1896.         $icon_used = $submenu_used = FALSE;
  1897.         foreach ($actions as $action_menu_title => &$action_data) {
  1898.             /* If set to FALSE, inserts action into the command line */
  1899.             $get_operant = FALSE;
  1900.             $is_submenu = is_array($action_data) && $action_data[6];
  1901.  
  1902.             $icon = '&nbsp;';
  1903.             $icon_over = FALSE;
  1904.  
  1905.             if (is_array($action_data) && $action_data[4]) {
  1906.                 $icon = $action_data[4];
  1907.                 if ($action_data[5]) {
  1908.                     $icon_over = $action_data[5];
  1909.                 }
  1910.                 $icon_used = TRUE;
  1911.             }
  1912.  
  1913.             list($actionstr, $send_action, $ghosted) =
  1914.                 $this->_getActionsMenuFullAction($action_data, $user);
  1915.  
  1916.             if ((!isset($user->inputMode) || 'say' !== $user->inputMode)
  1917.                     && '' === $actionstr) {
  1918.                 $get_operant = $is_submenu = TRUE;
  1919.             }
  1920.  
  1921.             if (!$ghosted) {
  1922.                 $gstyle = $gdstyle = $gdsstyle = '';
  1923.             } else {
  1924.                 $gstyle = ' am_ghosted';
  1925.                 $gdstyle = ' am_deep_ghosted';
  1926.                 $gdsstyle = ' am_deep_selected_ghosted';
  1927.             }
  1928.  
  1929.             $mouseover = "if (action_over(this)) { ";
  1930.             $add_to_mouseover = '';
  1931.             $mouseout = $mouseclick = '';
  1932.  
  1933.             if (!$lvl_cnt && !$is_submenu) {
  1934.                 $mouseover .= "jQuery('div.am_deep_selected')."
  1935.                     . "removeClass('am_deep_selected am_selected$gdsstyle')";
  1936.                 $add_to_mouseover = '; ';
  1937.             }
  1938.             if (!$is_submenu || $ghosted) {
  1939.                 $mouseout = "am_target_out = this";
  1940.                 $mouseclick = $ghosted ? 'am_no_close = true'
  1941.                     : ((FALSE === $send_action ? 'show_input'
  1942.                     : 'send_action2server') . "('" .
  1943.                     addslashes(htmlspecialchars($actionstr)) . "')");
  1944.             } else {
  1945.                 $submenu_used = TRUE;
  1946.                 $mouseover .= $add_to_mouseover
  1947.                     . "jQuery(this).addClass('am_deep_selected" . $gdsstyle
  1948.                     . "'); " . (isset($user->_GET['map_area_id'])
  1949.                     ? "get_map_area_actions('{$user->_GET['map_name']}', "
  1950.                     "'{$user->_GET['map_area_id']}', "
  1951.                     "get_actions(")
  1952.                     . "'{$this->uniqueId}', event, ";
  1953.  
  1954.                 for ($i = 0; $i < $lvl_cnt; $i++) {
  1955.                     $mouseover .= "'"
  1956.                         . addslashes(htmlspecialchars($lvl_titles[$i])) . "', ";
  1957.                 }
  1958.  
  1959.                 $mouseover .= "'"
  1960.                     . addslashes(htmlspecialchars($action_menu_title)) . "')";
  1961.  
  1962.                 $add_to_mouseover = '; ';
  1963.                 $mouseclick = 'am_no_close = true';
  1964.             }
  1965.  
  1966.             if ($icon_over) {
  1967.                 $mouseover .= $add_to_mouseover
  1968.                     . "jQuery('span.am_icon', this).attr('id', "
  1969.                     . "jQuery('span.am_icon > img', this).attr('src')); "
  1970.                     . "jQuery('span.am_icon > img', this).attr('src', "
  1971.                     . "'{$icon_over}')";
  1972.             }
  1973.  
  1974.             $mouseover .= '}';
  1975.  
  1976.             $action_menu .= '<div id="action_menu' . $lvl_cnt . '" '
  1977.                 . 'class="am' . (!$is_submenu ? '' : ' am_deep' . $gdstyle)
  1978.                 . $gstyle . '" onmouseover="' . $mouseover
  1979.                 . '" onmouseout="' . $mouseout
  1980.                 . '" onclick="' . $mouseclick . '">'
  1981.                 . '<span class="AM_ICON" id=' . $icon_over . '>' . $icon
  1982.                 . '</span>'
  1983.                 . '<span class="am_title">' . $action_menu_title . '</span>'
  1984.                 . '<span class="AM_SUBMENU">&nbsp;</span>&nbsp;'
  1985.                 . '<br clear="all" /></div>' . "\n";
  1986.         }
  1987.  
  1988.         $action_menu = str_replace(array('AM_ICON', 'AM_SUBMENU'),
  1989.             array((!$icon_used ? 'am_empty' : 'am_icon'),
  1990.             (!$submenu_used ? 'am_empty2' : 'am_submenu')), $action_menu);
  1991.  
  1992.         $user->tell('<actions id="' . $this->uniqueId
  1993.             . '" level="' . $lvl_cnt . '" checksum="' . $user->_GET['checksum']
  1994.             . '"><div class="actionwindow_inner">' . $action_menu
  1995.             . '</div></actions>');
  1996.     }
  1997.  
  1998.     /**
  1999.      * Gets information about the current trail of menu and submenus
  2000.      *
  2001.      * Used by getActionsMenu.
  2002.      *
  2003.      * @access     private
  2004.      * @param      object    &$user        performer of actions
  2005.      * @return     array     data structure with level info
  2006.      * @see        getActionsMenu
  2007.      * @since      DutchPIPE 0.3.0
  2008.      */
  2009.     private function &_getActionsMenuLevels(&$user)
  2010.     {
  2011.         /*
  2012.          * If the user is navigating to submenus, the client passes each menu
  2013.          * title leading to the submenu, for example:
  2014.          * &l1=foo&l2=bar
  2015.          */
  2016.         $lvl_titles = array();
  2017.         $lvl_cnt = 0;
  2018.         $lvl_last_title = NULL;
  2019.         while (isset($user->_GET['l' . ($lvl_cnt + 1)])) {
  2020.             $lvl_cnt++;
  2021.             $lvl_titles[] = $lvl_last_title = $user->_GET['l' . $lvl_cnt];
  2022.         }
  2023.         $rval = array($lvl_titles, $lvl_cnt, $lvl_last_title);
  2024.  
  2025.         return $rval;
  2026.     }
  2027.  
  2028.     /**
  2029.      * Gets actions which can be performed on this object, for action menu
  2030.      *
  2031.      * Gets an array with actions which can be performed on this object, so
  2032.      * we can make a menu when hovering over the object image with the mouse.
  2033.      * This includes actions that are defined by other objects but appear in
  2034.      * this object's action menu.
  2035.      *
  2036.      * An array is returned, empty if there are no menu actions found, with
  2037.      * key-value pairs. Each key is the (first) menu title associated with the
  2038.      * action pair, each value an array of three elements: the verb, the
  2039.      * "operant" as defined with addAction and a boolean indicating whether this
  2040.      * menu item is ghosted.
  2041.      *
  2042.      * @param      object    &$user      user getting the menu
  2043.      * @param      array     $levels     current path of user in (sub)menu
  2044.      * @param      string    $mapAreaId  id of area in imagemap
  2045.      * @return     array     array with menu actions, can be empty
  2046.      * @see        getActionsMenu
  2047.      */
  2048.     function &getTargettedActions(&$user, $levels = NULL, $mapAreaId = NULL)
  2049.     {
  2050.         /* Gets menu actions on this object defined by this object */
  2051.         $actions = $this->_getTargettedActions($this, $user, $levels,
  2052.             $mapAreaId);
  2053.  
  2054.         /*
  2055.          * Gets menu actions on this object defined by objects in inventory:
  2056.          */
  2057.         $inv = $this->getInventory();
  2058.         foreach ($inv as &$ob) {
  2059.             $actions = array_merge($actions,
  2060.                 $this->_getTargettedActions($ob, $user, $levels, $mapAreaId));
  2061.         }
  2062.  
  2063.         /*
  2064.          * Gets menu actions on this object defined by objects in this
  2065.          * object's environment:
  2066.          */
  2067.         $env = $this->getEnvironment();
  2068.         if (FALSE !== $env) {
  2069.             $inv = $env->getInventory();
  2070.             foreach ($inv as &$ob) {
  2071.                 if ($ob !== $this) {
  2072.                     $actions = array_merge($actions,
  2073.                         $this->_getTargettedActions($ob, $user, $levels,
  2074.                         $mapAreaId));
  2075.                 }
  2076.             }
  2077.  
  2078.             /*
  2079.              * Gets menu actions on this object defined by the object's
  2080.              * environment:
  2081.              */
  2082.             $actions = array_merge($actions,
  2083.                 $this->_getTargettedActions($env, $user, $levels, $mapAreaId));
  2084.         }
  2085.  
  2086.         return $actions;
  2087.     }
  2088.  
  2089.     /**
  2090.      * Gets actions that can be performed on a given object by a given user
  2091.      *
  2092.      * An array is returned with each element a pair consisting of:
  2093.      *     menulabel => array(verb, operant, ghosted)
  2094.      * with operant one of DP_ACTION_OPERANT_ from
  2095.      * dpuniverse/include/actions.php, for example:
  2096.      * 'read me!' => array('read', DP_ACTION_OPERANT_MENU, FALSE)
  2097.      *
  2098.      * @access     private
  2099.      * @param      object    &$ob        target of actions
  2100.      * @param      object    &$user      performer of actions
  2101.      * @param      array     $levels     current path of user in (sub)menu
  2102.      * @param      string    $mapAreaId  id of area in imagemap
  2103.      * @return     array     array with actions, can be empty
  2104.      * @see        getTargettedActions, _checkTargettedAction
  2105.      * @since      DutchPIPE 0.3.0
  2106.      */
  2107.     private function &_getTargettedActions(&$ob, &$user, $levels = NULL,
  2108.             $mapAreaId = NULL)
  2109.     {
  2110.         $ob_actions = is_null($mapAreaId) ? $ob->getActionData()
  2111.             : $ob->getMapAreaActions($mapAreaId);
  2112.  
  2113.         if (FALSE === $ob_actions || !count($ob_actions)) {
  2114.             $ob_actions = array();
  2115.             return $ob_actions;
  2116.         }
  2117.         $t_actions = array();
  2118.  
  2119.         $is_registered = isset($user->isRegistered)
  2120.             && $this->isRegistered === TRUE;
  2121.         $is_admin = isset($user->isAdmin) && $user->isAdmin === TRUE;
  2122.  
  2123.         $level = !is_array($levels) ? 0 : count($levels);
  2124.         if (is_null($mapAreaId)) {
  2125.             foreach ($ob_actions as $verb => &$a_d) {
  2126.                 foreach ($a_d as $action_data) {
  2127.                     if (FALSE === $this->_addTargettedAction($t_actions,
  2128.                             $verb, $action_data, $ob, $user, $level, $levels,
  2129.                             $is_registered, $is_admin)) {
  2130.                         continue;
  2131.                     }
  2132.                 }
  2133.             }
  2134.         } else {
  2135.             foreach ($ob_actions as $action_data) {
  2136.                 if (FALSE === $this->_addTargettedAction($t_actions, NULL,
  2137.                         $action_data, $ob, $user, $level, $levels,
  2138.                         $is_registered, $is_admin)) {
  2139.                     continue;
  2140.                 }
  2141.             }
  2142.         }
  2143.         return $t_actions;
  2144.     }
  2145.  
  2146.     /**
  2147.      * Adds action that can be performed on a given object by a given user
  2148.      *
  2149.      * Used by _getTargettedActions.
  2150.      *
  2151.      * @access     private
  2152.      * @param      array     &$t_actions   targetted actions found so far
  2153.      * @param      string    $verb         associated verb for this action
  2154.      * @param      array     &$actionData  complete action data
  2155.      * @param      object    &$ob          target of actions
  2156.      * @param      object    &$user        performer of actions
  2157.      * @param      integer   $level        submenu level, starts at 0
  2158.      * @param      array     $levels       sublevel titles
  2159.      * @param      boolean   $isRegistered is performer a registered user?
  2160.      * @param      boolean   $isAdmin      is performer an administrator?
  2161.      * @return     array     array with actions, can be empty
  2162.      * @see        _getTargettedActions
  2163.      * @since      DutchPIPE 0.3.0
  2164.      */
  2165.     private function _addTargettedAction(&$t_actions, $verb, &$actionData,
  2166.             &$ob, &$user, $level, &$levels, $isRegistered, $isAdmin)
  2167.     {
  2168.         $get_operant = FALSE;
  2169.         $add_operant = 0;
  2170.         $verb_data = $operant = NULL;
  2171.  
  2172.         $is_map_area = is_null($verb);
  2173.         if (1 || $level) {
  2174.             if ($is_map_area) {
  2175.                 if (!is_null($actionData[2]) && !is_null($actionData[3])) {
  2176.                     $verb_data = $ob->getActionData($actionData[2],
  2177.                         $actionData[3]);
  2178.                     $operant = $verb_data[2];
  2179.                     $verb = $verb_data[2];
  2180.                 } else {
  2181.                     $operant = <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_OPERANT_MENU">DP_ACTION_OPERANT_MENU</a>;
  2182.                     $verb = $actionData[1];
  2183.                 }
  2184.             } else {
  2185.                 $operant = $actionData[2];
  2186.             }
  2187.  
  2188.             parse_dp_callable($actionData[0], $verb, $this, $ob, $user);
  2189.  
  2190.             if (is_array($operant) && 2 === count($operant)
  2191.                     && is_object($operant[0])) {
  2192.                 $operant = $operant[0]->{$operant[1]}($verb, $this, $ob,
  2193.                     $user);
  2194.             } elseif (DP_ACTION_OPERANT_METHOD === $operant) {
  2195.                 $operant = $this->getActionOperant($verb, $this, $ob,
  2196.                     $user);
  2197.             }
  2198.             if (is_array($operant) ||
  2199.                     DP_ACTION_OPERANT_METHOD_MENU === $operant) {
  2200.                 $get_operant = TRUE;
  2201.                 $add_operant = 1;
  2202.                 if (is_array($actionData[0]) && count($actionData[0])
  2203.                         < $level - $add_operant) {
  2204.                     return FALSE;
  2205.                 }
  2206.             } elseif (is_array($actionData[0])
  2207.                     && count($actionData[0]) < $level) {
  2208.                 return FALSE;
  2209.             }
  2210.  
  2211.             for ($i = 0; $i < $level; $i++) {
  2212.                 $action_menu_title = !is_array($actionData[0])
  2213.                     ? $actionData[0] : $actionData[0][$i];
  2214.                 if (FALSE !== ($pos = dp_strrpos($action_menu_title, '#'))) {
  2215.                     $action_menu_title = dp_substr($action_menu_title,
  2216.                         $pos + 1);
  2217.                 }
  2218.  
  2219.                 if (!is_array($actionData[0])) {
  2220.                     if (0 === $i && $levels[0] === $action_menu_title) {
  2221.                         continue;
  2222.                     }
  2223.                     return FALSE;
  2224.                 }
  2225.                 if ($levels[$i] <> $action_menu_title) {
  2226.                     return FALSE;
  2227.                 }
  2228.             }
  2229.         }
  2230.  
  2231.         $ghosted = FALSE;
  2232.         if (!$is_map_area) {
  2233.             if (FALSE ===
  2234.                     $this->_checkTargettedAction($verb, $actionData, $ob,
  2235.                     $user, $isRegistered, $isAdmin)) {
  2236.                 return FALSE;
  2237.             }
  2238.             parse_dp_callable($actionData[4], $verb, $this, $ob, $user);
  2239.             $ghosted = <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_AUTHORIZED_DISABLED">DP_ACTION_AUTHORIZED_DISABLED</a> & $actionData[4];
  2240.         } else {
  2241.             if (!is_null($actionData[2]) && !is_null($actionData[3])) {
  2242.                 if (is_null($verb_data)) {
  2243.                     $verb_data = $ob->getActionData($actionData[2],
  2244.                         $actionData[3]);
  2245.                 }
  2246.  
  2247.                 if (!$get_operant && FALSE === $this->_checkTargettedAction(
  2248.                         $actionData[2], $verb_data, $ob, $user, $isRegistered,
  2249.                         $isAdmin)) {
  2250.                     return FALSE;
  2251.                 }
  2252.                 if (is_array($verb_data)) {
  2253.                     parse_dp_callable($verb_data[4], $verb, $this, $ob, $user);
  2254.                     $ghosted = <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_AUTHORIZED_DISABLED">DP_ACTION_AUTHORIZED_DISABLED</a> & $verb_data[4];
  2255.                 }
  2256.             }
  2257.         }
  2258.  
  2259.         if (!$get_operant || $ghosted || ($level < (!is_array($actionData[0])
  2260.                 ? 1 : count($actionData[0])))) {
  2261.             $titles =& $actionData[0];
  2262.             if (is_string($titles)) {
  2263.                 $title = $titles;
  2264.             } elseif (is_array($titles)) {
  2265.                 if (2 !== count($titles) || !is_object($titles[0])) {
  2266.                     parse_dp_callable($titles[$level], $verb, $this,
  2267.                         $ob, $user);
  2268.                 } else {
  2269.                     parse_dp_callable($titles, $verb, $this, $ob,
  2270.                         $user);
  2271.                 }
  2272.  
  2273.                 $title = !is_array($titles) ? $titles : $titles[$level];
  2274.             } else {
  2275.                 return FALSE;
  2276.             }
  2277.  
  2278.             $icon = $icon_over = FALSE;
  2279.             if (FALSE !== dp_strpos($title, '#')) {
  2280.                 $tmp = explode('#', $title);
  2281.                 if (2 == count($tmp)) {
  2282.                     $icon = $tmp[0];
  2283.                     $title = $tmp[1];
  2284.                 } elseif (3 == count($tmp)) {
  2285.                     $icon = $tmp[0];
  2286.                     $icon_over = $tmp[1];
  2287.                     $title = $tmp[2];
  2288.                 }
  2289.             }
  2290.  
  2291.             $cnt = !is_array($titles) ? 1 : count($titles);
  2292.             $is_submenu = $cnt > $level + 1
  2293.                 - ($ghosted && $level + 1 === $cnt ? 0 : $add_operant);
  2294.  
  2295.             $data = !$is_map_area
  2296.                 ? array($verb, $actionData[2], $ghosted, $ob, $icon,
  2297.                     $icon_over, $is_submenu)
  2298.                 : array($actionData[1], (is_null($verb_data)
  2299.                     ? <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_OPERANT_MENU">DP_ACTION_OPERANT_MENU</a> : $verb_data[2]), $ghosted, $ob,
  2300.                     $icon, $icon_over, $is_submenu);
  2301.  
  2302.             $t_actions[$title] = $data;
  2303.         } elseif ($get_operant) {
  2304.             if (is_array($operant) && 2 === count($operant)
  2305.                     && is_object($operant[0])) {
  2306.                 $data = $operant[0]->{$operant[1]}($verb, $this, $ob,
  2307.                     $user);
  2308.             } elseif (DP_ACTION_OPERANT_METHOD_MENU === $operant) {
  2309.                 $data = $ob->getActionOperantMenu($verb, $this, $ob,
  2310.                     $user);
  2311.             }
  2312.             if ($data && is_array($data)) {
  2313.                 $t_actions += $data;
  2314.             }
  2315.         }
  2316.  
  2317.         return TRUE;
  2318.     }
  2319.  
  2320. /**    
  2321.      * Checks if an action can be included in an action menu
  2322.      *
  2323.      * Processes DP_ACTION_TARGET_, DP_ACTION_SCOPE_ and DP_ACTION_AUTHORIZED_
  2324.      * directives of the action.
  2325.      *
  2326.      * @access     private
  2327.      * @param      string    $verb          associated verb for this action
  2328.      * @param      array     &$actionData   complete action data
  2329.      * @param      object    &$ob           target of actions
  2330.      * @param      object    &$user         performer of actions
  2331.      * @param      boolean   $isRegistered  is performer a registered user?
  2332.      * @param      boolean   $isAdmin       is performer an administrator?
  2333.      * @return     boolean   TRUE to include action, FALSE to exclude
  2334.      * @see        getTargettedActions, _getTargettedActions
  2335.      * @since      DutchPIPE 0.2.1
  2336.      */
  2337.     private function _checkTargettedAction($verb, &$actionData, &$ob, &$user,
  2338.             $isRegistered = FALSE, $isAdmin = FALSE)
  2339.     {
  2340.         $target =& $actionData[3];
  2341.         parse_dp_callable($target, $verb, $this, $ob, $user);
  2342.  
  2343.         if (is_array($target) && 2 === count($target) && isset($target[0])
  2344.                 && is_object($target[0]) && isset($target[1])
  2345.                 && is_integer($target[1])) {
  2346.             $ob =& $target[0];
  2347.             $target = $target[1];
  2348.         }
  2349.  
  2350.         if ($target === <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_TARGET_NONE">DP_ACTION_TARGET_NONE</a>) {
  2351.             return FALSE;
  2352.         }
  2353.  
  2354.         $compare = 0;
  2355.  
  2356.         if ($ob === $this) {
  2357.             $compare = $compare | <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_TARGET_SELF">DP_ACTION_TARGET_SELF</a>;
  2358.         } else {
  2359.             if (isset($this->isLiving) && TRUE === $this->isLiving) {
  2360.                 $compare = $compare | <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_TARGET_LIVING">DP_ACTION_TARGET_LIVING</a>;
  2361.  
  2362.                 if (isset($this->isUser) && TRUE === $this->isUser) {
  2363.                     $compare = $compare | <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_TARGET_USER">DP_ACTION_TARGET_USER</a>;
  2364.                 }
  2365.             } elseif (FALSE !== ($this_env = $this->getEnvironment())
  2366.                     && FALSE !== ($ob_env = $ob->getEnvironment())
  2367.                     && $this_env === $ob_env) {
  2368.                 $compare = $compare | <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_TARGET_OBJENV">DP_ACTION_TARGET_OBJENV</a>;
  2369.             } elseif (FALSE !== ($this_env = $this->getEnvironment())
  2370.                     && $this_env === $ob) {
  2371.                 $compare = $compare | <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_TARGET_OBJINV">DP_ACTION_TARGET_OBJINV</a>;
  2372.             }
  2373.         }
  2374.  
  2375.         if (!($target & $compare)) {
  2376.             return FALSE;
  2377.         }
  2378.  
  2379.         $scope =& $actionData[5];
  2380.         parse_dp_callable($scope, $verb, $this, $ob, $user);
  2381.  
  2382.         if (is_array($scope) && 2 === count($scope) && isset($scope[0])
  2383.                 && is_object($scope[0]) && isset($scope[1])
  2384.                 && is_integer($scope[1])) {
  2385.             $ob =& $scope[0];
  2386.             $scope = $scope[1];
  2387.         }
  2388.  
  2389.         if ($scope & <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_SCOPE_SELF">DP_ACTION_SCOPE_SELF</a>) {
  2390.             if ($user !== $ob) {
  2391.                 return FALSE;
  2392.             }
  2393.         }
  2394.         if ($scope & <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_SCOPE_INVENTORY">DP_ACTION_SCOPE_INVENTORY</a>) {
  2395.             if ($user->getEnvironment() !== $ob) {
  2396.                 return FALSE;
  2397.             }
  2398.         }
  2399.         if ($scope & <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_SCOPE_ENVIRONMENT">DP_ACTION_SCOPE_ENVIRONMENT</a>) {
  2400.             if ($user->getEnvironment() !== $ob->getEnvironment()) {
  2401.                 return FALSE;
  2402.             }
  2403.         }
  2404.  
  2405.         $auth =& $actionData[4];
  2406.         parse_dp_callable($auth, $verb, $this, $ob, $user);
  2407.  
  2408.         if ($auth & <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_AUTHORIZED_GUEST">DP_ACTION_AUTHORIZED_GUEST</a>) {
  2409.             if (TRUE === $isRegistered) {
  2410.                 return FALSE;
  2411.             }
  2412.         } elseif ($auth & <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_AUTHORIZED_REGISTERED">DP_ACTION_AUTHORIZED_REGISTERED</a>) {
  2413.             if (TRUE !== $isRegistered) {
  2414.                 return FALSE;
  2415.             }
  2416.         } elseif ($auth & <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_AUTHORIZED_ADMIN">DP_ACTION_AUTHORIZED_ADMIN</a>) {
  2417.             if (TRUE !== $isAdmin) {
  2418.                 return FALSE;
  2419.             }
  2420.         }
  2421.  
  2422.         return TRUE;
  2423.     }
  2424.  
  2425. /**    
  2426.      * Gets the full action string for an action and some other data
  2427.      *
  2428.      * Used by getActionsMenu.
  2429.      *
  2430.      * @access     private
  2431.      * @param      array     &$actionData   action data array
  2432.      * @param      object    &$user          performer of actions
  2433.      * @return     array     data structure with action info
  2434.      * @see        getActionsMenu
  2435.      * @since      DutchPIPE 0.3.0
  2436.      */
  2437.     private function _getActionsMenuFullAction(&$actionData, $user)
  2438.     {
  2439.         $send_action = TRUE;
  2440.         $is_submenu = is_array($actionData) && $actionData[6];
  2441.         $gstyle = $gdstyle = $gdsstyle = '';
  2442.         $ghosted = FALSE;
  2443.  
  2444.         if (!$is_submenu && is_array($actionData)) {
  2445.             $action = $actionData[0];
  2446.             $operant = $actionData[1];
  2447.             $ghosted = $actionData[2];
  2448.             $defined_by = $actionData[3];
  2449.             if ($ghosted) {
  2450.                 $actionstr = '';
  2451.             } else {
  2452.                 if (is_array($operant) && 2 === count($operant)
  2453.                         && is_object($operant[0])) {
  2454.                     $operant = $operant[0]->{$operant[1]}($action, $this,
  2455.                         $defined_by, $user);
  2456.                 } elseif (DP_ACTION_OPERANT_METHOD === $operant) {
  2457.                     $operant = $this->getActionOperant($action, $this,
  2458.                         $defined_by, $user);
  2459.                 }
  2460.                 if (is_array($operant) ||
  2461.                         DP_ACTION_OPERANT_METHOD_MENU === $operant) {
  2462.                     $actionstr = '';
  2463.                 } elseif (<a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_OPERANT_MENU">DP_ACTION_OPERANT_MENU</a> === $operant) {
  2464.                     $actionstr = isset($user->_GET['map_area_id']) ? $action
  2465.                         : $action . ' ' . $this->uniqueId;
  2466.                 } elseif (<a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_OPERANT_NONE">DP_ACTION_OPERANT_NONE</a> === $operant) {
  2467.                     $actionstr = $action;
  2468.                 } elseif (is_string($operant)) {
  2469.                     $actionstr = $action . ' ' . $operant;
  2470.                     if (dp_strlen($actionstr)
  2471.                             && ' ' === dp_substr($actionstr, -1)) {
  2472.                         if (isset($user->inputMode)
  2473.                                 && 'say' === $user->inputMode
  2474.                                 && dp_text('say') !== $action) {
  2475.                             $actionstr = '/' . $actionstr;
  2476.                         }
  2477.                         $send_action = FALSE;
  2478.                     }
  2479.                 } else {
  2480.                     /* DP_ACTION_OPERANT_COMPLETE */
  2481.                     $actionstr = $action . ' ';
  2482.                     if (isset($user->inputMode) && 'say' === $user->inputMode) {
  2483.                         $actionstr = dp_text('say') === $action ? ''
  2484.                             : '/' . $actionstr;
  2485.                     }
  2486.                     $send_action = FALSE;
  2487.                 }
  2488.             }
  2489.         } else {
  2490.             $actionstr = is_string($actionData) ? $actionData : '';
  2491.         }
  2492.  
  2493.         return array($actionstr, $send_action, $ghosted, $gstyle, $gdstyle,
  2494.             $gdsstyle);
  2495.     }
  2496.  
  2497. /**    
  2498.      * Creates a new imagemap area which can be used by actions
  2499.      *
  2500.      * Creates an area for the imagemap $mapName. Make sure the right <map> and
  2501.      * <area> HTML is included when this object is viewed. The image should have
  2502.      * the following tag:
  2503.      *     usemap="#<map name>"
  2504.      *
  2505.      * The id given with $mapAreaId can be used by others methods, such as
  2506.      * addItem or addAction to refer to this area.
  2507.      *
  2508.      * The shape of the imagemap given with $mapAreaShape is one of:
  2509.      *     circle, poly, rect
  2510.      * See your HTML reference for a full explanation of these types.
  2511.      *
  2512.      * The coordinates of the shape should be given with $mapAreaCoords, for
  2513.      * example, the coordinates for a rectangle:
  2514.      *     128,132,241,179
  2515.      * See your HTML reference for a full explanation about coordinates.
  2516.      *
  2517.      * An optional tooltip can be shown when hovering over this area with the
  2518.      * mouse with $mapAreaAlt.
  2519.      *
  2520.      * @param      string    $mapName        name of imagemap
  2521.      * @param      string    $mapAreaId      id of area in this map
  2522.      * @param      string    $mapAreaShape   cirlce, poly, rect
  2523.      * @param      string    $mapAreaCoords  x,y,... (depends on shape)
  2524.      * @param      string    $mapAreaAlt     mouse tooltip for this area
  2525.      * @see        getMapArea, addMapAreaAction, removeMapAreaAction,
  2526.      *              getMapAreaActions, getMapAreaHtml, getActionsMenu
  2527.      * @since      DutchPIPE 0.2.0
  2528.      */
  2529.     function setMapArea($mapName, $mapAreaId, $mapAreaShape, $mapAreaCoords,
  2530.             $mapAreaAlt = '')
  2531.     {
  2532.         if (!isset($this->mMapAreas[$mapName])) {
  2533.             $this->mMapAreas[$mapName] = array();
  2534.         }
  2535.         $this->mMapAreas[$mapName][$mapAreaId] =
  2536.             array($mapAreaShape, $mapAreaCoords, $mapAreaAlt);
  2537.     }
  2538.  
  2539. /**    
  2540.      * Gets data of one, multiple or all imagemap areas
  2541.      *
  2542.      * If no arguments are given data of all imagemap areas is returned. If an
  2543.      * imagemap name is given, all data for that map is returned, or FALSE if
  2544.      * the imagemap is not defined. If both the map name and an id of the area
  2545.      * in the map are given, data for that area is returned, or FALSE if not
  2546.      * defined.
  2547.      *
  2548.      * @param      string    $mapName    name of imagemap
  2549.      * @param      string    $mapAreaId  id of area in imagemap
  2550.      * @return     mixed     array with imagemap areas, can be empty, or FALSE
  2551.      * @see        setMapArea, addMapAreaAction, removeMapAreaAction,
  2552.      *              getMapAreaActions, getMapAreaHtml, getActionsMenu
  2553.      * @since      DutchPIPE 0.2.0
  2554.      */
  2555.     function getMapArea($mapName = NULL, $mapAreaId = NULL)
  2556.     {
  2557.         if (is_null($mapName)) {
  2558.             return $this->mMapAreas;
  2559.         }
  2560.  
  2561.         if (is_null($mapAreaId)) {
  2562.             return !isset($this->mMapAreas[$mapName]) ? FALSE
  2563.                 : $this->mMapAreas[$mapName];
  2564.         }
  2565.  
  2566.         return !isset($this->mMapAreas[$mapName])
  2567.             || !isset($this->mMapAreas[$mapName][$mapAreaId]) ? FALSE
  2568.             : $this->mMapAreas[$mapName][$mapAreaId];
  2569.     }
  2570.  
  2571. /**    
  2572.      * Adds an action to a map area so it becomes clickable there
  2573.      *
  2574.      * Creates a menu item labelled $actionMenuTitle on the imagemap area with
  2575.      * id $mapAreaId. When clicked, executes $action for that user.
  2576.      *
  2577.      * Can optionally be associated with an existing action by giving an
  2578.      * $actionVerb and $actionVerbKey. Normal map area menu actions always
  2579.      * appear. By associating it to a regular action, all its settings such as
  2580.      * scope, target and authorization are used. Use addAction to set up such
  2581.      * a map area action, as addAction will call addMapAreaAction with the right
  2582.      * verb and verb key (a verb key is needed because there can be multiple
  2583.      * indentical verbs).
  2584.  
  2585.      * @param      string    $mapAreaId        id of area in imagemap
  2586.      * @param      string    $actionMenuTitle  title of menu item
  2587.      * @param      string    $action           action executed when clicked
  2588.      * @param      string    $actionVerb       optional associated verb
  2589.      * @param      string    $actionVerbKey    optional index of this verb
  2590.      * @see        setMapArea, getMapArea, removeMapAreaAction,
  2591.      8             getMapAreaActions, getMapAreaHtml, getActionsMenu
  2592.      * @since      DutchPIPE 0.2.0
  2593.      */
  2594.     function addMapAreaAction($mapAreaId, $actionMenuTitle, $action,
  2595.             $actionVerb = NULL, $actionVerbKey = NULL)
  2596.     {
  2597.         if (!isset($this->mMapAreaActions[$mapAreaId])) {
  2598.             $this->mMapAreaActions[$mapAreaId] = array();
  2599.         }
  2600.         $new_area_data = array($actionMenuTitle, $action, $actionVerb,
  2601.             $actionVerbKey);
  2602.         foreach ($this->mMapAreaActions[$mapAreaId] as $area_data) {
  2603.             if ($area_data === $new_area_data) {
  2604.                 return;
  2605.             }
  2606.         }
  2607.  
  2608.         $this->mMapAreaActions[$mapAreaId][] = $new_area_data;
  2609.     }
  2610.  
  2611. /**    
  2612.      * Removes a map area action
  2613.      *
  2614.      * Either 1) the action menu title, 2) the executed action string when
  2615.      * clicked (while the title is NULL) or 3) both can be given. Removes the
  2616.      * first found match.
  2617.      *
  2618.      * @param      string    $mapAreaId        id of area in imagemap
  2619.      * @param      string    $actionMenuTitle  title of menu item
  2620.      * @param      string    $action           action executed when clicked
  2621.      * @see        setMapArea, getMapArea, addMapAreaAction, getMapAreaActions,
  2622.      *              getMapAreaHtml, getActionsMenu
  2623.      * @since      DutchPIPE 0.2.0
  2624.      */
  2625.     function removeMapAreaAction($mapAreaId, $actionMenuTitle, $action = NULL)
  2626.     {
  2627.         if (!isset($this->mMapAreaActions[$mapAreaId])
  2628.                 || (is_null($actionMenuTitle) && is_null($action))) {
  2629.             return;
  2630.         }
  2631.  
  2632.         foreach ($this->mMapAreaActions[$mapAreaId] as $i => &$area_data) {
  2633.             if ((is_null($actionMenuTitle)
  2634.                     || $area_data[0] === $actionMenuTitle)
  2635.                     && (is_null($action) || $area_data[1] === $action)) {
  2636.                 unset($this->mMapAreaActions[$mapAreaId][$i]);
  2637.                 return;
  2638.             }
  2639.         }
  2640.     }
  2641.  
  2642. /**    
  2643.      * Gets all map area actions for all areas or for a given area
  2644.      *
  2645.      * @param      string    $mapAreaId  id of area in imagemap
  2646.      * @return     array     array with map area data, can be empty
  2647.      * @see        setMapArea, getMapArea, addMapAreaAction,
  2648.      *              removeMapAreaAction, getMapAreaHtml, getActionsMenu
  2649.      * @since      DutchPIPE 0.2.0
  2650.      */
  2651.     function getMapAreaActions($mapAreaId = NULL)
  2652.     {
  2653.         if (is_null($mapAreaId)) {
  2654.             return $this->mMapAreaActions;
  2655.         }
  2656.  
  2657.         return !isset($this->mMapAreaActions[$mapAreaId]) ? FALSE
  2658.             : $this->mMapAreaActions[$mapAreaId];
  2659.     }
  2660.  
  2661. /**    
  2662.      * Gets HTML for all imagemaps or the given imagemap for inclusion in page
  2663.      *
  2664.      * Constructs the right HTML with <map> and <area> tags and onclick events.
  2665.      * Returns an empty string of no map data was found. Used by getBody.
  2666.      *
  2667.      * @param      string    $mapName        name of imagemap
  2668.      * @return     string    HTML for one or more imagemaps, or empty string.
  2669.      * @see        getBody, setMapArea, getMapArea, addMapAreaAction,
  2670.      *              removeMapAreaAction, getMapAreaActions, getActionsMenu
  2671.      * @since      DutchPIPE 0.2.0
  2672.      */
  2673.     function getMapAreaHtml($mapName = NULL)
  2674.     {
  2675.         if (is_null($mapName)) {
  2676.             $rval = '';
  2677.             $map_names = array_keys($this->mMapAreas);
  2678.             foreach ($map_names as $map_name) {
  2679.                 $rval .= $this->getMapAreaHtml($map_name);
  2680.             }
  2681.  
  2682.             return $rval;
  2683.         }
  2684.  
  2685.         if (!isset($this->mMapAreas[$mapName])) {
  2686.             return '';
  2687.         }
  2688.  
  2689.  
  2690.         $rval = "<map name=\"{$mapName}\">\n";
  2691.         foreach ($this->mMapAreas[$mapName] as
  2692.                 $map_area_id => &$map_area_data) {
  2693.             $actions = $this->getMapAreaActions($map_area_id);
  2694.             $nr_of_actions = count($actions);
  2695.             if (0 === $nr_of_actions) {
  2696.                 $alt = '';
  2697.             } elseif (1 === $nr_of_actions) {
  2698.                 reset($actions);
  2699.                 $action = current($actions);
  2700.                 $alt = $action[0];
  2701.             } else {
  2702.                 $alt = dp_text('Click for menu');
  2703.             }
  2704.             $rval .= "<area shape=\"{$map_area_data[0]}\" "
  2705.                 "coords=\"{$map_area_data[1]}}\" "
  2706.                 "href=\"javascript:void(0)\" "
  2707.                 . "alt=\"{$alt}\" title=\"{$alt}\" "
  2708.                 "onclick=\"get_map_area_actions('{$mapName}', "
  2709.                 "'{$map_area_id}', '{$this->uniqueId}', event)\" "
  2710.                 "style=\"cursor: pointer\" />\n";
  2711.         }
  2712.         $rval .= '</map>';
  2713.  
  2714.         return $rval;
  2715.     }
  2716.  
  2717. /**    
  2718.      * Tries if a user action can be performed on this object
  2719.      *
  2720.      * When a user doesn't use the action menu, but gives a command such as
  2721.      * 'take beer', or when an NPC performs an action, the system doesn't know
  2722.      * which object defines the action. Therefore, it calls this method in all
  2723.      * objects which are eligable to perform this action. Objects are searched
  2724.      * for, in this order, in the object performing the action, its inventory,
  2725.      * in its environment, and the environment itself.
  2726.      *
  2727.      * performActionSubject returns TRUE if the action was completed by this
  2728.      * object, or FALSE if this action was not directed at this object, in which
  2729.      * case the system will try the next object, if any.
  2730.      *
  2731.      * @param      string    $action     the complete input string
  2732.      * @param      object    &$living    user or npc performing the action
  2733.      * @return     boolean   TRUE for action completed, FALSE otherwise
  2734.      */
  2735.     final public function performActionSubject($action, &$living)
  2736.     {
  2737.         if (dp_strlen($action) >= 1 && dp_substr($action, 0, 1) == "'") {
  2738.             $say = dp_text('say');
  2739.             $action = dp_strlen($action) == 1 ? $say : $say . ' '
  2740.                 . dp_substr($action, 1);
  2741.         } elseif (dp_strlen($action) >= 1 && dp_substr($action, 0, 1) == '"') {
  2742.             $tell = dp_text('tell');
  2743.             $action = dp_strlen($action) == 1 ? $tell : $tell . ' '
  2744.                 . dp_substr($action, 1);
  2745.         }
  2746.  
  2747.         if (FALSE !== ($x = dp_strpos($action, ' '))) {
  2748.             $verb = dp_substr($action, 0, $x);
  2749.             $noun = trim(dp_substr($action, $x));
  2750.             if (!dp_strlen($noun)) {
  2751.                 $noun = null;
  2752.             }
  2753.         } else {
  2754.             $verb = trim($action);
  2755.             $noun = null;
  2756.         }
  2757.  
  2758.         if (isset($this->isLiving) && TRUE === $this->isLiving
  2759.                 && $living === $this) {
  2760.             /* Try inventory and environment */
  2761.             $inv = $this->getInventory();
  2762.             foreach ($inv as &$ob) {
  2763.                 if (TRUE === (bool)$ob->performActionSubject($action,
  2764.                         $living)) {
  2765.                     return TRUE;
  2766.                 }
  2767.             }
  2768.             $env = $this->getEnvironment();
  2769.             $inv = $env->getInventory();
  2770.             foreach ($inv as &$ob) {
  2771.                 if ($ob !== $this && TRUE ===
  2772.                         (bool)$ob->performActionSubject($action, $living)) {
  2773.                     return TRUE;
  2774.                 }
  2775.             }
  2776.             if ((boolean)$env->performActionSubject($action, $living)) {
  2777.                 return TRUE;
  2778.             }
  2779.         }
  2780.  
  2781.         $is_phrase = FALSE;
  2782.  
  2783.         if (isset($this->mActions[$verb])) {
  2784.             reset($this->mActions[$verb]);
  2785.             $action_data = $this->mActions[$verb][key($this->mActions[$verb])];
  2786.         } elseif (isset($this->mActions[$action])) {
  2787.             $is_phrase = TRUE;
  2788.             reset($this->mActions[$verb]);
  2789.             $action_data = $this->mActions[$action]
  2790.                 [key($this->mActions[$verb])];
  2791.         } elseif (isset($this->mActionAliases[$verb])) {
  2792.             reset($this->mActionAliases[$verb]);
  2793.             $alias =& $this->mActionAliases[$verb]
  2794.                 [key($this->mActionAliases[$verb])];
  2795.             $action_data = $this->mActions[$alias[0]][$alias[1]];
  2796.         } elseif (isset($this->mActionAliases[$action])) {
  2797.             $is_phrase = TRUE;
  2798.             reset($this->mActionAliases[$verb]);
  2799.             $alias =& $this->mActionAliases[$action]
  2800.                 [key($this->mActionAliases[$verb])];
  2801.             $action_data = $this->mActions[$alias[0]][$alias[1]];
  2802.         } else {
  2803.             return FALSE;
  2804.         }
  2805.  
  2806.         $scope =& $action_data[5];
  2807.         parse_dp_callable($scope, $verb, NULL, $this, $living);
  2808.  
  2809.         if ($scope & <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_SCOPE_SELF">DP_ACTION_SCOPE_SELF</a>) {
  2810.             if ($living !== $this) {
  2811.                 return FALSE;
  2812.             }
  2813.         }
  2814.         if ($scope & <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_SCOPE_INVENTORY">DP_ACTION_SCOPE_INVENTORY</a>) {
  2815.             if ($living->getEnvironment() !== $this) {
  2816.                 return FALSE;
  2817.             }
  2818.         }
  2819.         if ($scope & <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_SCOPE_ENVIRONMENT">DP_ACTION_SCOPE_ENVIRONMENT</a>) {
  2820.             if ($living->getEnvironment() !== $this->getEnvironment()) {
  2821.                 return FALSE;
  2822.             }
  2823.         }
  2824.  
  2825.         $auth =& $action_data[4];
  2826.         parse_dp_callable($auth, $verb, NULL, $this, $living);
  2827.  
  2828.         if ($auth === <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_AUTHORIZED_GUEST">DP_ACTION_AUTHORIZED_GUEST</a>) {
  2829.             if (TRUE === $living->isRegistered) {
  2830.                 return FALSE;
  2831.             }
  2832.         } elseif ($auth === <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_AUTHORIZED_REGISTERED">DP_ACTION_AUTHORIZED_REGISTERED</a>) {
  2833.             if (TRUE !== $living->isRegistered) {
  2834.                 return FALSE;
  2835.             }
  2836.         } elseif ($auth === <a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---actions.php.html#defineDP_ACTION_AUTHORIZED_ADMIN">DP_ACTION_AUTHORIZED_ADMIN</a>) {
  2837.             if (TRUE !== $living->isAdmin) {
  2838.                 return FALSE;
  2839.             }
  2840.         }
  2841.  
  2842.         if (!is_dp_callable($action_data[1])) {
  2843.             $call_obj =& $this;
  2844.             $call_method = $action_data[1];
  2845.         } else {
  2846.             $call_obj =& $action_data[1][0];
  2847.             $call_method = $action_data[1][1];
  2848.         }
  2849.  
  2850.         return method_exists($call_obj, $call_method) &&
  2851.             (bool)$call_obj->{$call_method}(!$is_phrase ? $verb : $action,
  2852.             $noun);
  2853.     }
  2854.  
  2855. /**    
  2856.      * Reports an event
  2857.      *
  2858.      * Called when certain events occur, given with $name. The property
  2859.      * lastEventTime is set to a unix time stamp. Calls eventDpObject.
  2860.      *
  2861.      * @param      object    $name       Name of event
  2862.      * @param      mixed     $args       One or more arguments, depends on event
  2863.      */
  2864.     final function event($name)
  2865.     {
  2866.         $this->lastEventTime = time();
  2867.         $args = func_get_args();
  2868.         call_user_func_array(array($this, 'eventDpObject'), $args);
  2869.     }
  2870.  
  2871. /**    
  2872.      * Reports an event
  2873.      *
  2874.      * Called when certain events occur, given with $name.
  2875.      *
  2876.      * @param      object    $name       Name of event
  2877.      * @param      mixed     $args       One or more arguments, depends on event
  2878.      * @since      DutchPIPE 0.2.0
  2879.      */
  2880.     function eventDpObject($name)
  2881.     {
  2882.     }
  2883.  
  2884. /**    
  2885.      * Called by the universe object, checks if this object can be removed.
  2886.      *
  2887.      * To save some memory, the universe object will call this method in objects
  2888.      * with no environment, which haven't been referenced for a while.
  2889.      *
  2890.      * If no users or special object using the isNoCleanUp property are present,
  2891.      * the object and all of its inventory is destroyed.
  2892.      *
  2893.      * @since      DutchPIPE 0.2.0
  2894.      */
  2895.     function handleCleanUp()
  2896.     {
  2897.         foreach ($this->mCheckPresentObjects as $i => &$ob) {
  2898.             if ($ob->getEnvironment() !== $this) {
  2899.                 echo sprintf(
  2900.                     dp_text("handleCleanUp() called in %s: not removed",
  2901.                     $this->title));
  2902.                 return;
  2903.             }
  2904.         }
  2905.  
  2906.         $inv = $this->getInventory();
  2907.         foreach ($inv as &$ob) {
  2908.             if ($ob->isUser || $ob->isNoCleanUp) {
  2909.                 echo sprintf(
  2910.                     dp_text("handleCleanUp() called in %s: not removed",
  2911.                     $this->title));
  2912.                 return;
  2913.             }
  2914.         }
  2915.  
  2916.         echo sprintf(dp_text("handleCleanUp() called in %s: removing\n",
  2917.             $this->title));
  2918.         $this->removeDpObject();
  2919.     }
  2920.  
  2921. /**    
  2922.      * Can we be dragged on the screen by the given user?
  2923.      *
  2924.      * Experimental mouse dragging of objects.
  2925.      *
  2926.      * @param      object    &$by_who    subject that wants to drag us
  2927.      * @return     boolean   TRUE if $by_who may drag us, FALSE otherwise
  2928.      * @since      DutchPIPE 0.2.0
  2929.      */
  2930.     function isDraggable(&$by_who)
  2931.     {
  2932.         return $this->getDpProperty('isDraggable');
  2933.     }
  2934.  
  2935. /**    
  2936.      * Reports graphical movement of this object to other objects
  2937.      *
  2938.      * Called by the client-side dpclient-js.php script after an object was
  2939.      * dragged by a user. Coordinates are passed as 'x' and 'y' in a GET
  2940.      * request and passed on to other users in the same environment.
  2941.      *
  2942.      * @see        dpclient-js.php
  2943.      * @since      DutchPIPE 0.2.0
  2944.      */
  2945.     function reportMove()
  2946.     {
  2947.         if (!($user = get_current_dpuser())
  2948.                 || !($env = $user->getEnvironment())
  2949.                 || !($inv = $env->getInventory())) {
  2950.             return;
  2951.         }
  2952.  
  2953.         foreach ($inv as &$ob) {
  2954.             if ($ob !== $user && $ob->isUser) {
  2955.                 if ($user !== $this) {
  2956.                     $ob->tell(sprintf(dp_text("%s moves %s around.<br />"),
  2957.                         $user->getTitle(<a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---title_types.php.html#defineDPUNIVERSE_TITLE_TYPE_DEFINITE">DPUNIVERSE_TITLE_TYPE_DEFINITE</a>),
  2958.                         $this->getTitle(<a href="../DutchPIPE/dpuniverse_include/_dpuniverse---include---title_types.php.html#defineDPUNIVERSE_TITLE_TYPE_DEFINITE">DPUNIVERSE_TITLE_TYPE_DEFINITE</a>)));
  2959.                 }
  2960.                 $ob->tell('<reportmove id="' . $this->uniqueId . '" left="'
  2961.                     . $user->_GET['x'] . '" top="' . $user->_GET['y']
  2962.                     . '">&#160;</reportmove>');
  2963.             }
  2964.         }
  2965.     }
  2966.  
  2967. /**    
  2968.      * Sets a heap object of a given amount in this object
  2969.      *
  2970.      * @param      string    $pathname   path to code from universe base path
  2971.      * @param      string    $idProperty unique property to identify heap object
  2972.      * @param      int|float$amount     amount, depends on heap type
  2973.      * @return     boolean   TRUE for success, FALSE otherwise
  2974.      * @since      DutchPIPE 0.2.0
  2975.      */
  2976.     function setHeapAmount($pathname, $idProperty, $amount)
  2977.     {
  2978.         $inv = $this->getInventory();
  2979.  
  2980.         foreach ($inv as &$ob) {
  2981.             if ($ob->{$idProperty}) {
  2982.                 $ob->amount = $amount;
  2983.                 return TRUE;
  2984.             }
  2985.         }
  2986.  
  2987.         $heap_ob = get_current_dpuniverse()->newDpObject($pathname);
  2988.         $heap_ob->amount = $amount;
  2989.         $heap_ob->moveDpObject($this);
  2990.         return TRUE;
  2991.     }
  2992.  
  2993. /**    
  2994.      * Gets the amount of a given heap object
  2995.      *
  2996.      * @param      string    $idProperty unique property to identify heap object
  2997.      * @return     int|floatamount, depends on heap type
  2998.      * @since      DutchPIPE 0.2.0
  2999.      */
  3000.     function getHeapAmount($idProperty)
  3001.     {
  3002.         $inv = $this->getInventory();
  3003.         $amount = 0;
  3004.  
  3005.         foreach ($inv as &$ob) {
  3006.             if ($ob->{$idProperty}) {
  3007.                 $amount += $ob->amount;
  3008.             }
  3009.         }
  3010.  
  3011.         return $amount;
  3012.     }
  3013.  
  3014. /**    
  3015.      * Sets the amount of credits in the inventory of this object
  3016.      *
  3017.      * @param      int|float$credits    amount of credits
  3018.      * @return     boolean   TRUE for success, FALSE otherwise
  3019.      * @see        getCredits
  3020.      * @since      DutchPIPE 0.2.0
  3021.      */
  3022.     function setCredits($credits)
  3023.     {
  3024.         return $this->setHeapAmount(<a href="../DutchPIPE/config/_config---dpuniverse-ini.php.html#defineDPUNIVERSE_OBJ_PATH">DPUNIVERSE_OBJ_PATH</a> . 'credits.php',
  3025.             'isCredits', $credits);
  3026.     }
  3027.  
  3028. /**    
  3029.      * Gets the amount of credits in the inventory of this object
  3030.      *
  3031.      * @return     int|floatamount of credits
  3032.      * @see        setCredits
  3033.      * @since      DutchPIPE 0.2.0
  3034.      */
  3035.     function getCredits()
  3036.     {
  3037.         return $this->getHeapAmount('isCredits');
  3038.     }
  3039.  
  3040. /**    
  3041.      * Makes the given method callable from the DutchPIPE client
  3042.      *
  3043.      * @param      string    $methodName  method to add
  3044.      * @see        removeValidClientCall, isValidClientCall
  3045.      * @since      DutchPIPE 0.4.0
  3046.      */
  3047.     protected final function addValidClientCall($methodName)
  3048.     {
  3049.         $this->mValidClientCalls[] = $methodName;
  3050.     }
  3051.  
  3052. /**    
  3053.      * Removes the given method from callable methods from the DutchPIPE client
  3054.      *
  3055.      * @param      string    $methodName  method to remove
  3056.      * @see        addValidClientCall, isValidClientCall
  3057.      * @since      DutchPIPE 0.4.0
  3058.      */
  3059.     protected final function removeValidClientCall($methodName)
  3060.     {
  3061.         if (in_array($methodName, $this->mValidClientCalls, TRUE)) {
  3062.             unset($this->mValidClientCalls[$methodName]);
  3063.         }
  3064.     }
  3065.  
  3066. /**    
  3067.      * May the given method be called in this object from the DutchPIPE client?
  3068.      *
  3069.      * @param      string    $methodName  method to check
  3070.      * @return     boolean   TRUE if the method can be called, FALSE otherwise
  3071.      * @see        addValidClientCall, removeValidClientCall
  3072.      * @since      DutchPIPE 0.4.0
  3073.      */
  3074.     final function isValidClientCall($methodName)
  3075.     {
  3076.         return in_array($methodName, $this->mValidClientCalls, TRUE);
  3077.     }
  3078.  
  3079. /**    
  3080.      * Gets the width in pixels of the title image
  3081.      *
  3082.      * @return     mixed     Integer with width in pixels, FALSE for unknown
  3083.      * @see        getTitleImgHeight
  3084.      * @since      DutchPIPE 0.4.1
  3085.      */
  3086.     function getTitleImgWidth()
  3087.     {
  3088.         $this->_initTitleImgDimensions();
  3089.  
  3090.         $title_img_width = $this->getDpProperty('titleImgWidth');
  3091.         return is_null($title_img_width) ? FALSE : $title_img_width;
  3092.     }
  3093.  
  3094. /**    
  3095.      * Gets the height in pixels of the title image
  3096.      *
  3097.      * @return     mixed     Integer with height in pixels, FALSE for unknown
  3098.      * @see        getTitleImgWidth
  3099.      * @since      DutchPIPE 0.4.1
  3100.      */
  3101.     function getTitleImgHeight()
  3102.     {
  3103.         $this->_initTitleImgDimensions();
  3104.  
  3105.         $title_img_height = $this->getDpProperty('titleImgHeight');
  3106.         return is_null($title_img_height) ? FALSE : $title_img_height;
  3107.     }
  3108.  
  3109. /**    
  3110.      * Sets the titleImgWidth and titleImgHeight properties
  3111.      *
  3112.      * Sets these properties in this object if they aren't set and if PHP is
  3113.      * installed with the GD library.
  3114.      *
  3115.      * @access     private
  3116.      * @see        getTitleImgWidth, getTitleImgHeight
  3117.      * @since      DutchPIPE 0.4.1
  3118.      */
  3119.     private function _initTitleImgDimensions()
  3120.     {
  3121.         $title_img_width = $this->getDpProperty('titleImgWidth');
  3122.         $title_img_height = $this->getDpProperty('titleImgHeight');
  3123.  
  3124.         if (!is_null($title_img_width) && !is_null($title_img_height)) {
  3125.             return;
  3126.         }
  3127.         if (!function_exists('gd_info')) {
  3128.             return;
  3129.         }
  3130.         $url2path = array(
  3131.             <a href="../DutchPIPE/config/_config---dpuniverse-ini.php.html#defineDPUNIVERSE_AVATAR_STD_URL">DPUNIVERSE_AVATAR_STD_URL</a>
  3132.                 => <a href="../DutchPIPE/config/_config---dpuniverse-ini.php.html#defineDPUNIVERSE_AVATAR_STD_PATH">DPUNIVERSE_AVATAR_STD_PATH</a>,
  3133.             <a href="../DutchPIPE/config/_config---dpuniverse-ini.php.html#defineDPUNIVERSE_AVATAR_CUSTOM_GUEST_URL">DPUNIVERSE_AVATAR_CUSTOM_GUEST_URL</a>
  3134.                 => <a href="../DutchPIPE/config/_config---dpuniverse-ini.php.html#defineDPUNIVERSE_AVATAR_CUSTOM_GUEST_PATH">DPUNIVERSE_AVATAR_CUSTOM_GUEST_PATH</a>,
  3135.             <a href="../DutchPIPE/config/_config---dpuniverse-ini.php.html#defineDPUNIVERSE_AVATAR_CUSTOM_REG_URL">DPUNIVERSE_AVATAR_CUSTOM_REG_URL</a>
  3136.                 => <a href="../DutchPIPE/config/_config---dpuniverse-ini.php.html#defineDPUNIVERSE_AVATAR_CUSTOM_REG_PATH">DPUNIVERSE_AVATAR_CUSTOM_REG_PATH</a>,
  3137.             <a href="../DutchPIPE/config/_config---dpuniverse-ini.php.html#defineDPUNIVERSE_IMAGE_URL">DPUNIVERSE_IMAGE_URL</a>
  3138.                 => <a href="../DutchPIPE/config/_config---dpuniverse-ini.php.html#defineDPUNIVERSE_IMAGE_PATH">DPUNIVERSE_IMAGE_PATH</a>
  3139.         );
  3140.  
  3141.         foreach ($url2path as $url => $path) {
  3142.             $title_img = str_replace($url, $path, $this->titleImg);
  3143.             if ($this->titleImg !== $title_img) {
  3144.                 break;
  3145.             }
  3146.         }
  3147.  
  3148.         $image_info = getimagesize($title_img);
  3149.         if (!is_array($image_info)) {
  3150.             return;
  3151.         }
  3152.  
  3153.         list($width, $height) = $image_info;
  3154.         if (is_null($title_img_width)) {
  3155.             $this->titleImgWidth = new_dp_property($width);
  3156.         }
  3157.         if (is_null($title_img_height)) {
  3158.             $this->titleImgHeight = new_dp_property($height);
  3159.         }
  3160.     }
  3161. }

Documentation generated on Mon, 03 Sep 2007 22:20:18 +0200 by phpDocumentor 1.3.0RC6

Click me!
Guest#215
 
 
 
  Go to Top
 
 
Input Field OptionsClose Input Field Go to Top
 
Legal Notices | Copyright © 2006, 2007 Lennert Stock. All rights reserved. Last update: Mon Sep 03 2007, 21:50 CET.