Package lineage2.gameserver.instancemanager.itemauction

Source Code of lineage2.gameserver.instancemanager.itemauction.ItemAuctionInstance$ScheduleAuctionTask

/*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package lineage2.gameserver.instancemanager.itemauction;

import gnu.trove.map.hash.TIntObjectHashMap;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import lineage2.commons.dao.JdbcEntityState;
import lineage2.commons.dbutils.DbUtils;
import lineage2.commons.threading.RunnableImpl;
import lineage2.commons.time.cron.SchedulingPattern;
import lineage2.commons.util.Rnd;
import lineage2.gameserver.Announcements;
import lineage2.gameserver.Config;
import lineage2.gameserver.ThreadPoolManager;
import lineage2.gameserver.cache.Msg;
import lineage2.gameserver.database.DatabaseFactory;
import lineage2.gameserver.model.Player;
import lineage2.gameserver.model.items.ItemInstance;
import lineage2.gameserver.model.items.ItemInstance.ItemLocation;
import lineage2.gameserver.network.serverpackets.SystemMessage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* @author Mobius
* @version $Revision: 1.0 $
*/
public class ItemAuctionInstance
{
  /**
   * Field _log.
   */
  private static final Logger _log = LoggerFactory.getLogger(ItemAuctionInstance.class);
  /**
   * Field DATE_FORMAT.
   */
  private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
  /**
   * Field START_TIME_SPACE.
   */
  private static final long START_TIME_SPACE = TimeUnit.MILLISECONDS.convert(1, TimeUnit.MINUTES);
  /**
   * Field FINISH_TIME_SPACE.
   */
  private static final long FINISH_TIME_SPACE = TimeUnit.MILLISECONDS.convert(10, TimeUnit.MINUTES);
  /**
   * Field _instanceId.
   */
  private final int _instanceId;
  /**
   * Field _auctions.
   */
  private final TIntObjectHashMap<ItemAuction> _auctions;
  /**
   * Field _items.
   */
  private final List<AuctionItem> _items;
  /**
   * Field _dateTime.
   */
  private final SchedulingPattern _dateTime;
  /**
   * Field _currentAuction.
   */
  private ItemAuction _currentAuction;
  /**
   * Field _nextAuction.
   */
  private ItemAuction _nextAuction;
  /**
   * Field _stateTask.
   */
  private ScheduledFuture<?> _stateTask;
 
  /**
   * Constructor for ItemAuctionInstance.
   * @param instanceId int
   * @param dateTime SchedulingPattern
   * @param items List<AuctionItem>
   */
  ItemAuctionInstance(int instanceId, SchedulingPattern dateTime, List<AuctionItem> items)
  {
    _instanceId = instanceId;
    _auctions = new TIntObjectHashMap<>();
    _items = items;
    _dateTime = dateTime;
    load();
    _log.info("ItemAuction: Loaded " + _items.size() + " item(s) and registered " + _auctions.size() + " auction(s) for instance " + _instanceId + ".");
    checkAndSetCurrentAndNextAuction();
  }
 
  /**
   * Method load.
   */
  private void load()
  {
    Connection con = null;
    PreparedStatement statement = null;
    ResultSet rset = null;
    try
    {
      con = DatabaseFactory.getInstance().getConnection();
      statement = con.prepareStatement("SELECT auctionId FROM item_auction WHERE instanceId=?");
      statement.setInt(1, _instanceId);
      rset = statement.executeQuery();
      while (rset.next())
      {
        int auctionId = rset.getInt(1);
        try
        {
          ItemAuction auction = loadAuction(auctionId);
          if (auction != null)
          {
            _auctions.put(auctionId, auction);
          }
          else
          {
            ItemAuctionManager.getInstance().deleteAuction(auctionId);
          }
        }
        catch (SQLException e)
        {
          _log.warn("ItemAuction: Failed loading auction: " + auctionId, e);
        }
      }
    }
    catch (SQLException e)
    {
      _log.error("ItemAuction: Failed loading auctions.", e);
      return;
    }
    finally
    {
      DbUtils.closeQuietly(con, statement, rset);
    }
  }
 
  /**
   * Method getCurrentAuction.
   * @return ItemAuction
   */
  public ItemAuction getCurrentAuction()
  {
    return _currentAuction;
  }
 
