SHARE
TWEET

com.l2jserver.gameserver.model.itemauction.ItemAuction

fforc9e Apr 28th, 2014 156 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  * This program is free software: you can redistribute it and/or modify it under
  3.  * the terms of the GNU General Public License as published by the Free Software
  4.  * Foundation, either version 3 of the License, or (at your option) any later
  5.  * version.
  6.  *
  7.  * This program is distributed in the hope that it will be useful, but WITHOUT
  8.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9.  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  10.  * details.
  11.  *
  12.  * You should have received a copy of the GNU General Public License along with
  13.  * this program. If not, see <http://www.gnu.org/licenses/>.
  14.  */
  15. package com.l2jserver.gameserver.model.itemauction;
  16.  
  17. import java.sql.Connection;
  18. import java.sql.PreparedStatement;
  19. import java.sql.SQLException;
  20. import java.util.ArrayList;
  21. import java.util.concurrent.TimeUnit;
  22. import java.util.logging.Level;
  23. import java.util.logging.Logger;
  24.  
  25. import com.l2jserver.Config;
  26. import com.l2jserver.L2DatabaseFactory;
  27. import com.l2jserver.gameserver.ThreadPoolManager;
  28. import com.l2jserver.gameserver.instancemanager.ItemAuctionManager;
  29. import com.l2jserver.gameserver.model.ItemInfo;
  30. import com.l2jserver.gameserver.model.L2ItemInstance;
  31. import com.l2jserver.gameserver.model.L2World;
  32. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  33. import com.l2jserver.gameserver.network.SystemMessageId;
  34. import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
  35. import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
  36.  
  37. /**
  38.  * @author Forsaiken
  39.  */
  40. public final class ItemAuction
  41. {
  42.         static final Logger _log = Logger.getLogger(ItemAuctionManager.class.getName());
  43.         private static final long ENDING_TIME_EXTEND_5 = TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES);
  44.         private static final long ENDING_TIME_EXTEND_3 = TimeUnit.MILLISECONDS.convert(3, TimeUnit.MINUTES);
  45.        
  46.         private final int _auctionId;
  47.         private final int _instanceId;
  48.         private final long _startingTime;
  49.         private volatile long _endingTime;
  50.         private final AuctionItem _auctionItem;
  51.         private final ArrayList<ItemAuctionBid> _auctionBids;
  52.         private final Object _auctionStateLock;
  53.        
  54.         private volatile ItemAuctionState _auctionState;
  55.         private volatile ItemAuctionExtendState _scheduledAuctionEndingExtendState;
  56.         private volatile ItemAuctionExtendState _auctionEndingExtendState;
  57.        
  58.         private final ItemInfo _itemInfo;
  59.        
  60.         private ItemAuctionBid _highestBid;
  61.         private int _lastBidPlayerObjId;
  62.        
  63.         public ItemAuction(final int auctionId, final int instanceId, final long startingTime, final long endingTime, final AuctionItem auctionItem)
  64.         {
  65.                 this(auctionId, instanceId, startingTime, endingTime, auctionItem, new ArrayList<ItemAuctionBid>(), ItemAuctionState.CREATED);
  66.         }
  67.        
  68.         public ItemAuction(final int auctionId, final int instanceId, final long startingTime, final long endingTime, final AuctionItem auctionItem, final ArrayList<ItemAuctionBid> auctionBids, final ItemAuctionState auctionState)
  69.         {
  70.                 _auctionId = auctionId;
  71.                 _instanceId = instanceId;
  72.                 _startingTime = startingTime;
  73.                 _endingTime = endingTime;
  74.                 _auctionItem = auctionItem;
  75.                 _auctionBids = auctionBids;
  76.                 _auctionState = auctionState;
  77.                 _auctionStateLock = new Object();
  78.                 _scheduledAuctionEndingExtendState = ItemAuctionExtendState.INITIAL;
  79.                 _auctionEndingExtendState = ItemAuctionExtendState.INITIAL;
  80.                
  81.                 final L2ItemInstance item  = _auctionItem.createNewItemInstance();
  82.                 _itemInfo = new ItemInfo(item);
  83.                 L2World.getInstance().removeObject(item);
  84.                
  85.                 for (final ItemAuctionBid bid : _auctionBids)
  86.                 {
  87.                         if (_highestBid == null || _highestBid.getLastBid() < bid.getLastBid())
  88.                                 _highestBid = bid;
  89.                 }
  90.         }
  91.        
  92.         public final ItemAuctionState getAuctionState()
  93.         {
  94.                 final ItemAuctionState auctionState;
  95.                
  96.                 synchronized (_auctionStateLock)
  97.                 {
  98.                         auctionState = _auctionState;
  99.                 }
  100.                
  101.                 return auctionState;
  102.         }
  103.        
  104.         public final boolean setAuctionState(final ItemAuctionState expected, final ItemAuctionState wanted)
  105.         {
  106.                 synchronized (_auctionStateLock)
  107.                 {
  108.                         if (_auctionState != expected)
  109.                                 return false;
  110.                        
  111.                         _auctionState = wanted;
  112.                         storeMe();
  113.                         return true;
  114.                 }
  115.         }
  116.        
  117.         public final int getAuctionId()
  118.         {
  119.                 return _auctionId;
  120.         }
  121.        
  122.         public final int getInstanceId()
  123.         {
  124.                 return _instanceId;
  125.         }
  126.        
  127.         public final ItemInfo getItemInfo()
  128.         {
  129.                 return _itemInfo;
  130.         }
  131.        
  132.         public final L2ItemInstance createNewItemInstance()
  133.         {
  134.                 return _auctionItem.createNewItemInstance();
  135.         }
  136.        
  137.         public final long getAuctionInitBid()
  138.         {
  139.                 return _auctionItem.getAuctionInitBid();
  140.         }
  141.        
  142.         public final ItemAuctionBid getHighestBid()
  143.         {
  144.                 return _highestBid;
  145.         }
  146.        
  147.         public final ItemAuctionExtendState getAuctionEndingExtendState()
  148.         {
  149.                 return _auctionEndingExtendState;
  150.         }
  151.        
  152.         public final ItemAuctionExtendState getScheduledAuctionEndingExtendState()
  153.         {
  154.                 return _scheduledAuctionEndingExtendState;
  155.         }
  156.        
  157.         public final void setScheduledAuctionEndingExtendState(ItemAuctionExtendState state)
  158.         {
  159.                 _scheduledAuctionEndingExtendState = state;
  160.         }
  161.        
  162.         public final long getStartingTime()
  163.         {
  164.                 return _startingTime;
  165.         }
  166.        
  167.         public final long getEndingTime()
  168.         {
  169.                 return _endingTime;
  170.         }
  171.        
  172.         public final long getStartingTimeRemaining()
  173.         {
  174.                 return Math.max(getEndingTime() - System.currentTimeMillis(), 0L);
  175.         }
  176.        
  177.         public final long getFinishingTimeRemaining()
  178.         {
  179.                 return Math.max(getEndingTime() - System.currentTimeMillis(), 0L);
  180.         }
  181.        
  182.         public final void storeMe()
  183.         {
  184.                 Connection con = null;
  185.                 try
  186.                 {
  187.                         con = L2DatabaseFactory.getInstance().getConnection();
  188.                         PreparedStatement statement = con.prepareStatement("INSERT INTO item_auction (auctionId,instanceId,auctionItemId,startingTime,endingTime,auctionStateId) VALUES (?,?,?,?,?,?) ON DUPLICATE KEY UPDATE auctionStateId=?");
  189.                         statement.setInt(1, _auctionId);
  190.                         statement.setInt(2, _instanceId);
  191.                         statement.setInt(3, _auctionItem.getAuctionItemId());
  192.                         statement.setLong(4, _startingTime);
  193.                         statement.setLong(5, _endingTime);
  194.                         statement.setByte(6, _auctionState.getStateId());
  195.                         statement.setByte(7, _auctionState.getStateId());
  196.                         statement.execute();
  197.                         statement.close();
  198.                 }
  199.                 catch (final SQLException e)
  200.                 {
  201.                         _log.log(Level.WARNING, "", e);
  202.                 }
  203.                 finally
  204.                 {
  205.                         L2DatabaseFactory.close(con);
  206.                 }
  207.         }
  208.        
  209.         public final int getAndSetLastBidPlayerObjectId(final int playerObjId)
  210.         {
  211.                 final int lastBid = _lastBidPlayerObjId;
  212.                 _lastBidPlayerObjId = playerObjId;
  213.                 return lastBid;
  214.         }
  215.        
  216.         private final void updatePlayerBid(final ItemAuctionBid bid, final boolean delete)
  217.         {
  218.                 // TODO nBd maybe move such stuff to you db updater :D
  219.                 updatePlayerBidInternal(bid, delete);
  220.         }
  221.        
  222.         final void updatePlayerBidInternal(final ItemAuctionBid bid, final boolean delete)
  223.         {
  224.                 Connection con = null;
  225.                 try
  226.                 {
  227.                         con = L2DatabaseFactory.getInstance().getConnection();
  228.                         final PreparedStatement statement;
  229.                        
  230.                         if (delete)
  231.                         {
  232.                                 statement = con.prepareStatement("DELETE FROM item_auction_bid WHERE auctionId=? AND playerObjId=?");
  233.                                 statement.setInt(1, _auctionId);
  234.                                 statement.setInt(2, bid.getPlayerObjId());
  235.                         }
  236.                         else
  237.                         {
  238.                                 statement = con.prepareStatement("INSERT INTO item_auction_bid (auctionId,playerObjId,playerBid) VALUES (?,?,?) ON DUPLICATE KEY UPDATE playerBid=?");
  239.                                 statement.setInt(1, _auctionId);
  240.                                 statement.setInt(2, bid.getPlayerObjId());
  241.                                 statement.setLong(3, bid.getLastBid());
  242.                                 statement.setLong(4, bid.getLastBid());
  243.                         }
  244.                        
  245.                         statement.execute();
  246.                         statement.close();
  247.                 }
  248.                 catch (SQLException e)
  249.                 {
  250.                         _log.log(Level.WARNING, "", e);
  251.                 }
  252.                 finally
  253.                 {
  254.                         L2DatabaseFactory.close(con);
  255.                 }
  256.         }
  257.        
  258.         public final void registerBid(final L2PcInstance player, final long newBid)
  259.         {
  260.                 if (player == null)
  261.                         throw new NullPointerException();
  262.                
  263.                 if (newBid < getAuctionInitBid())
  264.                 {
  265.                         player.sendPacket(new SystemMessage(SystemMessageId.BID_PRICE_MUST_BE_HIGHER));
  266.                         return;
  267.                 }
  268.                
  269.                 if (newBid > 100000000000L)
  270.                 {
  271.                         player.sendPacket(new SystemMessage(SystemMessageId.BID_CANT_EXCEED_100_BILLION));
  272.                         return;
  273.                 }
  274.                
  275.                 if (getAuctionState() != ItemAuctionState.STARTED)
  276.                         return;
  277.                
  278.                 final int playerObjId = player.getObjectId();
  279.                
  280.                 synchronized (_auctionBids)
  281.                 {
  282.                         if (_highestBid != null && newBid < _highestBid.getLastBid())
  283.                         {
  284.                                 player.sendPacket(new SystemMessage(SystemMessageId.BID_MUST_BE_HIGHER_THAN_CURRENT_BID));
  285.                                 return;
  286.                         }
  287.                        
  288.                         ItemAuctionBid bid = getBidFor(playerObjId);
  289.                         if (bid == null)
  290.                         {
  291.                                 if (!reduceItemCount(player, newBid))
  292.                                 {
  293.                                         player.sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_ADENA_FOR_THIS_BID));
  294.                                         return;
  295.                                 }
  296.                                
  297.                                 bid = new ItemAuctionBid(playerObjId, newBid);
  298.                                 _auctionBids.add(bid);
  299.                         }
  300.                         else
  301.                         {
  302.                                 if (!bid.isCanceled())
  303.                                 {
  304.                                         if (newBid < bid.getLastBid()) // just another check
  305.                                         {
  306.                                                 player.sendPacket(new SystemMessage(SystemMessageId.BID_MUST_BE_HIGHER_THAN_CURRENT_BID));
  307.                                                 return;
  308.                                         }
  309.                                        
  310.                                         if (!reduceItemCount(player, newBid - bid.getLastBid()))
  311.                                         {
  312.                                                 player.sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_ADENA_FOR_THIS_BID));
  313.                                                 return;
  314.                                         }
  315.                                 }
  316.                                 else if (!reduceItemCount(player, newBid))
  317.                                 {
  318.                                         player.sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_ADENA_FOR_THIS_BID));
  319.                                         return;
  320.                                 }
  321.                                
  322.                                 bid.setLastBid(newBid);
  323.                         }
  324.                        
  325.                         onPlayerBid(player, bid);
  326.                         updatePlayerBid(bid, false);
  327.                        
  328.                         player.sendPacket(new SystemMessage(SystemMessageId.SUBMITTED_A_BID).addItemNumber(newBid));
  329.                         return;
  330.                 }
  331.         }
  332.        
  333.         private final void onPlayerBid(final L2PcInstance player, final ItemAuctionBid bid)
  334.         {
  335.                 if (_highestBid == null)
  336.                 {
  337.                         _highestBid = bid;
  338.                 }
  339.                 else if (_highestBid.getLastBid() < bid.getLastBid())
  340.                 {
  341.                         final L2PcInstance old = _highestBid.getPlayer();
  342.                         if (old != null)
  343.                                 old.sendPacket(new SystemMessage(SystemMessageId.YOU_HAVE_BEEN_OUTBID));
  344.                        
  345.                         _highestBid = bid;
  346.                 }
  347.                
  348.                 if (getEndingTime() - System.currentTimeMillis() <= (1000 * 60 * 10)) // 10 minutes
  349.                 {
  350.                         switch (_auctionEndingExtendState)
  351.                         {
  352.                                 case INITIAL:
  353.                                 {
  354.                                         _auctionEndingExtendState = ItemAuctionExtendState.EXTEND_BY_5_MIN;
  355.                                         _endingTime += ENDING_TIME_EXTEND_5;
  356.                                         broadcastToAllBidders(new SystemMessage(SystemMessageId.BIDDER_EXISTS_AUCTION_TIME_EXTENDED_BY_5_MINUTES));
  357.                                         break;
  358.                                 }
  359.                                 case EXTEND_BY_5_MIN:
  360.                                 {
  361.                                         if (getAndSetLastBidPlayerObjectId(player.getObjectId()) != player.getObjectId())
  362.                                         {
  363.                                                 _auctionEndingExtendState = ItemAuctionExtendState.EXTEND_BY_3_MIN;
  364.                                                 _endingTime += ENDING_TIME_EXTEND_3;
  365.                                                 broadcastToAllBidders(new SystemMessage(SystemMessageId.BIDDER_EXISTS_AUCTION_TIME_EXTENDED_BY_3_MINUTES));
  366.                                         }
  367.                                         break;
  368.                                 }
  369.                                 case EXTEND_BY_3_MIN:
  370.                                         if (Config.ALT_ITEM_AUCTION_TIME_EXTENDS_ON_BID > 0)
  371.                                         {
  372.                                                 if (getAndSetLastBidPlayerObjectId(player.getObjectId()) != player.getObjectId())
  373.                                                 {
  374.                                                         _auctionEndingExtendState = ItemAuctionExtendState.EXTEND_BY_CONFIG_PHASE_A;
  375.                                                         _endingTime += Config.ALT_ITEM_AUCTION_TIME_EXTENDS_ON_BID;
  376.                                                 }
  377.                                         }
  378.                                         break;
  379.                                 case EXTEND_BY_CONFIG_PHASE_A:
  380.                                 {
  381.                                         if (getAndSetLastBidPlayerObjectId(player.getObjectId()) != player.getObjectId())
  382.                                         {
  383.                                                 if (_scheduledAuctionEndingExtendState == ItemAuctionExtendState.EXTEND_BY_CONFIG_PHASE_B)
  384.                                                 {
  385.                                                         _auctionEndingExtendState = ItemAuctionExtendState.EXTEND_BY_CONFIG_PHASE_B;
  386.                                                         _endingTime += Config.ALT_ITEM_AUCTION_TIME_EXTENDS_ON_BID;
  387.                                                 }
  388.                                         }
  389.                                         break;
  390.                                 }
  391.                                 case EXTEND_BY_CONFIG_PHASE_B:
  392.                                 {
  393.                                         if (getAndSetLastBidPlayerObjectId(player.getObjectId()) != player.getObjectId())
  394.                                         {
  395.                                                 if (_scheduledAuctionEndingExtendState == ItemAuctionExtendState.EXTEND_BY_CONFIG_PHASE_A)
  396.                                                 {
  397.                                                         _endingTime += Config.ALT_ITEM_AUCTION_TIME_EXTENDS_ON_BID;
  398.                                                         _auctionEndingExtendState = ItemAuctionExtendState.EXTEND_BY_CONFIG_PHASE_A;
  399.                                                 }
  400.                                         }
  401.                                 }
  402.                         }
  403.                 }
  404.         }
  405.        
  406.         public final void broadcastToAllBidders(final L2GameServerPacket packet)
  407.         {
  408.                 ThreadPoolManager.getInstance().executeTask(new Runnable()
  409.                 {
  410.                         @Override
  411.                         public final void run()
  412.                         {
  413.                                 broadcastToAllBiddersInternal(packet);
  414.                         }
  415.                 });
  416.         }
  417.        
  418.         public final void broadcastToAllBiddersInternal(final L2GameServerPacket packet)
  419.         {
  420.                 for (int i = _auctionBids.size(); i-- > 0;)
  421.                 {
  422.                         final ItemAuctionBid bid = _auctionBids.get(i);
  423.                         if (bid != null)
  424.                         {
  425.                                 final L2PcInstance player = bid.getPlayer();
  426.                                 if (player != null)
  427.                                         player.sendPacket(packet);
  428.                         }
  429.                 }
  430.         }
  431.        
  432.         public final boolean cancelBid(final L2PcInstance player)
  433.         {
  434.                 if (player == null)
  435.                         throw new NullPointerException();
  436.                
  437.                 switch (getAuctionState())
  438.                 {
  439.                         case CREATED:
  440.                                 return false;
  441.                                
  442.                         case FINISHED:
  443.                                 if (_startingTime < System.currentTimeMillis() - TimeUnit.MILLISECONDS.convert(Config.ALT_ITEM_AUCTION_EXPIRED_AFTER, TimeUnit.DAYS))
  444.                                         return false;
  445.                                 else
  446.                                         break;
  447.                 }
  448.                
  449.                 final int playerObjId = player.getObjectId();
  450.                
  451.                 synchronized (_auctionBids)
  452.                 {
  453.                         if (_highestBid == null)
  454.                                 return false;
  455.                        
  456.                         final int bidIndex = getBidIndexFor(playerObjId);
  457.                         if (bidIndex == -1)
  458.                                 return false;
  459.                        
  460.                         final ItemAuctionBid bid = _auctionBids.get(bidIndex);
  461.                         if (bid.getPlayerObjId() == _highestBid.getPlayerObjId())
  462.                         {
  463.                                 // can't return winning bid
  464.                                 if (getAuctionState() == ItemAuctionState.FINISHED)
  465.                                         return false;
  466.                                
  467.                                 player.sendPacket(new SystemMessage(SystemMessageId.HIGHEST_BID_BUT_RESERVE_NOT_MET));
  468.                                 return true;
  469.                         }
  470.                        
  471.                         if (bid.isCanceled())
  472.                                 return false;
  473.                        
  474.                         increaseItemCount(player, bid.getLastBid());
  475.                         bid.cancelBid();
  476.                        
  477.                         // delete bid from database if auction already finished
  478.                         updatePlayerBid(bid, getAuctionState() == ItemAuctionState.FINISHED);
  479.                        
  480.                         player.sendPacket(new SystemMessage(SystemMessageId.CANCELED_BID));
  481.                 }
  482.                 return true;
  483.         }
  484.        
  485.         public final void clearCanceledBids()
  486.         {
  487.                 if (getAuctionState() != ItemAuctionState.FINISHED)
  488.                         throw new IllegalStateException("Attempt to clear canceled bids for non-finished auction");
  489.                
  490.                 synchronized (_auctionBids)
  491.                 {
  492.                         for (ItemAuctionBid bid : _auctionBids)
  493.                         {
  494.                                 if (bid == null || !bid.isCanceled())
  495.                                         continue;
  496.                                 updatePlayerBid(bid, true);
  497.                         }
  498.                 }
  499.         }
  500.        
  501.         private final boolean reduceItemCount(final L2PcInstance player, final long count)
  502.         {
  503.                 if (!player.reduceAdena("ItemAuction", count, player, true))
  504.                 {
  505.                         player.sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_ADENA_FOR_THIS_BID));
  506.                         return false;
  507.                 }
  508.                 return true;
  509.         }
  510.        
  511.         private final void increaseItemCount(final L2PcInstance player, final long count)
  512.         {
  513.                 player.addAdena("ItemAuction", count, player, true);
  514.         }
  515.        
  516.         /**
  517.          * Returns the last bid for the given player or -1 if he did not made one yet.
  518.          *
  519.          * @param player The player that made the bid
  520.          * @return The last bid the player made or -1
  521.          */
  522.         public final long getLastBid(final L2PcInstance player)
  523.         {
  524.                 final ItemAuctionBid bid = getBidFor(player.getObjectId());
  525.                 return bid != null ? bid.getLastBid() : -1L;
  526.         }
  527.        
  528.         public final ItemAuctionBid getBidFor(final int playerObjId)
  529.         {
  530.                 final int index = getBidIndexFor(playerObjId);
  531.                 return index != -1 ? _auctionBids.get(index) : null;
  532.         }
  533.        
  534.         private final int getBidIndexFor(final int playerObjId)
  535.         {
  536.                 for (int i = _auctionBids.size(); i-- > 0;)
  537.                 {
  538.                         final ItemAuctionBid bid = _auctionBids.get(i);
  539.                         if (bid != null && bid.getPlayerObjId() == playerObjId)
  540.                                 return i;
  541.                 }
  542.                 return -1;
  543.         }
  544. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top