/*
* 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 silentium.gameserver.model;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
import javolution.util.FastMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import silentium.commons.database.DatabaseFactory;
import silentium.gameserver.ThreadPoolManager;
import silentium.gameserver.tables.ItemTable;
import silentium.gameserver.templates.item.L2Item;
public class L2TradeList
{
private final Map<Integer, L2TradeItem> _items;
private final int _listId;
private String _buystorename, _sellstorename;
private boolean _hasLimitedStockItem;
private String _npcId;
public L2TradeList(int listId)
{
_items = new FastMap<>();
_listId = listId;
}
public void setNpcId(String id)
{
_npcId = id;
}
public String getNpcId()
{
return _npcId;
}
public void addItem(L2TradeItem item)
{
_items.put(item.getItemId(), item);
if (item.hasLimitedStock())
setHasLimitedStockItem(true);
}
public void replaceItem(int itemID, int price)
{
L2TradeItem item = _items.get(itemID);
if (item != null)
item.setPrice(price);
}
public void removeItem(int itemID)
{
_items.remove(itemID);
}
/**
* @return Returns the listId.
*/
public int getListId()
{
return _listId;
}
/**
* @param hasLimitedStockItem
* The hasLimitedStockItem to set.
*/
public void setHasLimitedStockItem(boolean hasLimitedStockItem)
{
_hasLimitedStockItem = hasLimitedStockItem;
}
/**
* @return Returns the hasLimitedStockItem.
*/
public boolean hasLimitedStockItem()
{
return _hasLimitedStockItem;
}
public void setSellStoreName(String name)
{
_sellstorename = name;
}
public String getSellStoreName()
{
return _sellstorename;
}
public void setBuyStoreName(String name)
{
_buystorename = name;
}
public String getBuyStoreName()
{
return _buystorename;
}
/**
* @return Returns the items.
*/
public Collection<L2TradeItem> getItems()
{
return _items.values();
}
public List<L2TradeItem> getItems(int start, int end)
{
List<L2TradeItem> list = new LinkedList<>();
list.addAll(_items.values());
return list.subList(start, end);
}
public int getPriceForItemId(int itemId)
{
L2TradeItem item = _items.get(itemId);
if (item != null)
return item.getPrice();
return -1;
}
public L2TradeItem getItemById(int itemId)
{
return _items.get(itemId);
}
public boolean containsItemId(int itemId)
{
return _items.containsKey(itemId);
}
/**
* Itens representation for trade lists
*
* @author KenM
*/
public static class L2TradeItem
{
private static final Logger _log = LoggerFactory.getLogger(L2TradeItem.class.getName());
private final int _listId, _itemId;
private final L2Item _template;
private int _price;
// count related
private final AtomicInteger _currentCount = new AtomicInteger();
private int _maxCount = -1;
private long _restoreDelay, _nextRestoreTime;
public L2TradeItem(int listId, int itemId)
{
_listId = listId;
_itemId = itemId;
_template = ItemTable.getInstance().getTemplate(itemId);
}
/**
* @return Returns the itemId.
*/
public int getItemId()
{
return _itemId;
}
/**
* @param price
* The price to set.
*/
public void setPrice(int price)
{
_price = price;
}
/**
* @return Returns the price.
*/
public int getPrice()
{
return _price;
}
public L2Item getTemplate()
{
return _template;
}
/**
* @param currentCount
* The currentCount to set.
*/
public void setCurrentCount(int currentCount)
{
_currentCount.set(currentCount);
}
public boolean decreaseCount(int val)
{
return _currentCount.addAndGet(-val) >= 0;
}
/**
* @return Returns the currentCount.
*/
public int getCurrentCount()
{
if (hasLimitedStock() && isPendingStockUpdate())
restoreInitialCount();
int ret = _currentCount.get();
return ret > 0 ? ret : 0;
}
public boolean isPendingStockUpdate()
{
return System.currentTimeMillis() >= _nextRestoreTime;
}
public void restoreInitialCount()
{
setCurrentCount(getMaxCount());
_nextRestoreTime = _nextRestoreTime + getRestoreDelay();
// consume until next update is on future
if (isPendingStockUpdate() && getRestoreDelay() > 0)
_nextRestoreTime = System.currentTimeMillis() + getRestoreDelay();
// exec asynchronously
try
{
ThreadPoolManager.getInstance().executeTask(new TimerSave());
}
catch (RejectedExecutionException e)
{
// during shutdown executeTask() failed
saveDataTimer();
}
}
/**
* @param maxCount
* The maxCount to set.
*/
public void setMaxCount(int maxCount)
{
_maxCount = maxCount;
}
/**
* @return Returns the maxCount.
*/
public int getMaxCount()
{
return _maxCount;
}
public boolean hasLimitedStock()
{
return getMaxCount() > -1;
}
/**
* @param restoreDelay
* The restoreDelay to set (in hours)
*/
public void setRestoreDelay(long restoreDelay)
{
_restoreDelay = restoreDelay * 60 * 60 * 1000;
}
/**
* @return Returns the restoreDelay (in milis)
*/
public long getRestoreDelay()
{
return _restoreDelay;
}
/**
* For resuming when server loads
*
* @param nextRestoreTime
* The nextRestoreTime to set.
*/
public void setNextRestoreTime(long nextRestoreTime)
{
_nextRestoreTime = nextRestoreTime;
}
/**
* @return Returns the nextRestoreTime.
*/
public long getNextRestoreTime()
{
return _nextRestoreTime;
}
class TimerSave implements Runnable
{
/**
* @see java.lang.Runnable#run()
*/
@Override
public void run()
{
saveDataTimer();
}
}
protected void saveDataTimer()
{
try (Connection con = DatabaseFactory.getConnection())
{
PreparedStatement statement = con.prepareStatement("UPDATE merchant_buylists SET savetimer =? WHERE shop_id =? and item_id =?");
statement.setLong(1, _nextRestoreTime);
statement.setInt(2, _listId);
statement.setInt(3, _itemId);
statement.executeUpdate();
statement.close();
}
catch (Exception e)
{
_log.error("L2TradeItem: Could not update Timer save in Buylist");
}
}
}
}