  /**
   * Method getNextAuction.
   * @return ItemAuction
   */
  public ItemAuction getNextAuction()
  {
    return _nextAuction;
  }
 
  /**
   * Method shutdown.
   */
  public void shutdown()
  {
    ScheduledFuture<?> stateTask = _stateTask;
    if (stateTask != null)
    {
      stateTask.cancel(false);
    }
  }
 
  /**
   * Method getAuctionItem.
   * @param auctionItemId int
   * @return AuctionItem
   */
  private AuctionItem getAuctionItem(int auctionItemId)
  {
    for (int i = _items.size(); i-- > 0;)
    {
      try
      {
        AuctionItem item = _items.get(i);
        if (item.getAuctionItemId() == auctionItemId)
        {
          return item;
        }
      }
      catch (IndexOutOfBoundsException e)
      {
      }
    }
    return null;
  }
 
  /**
   * Method checkAndSetCurrentAndNextAuction.
   */
  void checkAndSetCurrentAndNextAuction()
  {
    ItemAuction[] auctions = _auctions.values(new ItemAuction[_auctions.size()]);
    ItemAuction currentAuction = null;
    ItemAuction nextAuction = null;
    switch (auctions.length)
    {
      case 0:
      {
        nextAuction = createAuction(System.currentTimeMillis() + START_TIME_SPACE);
        break;
      }
      case 1:
      {
        switch (auctions[0].getAuctionState())
        {
          case CREATED:
          {
            if (auctions[0].getStartingTime() < (System.currentTimeMillis() + START_TIME_SPACE))
            {
              currentAuction = auctions[0];
              nextAuction = createAuction(System.currentTimeMillis() + START_TIME_SPACE);
            }
            else
            {
              nextAuction = auctions[0];
            }
            break;
          }
          case STARTED:
          {
            currentAuction = auctions[0];
            nextAuction = createAuction(Math.max(currentAuction.getEndingTime() + FINISH_TIME_SPACE, System.currentTimeMillis() + START_TIME_SPACE));
            break;
          }
          case FINISHED:
          {
            currentAuction = auctions[0];
            nextAuction = createAuction(System.currentTimeMillis() + START_TIME_SPACE);
            break;
          }
          default:
            throw new IllegalArgumentException();
        }
        break;
      }
      default:
      {
        Arrays.sort(auctions, new Comparator<ItemAuction>()
        {
          @Override
          public int compare(ItemAuction o1, ItemAuction o2)
          {
            if (o2.getStartingTime() > o1.getStartingTime())
            {
              return 1;
            }
            if (o2.getStartingTime() < o1.getStartingTime())
            {
              return -1;
            }
            return 0;
          }
        });
        long currentTime = System.currentTimeMillis();
        for (ItemAuction auction : auctions)
        {
          if (auction.getAuctionState() == ItemAuctionState.STARTED)
          {
            currentAuction = auction;
            break;
          }
          else if (auction.getStartingTime() <= currentTime)
          {
            currentAuction = auction;
            break;
          }
        }
        for (ItemAuction auction : auctions)
        {
          if ((auction.getStartingTime() > currentTime) && (currentAuction != auction))
          {
            nextAuction = auction;
            break;
          }
        }
        if (nextAuction == null)
        {
          nextAuction = createAuction(System.currentTimeMillis() + START_TIME_SPACE);
        }
        break;
      }
    }
    _auctions.put(nextAuction.getAuctionId(), nextAuction);
    _currentAuction = currentAuction;
    _nextAuction = nextAuction;
    if ((currentAuction != null) && (currentAuction.getAuctionState() == ItemAuctionState.STARTED))
    {
      setStateTask(ThreadPoolManager.getInstance().schedule(new ScheduleAuctionTask(currentAuction), Math.max(currentAuction.getEndingTime() - System.currentTimeMillis(), 0L)));
      _log.info("ItemAuction: Schedule current auction " + currentAuction.getAuctionId() + " for instance " + _instanceId);
    }
    else
    {
      setStateTask(ThreadPoolManager.getInstance().schedule(new ScheduleAuctionTask(nextAuction), Math.max(nextAuction.getStartingTime() - System.currentTimeMillis(), 0L)));
      _log.info("ItemAuction: Schedule next auction " + nextAuction.getAuctionId() + " on " + DATE_FORMAT.format(new Date(nextAuction.getStartingTime())) + " for instance " + _instanceId);
    }
  }
 
