/**
  * TODO: there is a bug in marauroa, remove this if marauroa stops storing volatile attributes.
  * review then also which attributes should be volatile and which shouldnt.
  *
  * @param player
  */
 private void removeVolatile(final RPObject player) {
   if (player.has(AWAY)) {
     player.remove(AWAY);
   }
   // remove grumpy on login to give postman a chance to deliver messages
   // (and in the hope that player is receptive now)
   if (player.has(GRUMPY)) {
     player.remove(GRUMPY);
   }
 }
  /**
   * Places the player (and his/her sheep if there is one) into the world on login.
   *
   * @param object RPObject representing the player
   * @param player Player-object
   */
  public static void placePlayerIntoWorldOnLogin(final RPObject object, final Player player) {
    StendhalRPZone zone = null;

    String zoneName = System.getProperty("stendhal.forcezone");
    if (zoneName != null) {
      zone = SingletonRepository.getRPWorld().getZone(zoneName);
      zone.placeObjectAtEntryPoint(player);
      return;
    }

    try {
      if (object.has("zoneid") && object.has("x") && object.has("y")) {
        if (Version.checkCompatibility(object.get("release"), Debug.VERSION)) {
          zone = SingletonRepository.getRPWorld().getZone(object.get("zoneid"));
        } else {
          if (player.getLevel() >= 2) {
            TutorialNotifier.newrelease(player);
          }
        }
        player.put("release", Debug.VERSION);
      }
    } catch (final RuntimeException e) {
      // If placing the player at its last position
      // fails, we reset to default zone
      logger.warn("Cannot place player at its last position. Using default", e);
    }

    if (zone != null) {
      /*
       * Put the player in their zone (use placeat() for collision rules)
       */
      if (!StendhalRPAction.placeat(zone, player, player.getX(), player.getY())) {
        logger.warn("Cannot place player at their last position: " + player.getName());
        zone = null;
      }
    }

    if (zone == null) {
      /*
       * Fallback to default zone
       */
      final String defaultZoneName = getDefaultZoneForPlayer(player);
      zone = SingletonRepository.getRPWorld().getZone(defaultZoneName);

      if (zone == null) {
        logger.error("Unable to locate default zone [" + defaultZoneName + "]");
        return;
      }

      zone.placeObjectAtEntryPoint(player);
    }
  }
예제 #3
0
  /**
   * The object removed attribute(s).
   *
   * @param object The base object.
   * @param changes The changes.
   */
  @Override
  public void onChangedRemoved(final RPObject object, final RPObject changes) {
    super.onChangedRemoved(object, changes);

    if (changes.has("away")) {
      onAway(null);
    }
    if (changes.has("grumpy")) {
      onGrumpy(null);
    }
    if (changes.has(LAST_PLAYER_KILL_TIME)) {
      badboy = false;
      fireChange(PROP_PLAYER_KILLER);
    }
  }
예제 #4
0
  /**
   * Check if the user is close enough the parent entity of the slot. If the user is too far away
   * the window should not be opened, and it should be closed if it was already open.
   *
   * @return <code>true</code> if the user is close enough to have the window open, <code>false
   *     </code> otherwise.
   */
  public boolean isCloseEnough() {
    final User user = User.get();

    if ((user != null) && (parent != null)) {
      // null checks are fixes for Bug 1825678:
      // NullPointerException happened
      // after double clicking one
      // monster and a fast double
      // click on another monster

      // Check if the parent is user
      RPObject root = parent.getRPObject().getBaseContainer();
      // We don't want to close our own stuff
      // The root entity may have been removed, but still if it was
      // the user we do not want to close it.
      // User may have been changed by the main thread, so we can not rely
      // on user.getRPObject() being equal to root. (bug #3159058)
      final String type = root.getRPClass().getName();
      if (type.equals("player") && root.has("name")) {
        if (StendhalClient.get().getCharacter().equalsIgnoreCase(root.get("name"))) {
          return true;
        }
      }

      return isCloseEnough(user.getX(), user.getY());
    }

    return true;
  }
  /**
   * Initialize this entity for an object.
   *
   * @param base The object.
   * @see #release()
   */
  @Override
  public void initialize(final RPObject base) {
    double speed;

    super.initialize(base);

    if (base.has("dir")) {
      setDirection(Direction.build(base.getInt("dir")));
    }

    if (base.has("speed")) {
      speed = base.getDouble("speed");
    } else {
      speed = 0.0;
    }

    dx = direction.getdx() * speed;
    dy = direction.getdy() * speed;
  }
