@Override
 protected Item buildMyPlant(MOB mob, Room room) {
   final int code = material & RawMaterial.RESOURCE_MASK;
   final Item newItem = CMClass.getBasicItem("GenItem");
   final String name =
       CMLib.english().startWithAorAn(RawMaterial.CODES.NAME(code).toLowerCase() + " tree");
   newItem.setName(name);
   newItem.setDisplayText(L("@x1 grows here.", newItem.name()));
   newItem.setDescription("");
   newItem.basePhyStats().setWeight(10000);
   CMLib.flags().setGettable(newItem, false);
   newItem.setMaterial(material);
   newItem.setSecretIdentity(mob.Name());
   newItem.setMiscText(newItem.text());
   room.addItem(newItem);
   final Chant_SummonTree newChant = new Chant_SummonTree();
   newItem.basePhyStats().setLevel(10 + newChant.getX1Level(mob));
   newItem.setExpirationDate(0);
   room.showHappens(
       CMMsg.MSG_OK_ACTION,
       L("a tall, healthy @x1 tree sprouts up.", RawMaterial.CODES.NAME(code).toLowerCase()));
   room.recoverPhyStats();
   newChant.plantsLocationR = room;
   newChant.littlePlantsI = newItem;
   if (CMLib.law().doesOwnThisLand(mob, room)) {
     newChant.setInvoker(mob);
     newChant.setMiscText(mob.Name());
     newItem.addNonUninvokableEffect(newChant);
   } else newChant.beneficialAffect(mob, newItem, 0, (newChant.adjustedLevel(mob, 0) * 240) + 450);
   room.recoverPhyStats();
   return newItem;
 }
  public static int updateLotWithThisData(
      Room R,
      LandTitle T,
      boolean resetRoomName,
      boolean clearAllItems,
      List optPlayerList,
      int lastNumItems) {
    boolean updateItems = false;
    boolean updateExits = false;
    boolean updateRoom = false;
    synchronized (("SYNC" + R.roomID()).intern()) {
      R = CMLib.map().getRoom(R);
      if (T.getOwnerName().length() == 0) {
        Item I = null;
        for (int i = R.numItems() - 1; i >= 0; i--) {
          I = R.getItem(i);
          if ((I == null) || (I.Name().equalsIgnoreCase("id"))) continue;
          CMLib.catalog().updateCatalogIntegrity(I);
          if (clearAllItems) {
            I.destroy();
            updateItems = true;
          } else {
            if (I.expirationDate() == 0) {
              long now = System.currentTimeMillis();
              now += (TimeManager.MILI_MINUTE * CMProps.getIntVar(CMProps.Int.EXPIRE_PLAYER_DROP));
              I.setExpirationDate(now);
            }
            if ((I.phyStats().rejuv() != PhyStats.NO_REJUV) && (I.phyStats().rejuv() != 0)) {
              I.basePhyStats().setRejuv(PhyStats.NO_REJUV);
              I.recoverPhyStats();
            }
          }
        }
        Ability A = null;
        if (clearAllItems)
          for (final Enumeration<Ability> a = R.effects(); a.hasMoreElements(); ) {
            A = a.nextElement();
            if (((A != null)
                && ((A.classificationCode() & Ability.ALL_ACODES) != Ability.ACODE_PROPERTY))) {
              A.unInvoke();
              R.delEffect(A);
              updateRoom = true;
            }
          }
        for (int d = Directions.NUM_DIRECTIONS() - 1; d >= 0; d--) {
          final Room R2 = R.rawDoors()[d];
          Exit E = R.getRawExit(d);
          if ((E != null) && (E.hasALock()) && (E.isGeneric())) {
            E.setKeyName("");
            E.setDoorsNLocks(E.hasADoor(), E.isOpen(), E.defaultsClosed(), false, false, false);
            updateExits = true;
            if (R2 != null) {
              E = R2.getRawExit(Directions.getOpDirectionCode(d));
              if ((E != null) && (E.hasALock()) && (E.isGeneric())) {
                E.setKeyName("");
                E.setDoorsNLocks(E.hasADoor(), E.isOpen(), E.defaultsClosed(), false, false, false);
                CMLib.database().DBUpdateExits(R2);
                R2.getArea().fillInAreaRoom(R2);
              }
            }
          }
        }
        if (updateExits) {
          CMLib.database().DBUpdateExits(R);
          R.getArea().fillInAreaRoom(R);
        }
        if (updateItems) CMLib.database().DBUpdateItems(R);
        if (updateRoom) CMLib.database().DBUpdateRoom(R);
        colorForSale(R, T.rentalProperty(), resetRoomName);
        return -1;
      }

      if ((lastNumItems < 0)
          && (!CMSecurity.isDisabled(CMSecurity.DisFlag.PROPERTYOWNERCHECKS))
          && (optPlayerList != null)) {
        boolean playerExists = (CMLib.players().getPlayer(T.getOwnerName()) != null);
        if (!playerExists) playerExists = (CMLib.clans().getClan(T.getOwnerName()) != null);
        if (!playerExists) playerExists = optPlayerList.contains(T.getOwnerName());
        if (!playerExists)
          for (int i = 0; i < optPlayerList.size(); i++)
            if (((String) optPlayerList.get(i)).equalsIgnoreCase(T.getOwnerName())) {
              playerExists = true;
              break;
            }
        if (!playerExists) {
          T.setOwnerName("");
          T.updateLot(null);
          return -1;
        }
      }

      int x = R.description().indexOf(SALESTR);
      if (x >= 0) {
        R.setDescription(R.description().substring(0, x));
        CMLib.database().DBUpdateRoom(R);
      }
      x = R.description().indexOf(RENTSTR);
      if (x >= 0) {
        R.setDescription(R.description().substring(0, x));
        CMLib.database().DBUpdateRoom(R);
      }

      // this works on the priciple that
      // 1. if an item has ONLY been removed, the lastNumItems will be != current # items
      // 2. if an item has ONLY been added, the dispossessiontime will be != null
      // 3. if an item has been added AND removed, the dispossession time will be != null on the
      // added
      if ((lastNumItems >= 0) && (R.numItems() != lastNumItems)) updateItems = true;

      for (int i = 0; i < R.numItems(); i++) {
        final Item I = R.getItem(i);
        if ((I.expirationDate() != 0)
            && ((I.isSavable()) || (I.Name().equalsIgnoreCase("id")))
            && ((!(I instanceof DeadBody)) || (((DeadBody) I).isPlayerCorpse()))) {
          I.setExpirationDate(0);
          updateItems = true;
        }

        if ((I.phyStats().rejuv() != Integer.MAX_VALUE) && (I.phyStats().rejuv() != 0)) {
          I.basePhyStats().setRejuv(PhyStats.NO_REJUV);
          I.recoverPhyStats();
          updateItems = true;
        }
      }
      lastNumItems = R.numItems();
      if ((!CMSecurity.isSaveFlag(CMSecurity.SaveFlag.NOPROPERTYITEMS)) && (updateItems))
        CMLib.database().DBUpdateItems(R);
    }
    return lastNumItems;
  }