  /**
   * Method getAuction.
   * @param auctionId int
   * @return ItemAuction
   */
  public ItemAuction getAuction(int auctionId)
  {
    return _auctions.get(auctionId);
  }
 
  /**
   * Method getAuctionsByBidder.
   * @param bidderObjId int
   * @return ItemAuction[]
   */
  public ItemAuction[] getAuctionsByBidder(int bidderObjId)
  {
    ItemAuction[] auctions = getAuctions();
    List<ItemAuction> stack = new ArrayList<>(auctions.length);
    for (ItemAuction auction : getAuctions())
    {
      if (auction.getAuctionState() != ItemAuctionState.CREATED)
      {
        ItemAuctionBid bid = auction.getBidFor(bidderObjId);
        if (bid != null)
        {
          stack.add(auction);
        }
      }
    }
    return stack.toArray(new ItemAuction[stack.size()]);
  }
 
  /**
   * Method getAuctions.
   * @return ItemAuction[]
   */
  public ItemAuction[] getAuctions()
  {
    synchronized (_auctions)
    {
      return _auctions.values(new ItemAuction[_auctions.size()]);
    }
  }
 
  /**
   * @author Mobius
   */
  private class ScheduleAuctionTask extends RunnableImpl
  {
    /**
     * Field _auction.
     */
    private final ItemAuction _auction;
   
    /**
     * Constructor for ScheduleAuctionTask.
     * @param auction ItemAuction
     */
    public ScheduleAuctionTask(ItemAuction auction)
    {
      _auction = auction;
    }
   
    /**
     * Method runImpl.
     * @throws Exception
     */
    @Override
    public void runImpl() throws Exception
    {
      ItemAuctionState state = _auction.getAuctionState();
      switch (state)
      {
        case CREATED:
        {
          if (!_auction.setAuctionState(state, ItemAuctionState.STARTED))
          {
            throw new IllegalStateException("Could not set auction state: " + ItemAuctionState.STARTED.toString() + ", expected: " + state.toString());
          }
          _log.info("ItemAuction: Auction " + _auction.getAuctionId() + " has started for instance " + _auction.getInstanceId());
          if (Config.ALT_ITEM_AUCTION_START_ANNOUNCE)
          {
            String[] params = {};
            Announcements.getInstance().announceByCustomMessage("lineage2.gameserver.model.instances.L2ItemAuctionBrokerInstance.announce." + _auction.getInstanceId(), params);
          }
          checkAndSetCurrentAndNextAuction();
          break;
        }
        case STARTED:
        {
          switch (_auction.getAuctionEndingExtendState())
          {
            case 1:
            {
              if (_auction.getScheduledAuctionEndingExtendState() == 0)
              {
                _auction.setScheduledAuctionEndingExtendState(1);
                setStateTask(ThreadPoolManager.getInstance().schedule(this, Math.max(_auction.getEndingTime() - System.currentTimeMillis(), 0L)));
                return;
              }
              break;
            }
            case 2:
            {
              if (_auction.getScheduledAuctionEndingExtendState() != 2)
              {
                _auction.setScheduledAuctionEndingExtendState(2);
                setStateTask(ThreadPoolManager.getInstance().schedule(this, Math.max(_auction.getEndingTime() - System.currentTimeMillis(), 0L)));
                return;
              }
              break;
            }
          }
          if (!_auction.setAuctionState(state, ItemAuctionState.FINISHED))
          {
            throw new IllegalStateException("Could not set auction state: " + ItemAuctionState.FINISHED.toString() + ", expected: " + state.toString());
          }
          onAuctionFinished(_auction);
          checkAndSetCurrentAndNextAuction();
          break;
        }
        default:
          throw new IllegalStateException("Invalid state: " + state);
      }
    }
  }
 