예제 #6
0
 /** Tests for onAdded. */
 @Test
 public void testOnAdded() {
   player.onAdded(new StendhalRPZone("playertest"));
   RPObject object = KeyedSlotUtil.getKeyedSlotObject(player, "!visited");
   if (object == null) {
     fail("slot not found");
   }
   assertTrue(object.has("playertest"));
   assertThat(player.get("visibility"), is("100"));
   player.onAdded(new StendhalRPZone(PlayerDieer.DEFAULT_DEAD_AREA));
   object = KeyedSlotUtil.getKeyedSlotObject(player, "!visited");
   if (object == null) {
     fail("slot not found");
   }
   assertTrue(object.has(PlayerDieer.DEFAULT_DEAD_AREA));
   assertThat(player.get("visibility"), is("50"));
   player.onRemoved(new StendhalRPZone(PlayerDieer.DEFAULT_DEAD_AREA));
   assertThat(player.get("visibility"), is("100"));
 }
  /**
   * Loads the items into the slots of the player on login.
   *
   * @param player Player
   * @param slot original slot
   * @param newSlot new Stendhal specific slot
   */
  private void loadSlotContent(final Player player, final RPSlot slot, final PlayerSlot newSlot) {
    final List<RPObject> objects = new LinkedList<RPObject>();
    for (final RPObject objectInSlot : slot) {
      objects.add(objectInSlot);
    }
    slot.clear();
    player.removeSlot(slot.getName());
    player.addSlot(newSlot);

    ItemTransformer transformer = new ItemTransformer();
    for (final RPObject rpobject : objects) {
      try {
        // remove admin items the player does not deserve
        if (ITEMS_FOR_ADMINS.contains(rpobject.get("name"))
            && (!player.has("adminlevel") || player.getInt("adminlevel") < 1000)) {
          logger.warn(
              "removed admin item " + rpobject.get("name") + " from player " + player.getName());
          new ItemLogger().destroyOnLogin(player, slot, rpobject);

          continue;
        }

        Item item = transformer.transform(rpobject);

        // log removed items
        if (item == null) {
          int quantity = 1;
          if (rpobject.has("quantity")) {
            quantity = rpobject.getInt("quantity");
          }

          logger.warn(
              "Cannot restore "
                  + quantity
                  + " "
                  + rpobject.get("name")
                  + " on login of "
                  + player.getName()
                  + " because this item"
                  + " was removed from items.xml");
          new ItemLogger().destroyOnLogin(player, slot, rpobject);

          continue;
        }

        boundOldItemsToPlayer(player, item);

        newSlot.add(item);
      } catch (final Exception e) {
        logger.error("Error adding " + rpobject + " to player slot" + slot, e);
      }
    }
  }
예제 #8
0
  /**
   * Set a keyed string value on a named slot.
   *
   * @param slotOwner the object owning the slot
   * @param name The slot name.
   * @param key The value key.
   * @param value The value to assign (or remove if <code>null</code>).
   * @return <code>true</code> if value changed, <code>false</code> if there was a problem.
   */
  public static boolean setKeyedSlot(
      final SlotOwner slotOwner, final String name, final String key, final String value) {
    final RPObject object = KeyedSlotUtil.getKeyedSlotObject(slotOwner, name);
    if (object == null) {
      return false;
    }

    if (value != null) {
      object.put(key, value);
    } else if (object.has(key)) {
      object.remove(key);
    }

    return true;
  }
  /**
   * Process attribute changes that may affect positioning. This is needed because different
   * entities may want to process coordinate changes more gracefully.
   *
   * @param base The previous values.
   * @param diff The changes.
   */
  @Override
  protected void processPositioning(final RPObject base, final RPObject diff) {
    // Real movement case
    final int oldx = base.getInt("x");
    final int oldy = base.getInt("y");

    int newX = oldx;
    int newY = oldy;

    if (diff.has("x")) {
      newX = diff.getInt("x");
    }
    if (diff.has("y")) {
      newY = diff.getInt("y");
    }

    Direction tempDirection;

    if (diff.has("dir")) {
      tempDirection = Direction.build(diff.getInt("dir"));
      setDirection(tempDirection);
    } else if (base.has("dir")) {
      tempDirection = Direction.build(base.getInt("dir"));
      setDirection(tempDirection);
    } else {
      tempDirection = Direction.STOP;
    }

    double speed;

    /*
     * Speed change must be fired only after the new speed has been stored
     * (done in onMove())
     */
    boolean speedChanged = false;

    if (diff.has("speed")) {
      speed = diff.getDouble("speed");
      speedChanged = true;
    } else if (base.has("speed")) {
      speed = base.getDouble("speed");
    } else {
      speed = 0;
    }

    onMove(newX, newY, tempDirection, speed);

    if (speedChanged) {
      fireChange(PROP_SPEED);
    }

    boolean positionChanged = false;
    if ((Direction.STOP.equals(tempDirection)) || (speed == 0)) {
      setSpeed(0.0, 0.0);

      /*
       * Try to ensure relocation in the case the client and server were
       * in disagreement about the position at the moment of stopping.
       */
      if (!(compareDouble(y, newY, EPSILON) && compareDouble(x, newX, EPSILON))) {
        positionChanged = true;
      }

      // Store the new position before signaling it with onPosition().
      x = newX;
      y = newY;
    }

    /*
     * Change in position?
     */
    if (positionChanged || ((oldx != newX) && (oldy != newY))) {
      onPosition(newX, newY);
    }
  }