package l2p.gameserver.modules;
import l2p.Config;
import l2p.database.DatabaseUtils;
import l2p.database.FiltredPreparedStatement;
import l2p.database.L2DatabaseFactory;
import l2p.database.ThreadConnection;
import l2p.gameserver.model.L2Player;
import l2p.gameserver.model.items.L2ItemInstance;
import l2p.gameserver.modules.option.mOption;
import l2p.gameserver.serverpackets.ExBR_BuyProductResult;
import l2p.gameserver.serverpackets.ExBR_GamePoint;
import l2p.gameserver.serverpackets.ExBR_ProductInfo;
import l2p.gameserver.serverpackets.ExBR_ProductList;
import l2p.gameserver.serverpackets.SystemMessage;
import l2p.gameserver.tables.ItemTable;
import l2p.gameserver.templates.L2Item;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.sql.ResultSet;
import java.util.Calendar;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.logging.Logger;
/**
* User: Shaitan
* Date: 13.01.11
* Time: 7:40
*/
@SuppressWarnings("unchecked")
public class CashShop
{
private static final Logger _log = Logger.getLogger(CashShop.class.getName());
private static CashShop b = new CashShop();
public static CashShop getInstance()
{
return b;
}
public void requestBuyItem(L2Player player, int brId, int count)
{
if(count > MAX_BUY_COUNT)
{
count = MAX_BUY_COUNT;
}
if(count < 1)
{
count = 1;
}
CashShopItem item = shop.get(brId);
if(item == null)
{
sendResult(player, BR_BUY_INVALID_PRODUCT);
return;
}
Calendar cal = Calendar.getInstance();
if(item.iStartSale > 0 && (item.iStartSale > (int) (cal.getTimeInMillis() / 1000)))
{
sendResult(player, BR_BUY_BEFORE_SALE_DATE);
return;
}
if(item.iEndSale > 0 && (item.iEndSale < (int) (cal.getTimeInMillis() / 1000)))
{
sendResult(player, BR_BUY_AFTER_SALE_DATE);
return;
}
if(item.iStartHour != 0 || item.iStartMin != 0 || item.iEndHour != 0 || item.iEndMin != 0)
{
if((item.iStartHour > cal.get(Calendar.HOUR_OF_DAY) && item.iStartMin > cal.get(Calendar.HOUR_OF_DAY))
|| (item.iEndHour < cal.get(Calendar.HOUR_OF_DAY) && item.iEndMin < cal.get(Calendar.HOUR_OF_DAY)))
{
sendResult(player, BR_BUY_NOT_TIME_OF_DAY);
return;
}
}
if(item.isLimited() && (item.limit() || item.iMaxStock - item.iStock < count))
{
sendResult(player, BR_BUY_SOLD_OUT);
return;
}
if(Config.itemmallType == 1)
{
if(!mOption.cash(player, cash, item.price * count))
{
sendResult(player, BR_BUY_LACK_OF_POINT);
return;
}
}
else if(Config.itemmallType == 2)
{
if(!mOption.price(player, Config.itemmallItem, item.price * count))
{
sendResult(player, BR_BUY_LACK_OF_POINT);
return;
}
}
validateMyPoints(player);
L2Item dummy = ItemTable.getInstance().getTemplate(item.template.itemId);
if(dummy.isStackable())
{
if(!player.getInventory().validateWeight(dummy.getWeight() * item.count * count))
{
sendResult(player, BR_BUY_INVENTROY_OVERFLOW);
return;
}
if(player.getInventory().getItemByItemId(item.template.itemId) == null && !player.getInventory().validateCapacity(1))
{
sendResult(player, BR_BUY_INVENTROY_OVERFLOW);
return;
}
player.getInventory().addItem(item.template.itemId, item.count * count);
player.sendPacket(new SystemMessage(53).addItemName(item.template.itemId).addNumber(count));
}
else
{
if(!player.getInventory().validateCapacity(item.count * count) || !player.getInventory().validateWeight(dummy.getWeight() * item.count * count))
{
sendResult(player, BR_BUY_INVENTROY_OVERFLOW);
return;
}
for(int i = 0; i < count * item.count; i++)
{
player.getInventory().addItem(item.template.itemId, 1);
player.sendPacket(new SystemMessage(54).addItemName(item.template.itemId));
}
}
if(item.isLimited())
{
synchronized(item)
{
item.iStock += count;
}
}
item.iSale += count;
sendResult(player, BR_BUY_SUCCESS);
}
public final int BR_BUY_SUCCESS = 1; //The item has been successfully purchased.
public final int BR_BUY_LACK_OF_POINT = -1; //Game points are not enough.
public final int BR_BUY_INVALID_PRODUCT = -2; //Product Purchase Error - The product is not right.
public final int BR_BUY_USER_CANCEL = -3; //The item has failed to be purchased.
public final int BR_BUY_INVENTROY_OVERFLOW = -4; //The item cannot be received because the inventory weight/quantity limit has been exceeded.
public final int BR_BUY_CLOSED_PRODUCT = -5; //Product Purchase Error - The product is not right.
public final int BR_BUY_SERVER_ERROR = -6; //The item has failed to be purchased.
public final int BR_BUY_BEFORE_SALE_DATE = -7; //The item you selected cannot be purchased. Unfortunately, the sale period ended.
public final int BR_BUY_AFTER_SALE_DATE = -8; //The item you selected cannot be purchased. Unfortunately, the sale period ended.
public final int BR_BUY_INVALID_USER = -9; //Product Purchase Error - The user state is not right.
public final int BR_BUY_INVALID_ITEM = -10; //Product Purchase Error - The item within the product is not right.
public final int BR_BUY_INVALID_USER_STATE = -11; //Product Purchase Error - The user state is not right.
public final int BR_BUY_NOT_DAY_OF_WEEK = -12; //You cannot buy the item on this day of the week.
public final int BR_BUY_NOT_TIME_OF_DAY = -13; //You cannot buy the item at this hour.
public final int BR_BUY_SOLD_OUT = -14; //Item out of stock.
public final int MAX_BUY_COUNT = 99;
private Map<Integer, CashShopItemTemplate> brTemplates = new HashMap<Integer, CashShopItemTemplate>();
private Map<Integer, CashShopItem> shop = new HashMap<Integer, CashShopItem>();
protected ExBR_ProductList list = null;
public int cash; //Current cash of player.
public CashShop()
{
loadTempaltes();
loadShop();
}
private void loadTempaltes()
{
brTemplates = new HashMap<Integer, CashShopItemTemplate>();
try
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setIgnoringComments(true);
final File file = new File(Config.DATAPACK_ROOT + "/data/item-mall.xml");
final Document doc = factory.newDocumentBuilder().parse(file);
for(Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if("list".equalsIgnoreCase(n.getNodeName()))
{
for(Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if("item".equalsIgnoreCase(d.getNodeName()))
{
NamedNodeMap attrs = d.getAttributes();
int brId = Integer.parseInt(attrs.getNamedItem("brId").getNodeValue());
int itemId = 0;
try
{
itemId = Integer.parseInt(attrs.getNamedItem("itemId").getNodeValue());
}
catch(NumberFormatException e)
{
}
if(itemId == 0)
{
continue;
}
int cat = Integer.parseInt(attrs.getNamedItem("category").getNodeValue());
CashShopItemTemplate csit = new CashShopItemTemplate();
csit.brId = brId;
csit.itemId = itemId;
csit.category = cat;
brTemplates.put(csit.itemId, csit);
}
}
}
}
}
catch(Exception e)
{
_log.severe("CashShop: Error parsing item-moll.xml file. ");
e.printStackTrace();
}
_log.info("CashShop: loaded " + brTemplates.size() + " item templates.");
}
private void loadShop()
{
shop = new HashMap<Integer, CashShopItem>();
ThreadConnection con = null;
FiltredPreparedStatement statement = null;
ResultSet result = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
statement = con.prepareStatement("SELECT * FROM item_mall WHERE onSale=1 ORDER BY ord");
result = statement.executeQuery();
while(result.next())
{
int itemId = result.getInt("itemId");
CashShopItemTemplate template = brTemplates.get(itemId);
if(template == null)
{
_log.warning("CashShop: item template for " + itemId + " was not found. skipping.");
continue;
}
CashShopItem item = new CashShopItem(template);
item.count = result.getInt("count");
item.price = result.getInt("price");
item.order = result.getInt("ord");
item.iCategory2 = result.getInt("iCategory2");
item.iStartSale = result.getInt("iStartSale");
item.iEndSale = result.getInt("iEndSale");
item.iStartHour = result.getInt("iStartHour");
item.iStartMin = result.getInt("iStartMin");
item.iEndHour = result.getInt("iEndHour");
item.iEndMin = result.getInt("iEndMin");
item.iStock = result.getInt("iStock");
item.iMaxStock = result.getInt("iMaxStock");
L2Item dummy = ItemTable.getInstance().getTemplate(itemId);
item.iWeight = dummy.getWeight();
item.iDropable = dummy.isDropable();
shop.put(item.template.brId, item);
}
}
catch(final Exception e)
{
_log.warning("CashShop: error in loadShop() " + e);
}
finally
{
DatabaseUtils.closeDatabaseCSR(con, statement, result);
}
_log.info("CashShop: loaded " + shop.size() + " items available for trading.");
list = new ExBR_ProductList();
Map<CashShopItem, Integer> data1 = new LinkedHashMap<CashShopItem, Integer>();
for(CashShopItem csi : shop.values())
{
data1.put(csi, csi.order);
}
data1 = ValueSortMap.sortMapByValue(data1, true);
list.collection = data1.keySet();
}
public void saveData()
{
ThreadConnection con = null;
FiltredPreparedStatement statement = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
for(CashShopItem csi : shop.values())
{
if(csi.isLimited())
{
statement = con.prepareStatement("UPDATE item_mall set iStock=? where ord=?");
statement.setInt(1, csi.iStock);
statement.setInt(2, csi.order);
statement.executeUpdate();
statement.close();
}
}
}
catch(final Exception e)
{
_log.warning("CashShop: error in saveData() " + e);
}
finally
{
DatabaseUtils.closeDatabaseCS(con, statement);
}
}
public class CashShopItemTemplate
{
public int brId, itemId, category;
}
public class CashShopItem
{
public CashShopItemTemplate template = null;
public int count, price;
public int order;
public int iSale = 0;
int iDayWeek;// TODO?
public int iCategory2;
public int iStartSale;
public int iEndSale;
public int iStartHour;
public int iStartMin;
public int iEndHour;
public int iEndMin;
public int iStock;
public int iMaxStock;
public int iWeight;
public boolean iDropable;
public CashShopItem(CashShopItemTemplate t)
{
template = t;
}
public boolean limit()
{
return iStock >= iMaxStock;
}
public boolean isLimited()
{
return iMaxStock > 0;
}
}
public void sendResult(L2Player player, int code)
{
player.sendPacket(new ExBR_BuyProductResult(code));
}
public void validateMyPoints(L2Player player)
{
if(Config.itemmallType == 1)
{
//Point system (Database)
//NOT TESTED
ThreadConnection con = null;
FiltredPreparedStatement statement = null;
ResultSet rset = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
statement = con.prepareStatement("SELECT `cash` FROM `character_cash` WHERE `char_obj_id`=? LIMIT 1");
statement.setInt(1, player.getObjectId());
rset = statement.executeQuery();
rset.next();
cash = rset.getInt("cash");
}
catch(final Exception e)
{
_log.warning("Could not validate char points in CashShop: " + e);
e.printStackTrace();
}
finally
{
DatabaseUtils.closeDatabaseCSR(con, statement, rset);
}
player.sendPacket(new ExBR_GamePoint(player.getObjectId(), cash));
}
else if(Config.itemmallType == 2)
{
//Point system (Adena)
L2ItemInstance item = player.getInventory().getItemByItemId(Config.itemmallItem);
int count;
if(item != null)
{
count = (int) item.getCount();
}
else
{
count = 0;
}
player.sendPacket(new ExBR_GamePoint(player.getObjectId(), count));
}
}
public void showList(L2Player player)
{
player.sendPacket(list);
}
public void showItemInfo(L2Player player, int brId)
{
CashShopItem item = shop.get(brId);
if(item == null)
{
sendResult(player, BR_BUY_INVALID_ITEM);
return;
}
player.sendPacket(new ExBR_ProductInfo(item));
}
public void recentProductList(L2Player player)
{
}
}