  /**
   * Method onAuctionFinished.
   * @param auction ItemAuction
   */
  void onAuctionFinished(ItemAuction auction)
  {
    auction.broadcastToAllBidders(new SystemMessage(SystemMessage.S1_S_AUCTION_HAS_ENDED).addNumber(auction.getAuctionId()));
    ItemAuctionBid bid = auction.getHighestBid();
    if (bid != null)
    {
      ItemInstance item = auction.createNewItemInstance();
      Player player = bid.getPlayer();
      if (player != null)
      {
        player.getWarehouse().addItem(item);
        player.sendPacket(Msg.YOU_HAVE_BID_THE_HIGHEST_PRICE_AND_HAVE_WON_THE_ITEM_THE_ITEM_CAN_BE_FOUND_IN_YOUR_PERSONAL);
        _log.info("ItemAuction: Auction " + auction.getAuctionId() + " has finished. Highest bid by (name) " + player.getName() + " for instance " + _instanceId);
      }
      else
      {
        item.setOwnerId(bid.getCharId());
        item.setLocation(ItemLocation.WAREHOUSE);
        item.setJdbcState(JdbcEntityState.UPDATED);
        item.update();
        _log.info("ItemAuction: Auction " + auction.getAuctionId() + " has finished. Highest bid by (id) " + bid.getCharId() + " for instance " + _instanceId);
      }
    }
    else
    {
      _log.info("ItemAuction: Auction " + auction.getAuctionId() + " has finished. There have not been any bid for instance " + _instanceId);
    }
  }
 
  /**
   * Method setStateTask.
   * @param future ScheduledFuture<?>
   */
  void setStateTask(ScheduledFuture<?> future)
  {
    ScheduledFuture<?> stateTask = _stateTask;
    if (stateTask != null)
    {
      stateTask.cancel(false);
    }
    _stateTask = future;
  }
 
  /**
   * Method createAuction.
   * @param after long
   * @return ItemAuction
   */
  private ItemAuction createAuction(long after)
  {
    AuctionItem auctionItem = _items.get(Rnd.get(_items.size()));
    long startingTime = _dateTime.next(after);
    long endingTime = startingTime + TimeUnit.MILLISECONDS.convert(auctionItem.getAuctionLength(), TimeUnit.MINUTES);
    int auctionId = ItemAuctionManager.getInstance().getNextId();
    ItemAuction auction = new ItemAuction(auctionId, _instanceId, startingTime, endingTime, auctionItem, ItemAuctionState.CREATED);
    auction.store();
    return auction;
  }
 
  /**
   * Method loadAuction.
   * @param auctionId int
   * @return ItemAuction * @throws SQLException
   */
  private ItemAuction loadAuction(int auctionId) throws SQLException
  {
    Connection con = null;
    PreparedStatement statement = null;
    ResultSet rset = null;
    try
    {
      con = DatabaseFactory.getInstance().getConnection();
      statement = con.prepareStatement("SELECT auctionItemId,startingTime,endingTime,auctionStateId FROM item_auction WHERE auctionId=?");
      statement.setInt(1, auctionId);
      rset = statement.executeQuery();
      if (!rset.next())
      {
        _log.warn("ItemAuction: Auction data not found for auction: " + auctionId);
        return null;
      }
      int auctionItemId = rset.getInt(1);
      long startingTime = rset.getLong(2);
      long endingTime = rset.getLong(3);
      int auctionStateId = rset.getInt(4);
      DbUtils.close(statement, rset);
      if (startingTime >= endingTime)
      {
        _log.warn("ItemAuction: Invalid starting/ending paramaters for auction: " + auctionId);
        return null;
      }
      AuctionItem auctionItem = getAuctionItem(auctionItemId);
      if (auctionItem == null)
      {
        _log.warn("ItemAuction: AuctionItem: " + auctionItemId + ", not found for auction: " + auctionId);
        return null;
      }
      ItemAuctionState auctionState = ItemAuctionState.stateForStateId(auctionStateId);
      if (auctionState == null)
      {
        _log.warn("ItemAuction: Invalid auctionStateId: " + auctionStateId + ", for auction: " + auctionId);
        return null;
      }
      ItemAuction auction = new ItemAuction(auctionId, _instanceId, startingTime, endingTime, auctionItem, auctionState);
      statement = con.prepareStatement("SELECT playerObjId,playerBid FROM item_auction_bid WHERE auctionId=?");
      statement.setInt(1, auctionId);
      rset = statement.executeQuery();
      while (rset.next())
      {
        int charId = rset.getInt(1);
        long playerBid = rset.getLong(2);
        ItemAuctionBid bid = new ItemAuctionBid(charId, playerBid);
        auction.addBid(bid);
      }
      return auction;
    }
    finally
    {
      DbUtils.closeQuietly(con, statement, rset);
    }
  }
}
TOP

Related Classes of lineage2.gameserver.instancemanager.itemauction.ItemAuctionInstance$ScheduleAuctionTask

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.