Beispiel #1
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;
  }
  /**
   * Get 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.
   * @return The keyed value of the slot, or <code>null</code> if not set.
   */
  public static String getKeyedSlot(
      final SlotOwner slotOwner, final String name, final String key) {
    final RPObject object = KeyedSlotUtil.getKeyedSlotObject(slotOwner, name);
    if (object == null) {
      return null;
    }

    return object.get(key);
  }
Beispiel #3
0
  /**
   * Initialize this entity for an object.
   *
   * @param object The object.
   * @see #release()
   */
  @Override
  public void initialize(final RPObject object) {
    super.initialize(object);

    if (object.hasSlot("content")) {
      content = object.getSlot("content");
    } else {
      content = null;
    }
  }
 /**
  * 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);
   }
 }
  /**
   * Check whether the given RPObject is the RPObject representing the user's character. When an
   * RPObject is the subclass of the "character" RPClass and has the same name as the user has
   * chosen as its character by the start, an object is considered to be the character object. This
   * relies on having unique character names.
   *
   * @param object the RPObject to check whether it's the user's character object
   * @return true if the given object is the user's character object
   */
  protected boolean isCharacter(final RPObject object) {
    if (name == null) {
      return false;
    }

    if (object.getRPClass().subclassOf("character")) {
      return name.equalsIgnoreCase(object.get("name"));
    } else {
      return false;
    }
  }
  /**
   * 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);
    }
  }
Beispiel #7
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);
    }
  }
  /**
   * 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;
  }
 /**
  * Takes the given RPObject as the new RPObject representing the user's character. Does nothing if
  * the provided RPObject isn't the user's character object as determined by
  * isCharacter(newCharacter) or the provided RPObject is the same as the current one.
  *
  * @param newCharacter the new RPObject representing the users character
  */
 public void setCharacter(final RPObject newCharacter) {
   if (isCharacter(newCharacter) && this.myCharacter != newCharacter) {
     myCharacter = newCharacter;
     name = newCharacter.get("name");
   } else {
     log.warn("Character not set because it's not our character.");
   }
 }
  /**
   * 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;
  }
Beispiel #11
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);
      }
    }
  }
  /**
   * 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);
    }
  }
  private void sendPlayerPerception(
      PlayerEntry entry, Perception perception, RPObject playerObject) {
    if (perception == null) {
      /** Until player enters game perception is null */
      return;
    }

    MessageS2CPerception messages2cPerception = new MessageS2CPerception(entry.channel, perception);

    stats.add("Perceptions " + (perception.type == 0 ? "DELTA" : "SYNC"), 1);

    /*
     * The perception is build of two parts: the general information and the
     * private information about our object. This private information
     * consists only of attributes that are not visible to every player but
     * the owner, because visible attributes are already stored in the
     * perception.
     */

    if (perception.type == Perception.SYNC) {
      RPObject copy = new RPObject();
      copy.fill(playerObject);
      if (!playerObject.isHidden()) {
        copy.clearVisible(true);
      }
      messages2cPerception.setMyRPObject(copy, null);
    } else {
      RPObject added = new RPObject();
      RPObject deleted = new RPObject();

      try {
        playerObject.getDifferences(added, deleted);
        if (!playerObject.isHidden()) {
          added.clearVisible(false);
          deleted.clearVisible(false);
        }

        if (added.size() == 0) {
          added = null;
        }

        if (deleted.size() == 0) {
          deleted = null;
        }
      } catch (Exception e) {
        logger.error("Error getting object differences", e);
        logger.error(playerObject);
        added = null;
        deleted = null;
      }
      messages2cPerception.setMyRPObject(added, deleted);
    }

    messages2cPerception.setClientID(entry.clientid);
    messages2cPerception.setPerceptionTimestamp(entry.getPerceptionTimestamp());
    messages2cPerception.setProtocolVersion(entry.getProtocolVersion());

    netMan.sendMessage(messages2cPerception);
  }