403 lines
15 KiB
Java
403 lines
15 KiB
Java
package server;
|
|
|
|
import java.util.Collection;
|
|
|
|
import tools.packet.MTSCSPacket;
|
|
|
|
import java.util.List;
|
|
import java.sql.SQLException;
|
|
|
|
import constants.GameConstants;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.sql.ResultSet;
|
|
import java.sql.PreparedStatement;
|
|
import java.sql.Connection;
|
|
|
|
import tools.FilePrinter;
|
|
import client.inventory.MapleInventoryType;
|
|
import tools.Pair;
|
|
import client.inventory.ItemLoader;
|
|
import database.DBConPool;
|
|
|
|
import java.util.Iterator;
|
|
import java.util.Map.Entry;
|
|
|
|
import client.inventory.IItem;
|
|
|
|
import java.util.LinkedHashMap;
|
|
|
|
import tools.FileoutputUtil;
|
|
|
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
import java.util.Map;
|
|
|
|
public class MTSStorage {
|
|
private static final long serialVersionUID = 231541893513228L;
|
|
private long lastUpdate;
|
|
private final Map<Integer, MTSCart> idToCart;
|
|
private final AtomicInteger packageId;
|
|
private final Map<Integer, MTSItemInfo> buyNow;
|
|
private static MTSStorage instance;
|
|
private boolean end;
|
|
private final ReentrantReadWriteLock mutex;
|
|
private final ReentrantReadWriteLock cart_mutex;
|
|
|
|
public MTSStorage() {
|
|
this.lastUpdate = System.currentTimeMillis();
|
|
this.end = false;
|
|
System.out.println("[" + FileoutputUtil.CurrentReadable_Time() + "][信息]:初始化MTSStorage");
|
|
this.idToCart = (Map<Integer, MTSCart>) new LinkedHashMap();
|
|
this.buyNow = (Map<Integer, MTSItemInfo>) new LinkedHashMap();
|
|
this.packageId = new AtomicInteger(1);
|
|
this.mutex = new ReentrantReadWriteLock();
|
|
this.cart_mutex = new ReentrantReadWriteLock();
|
|
}
|
|
|
|
public static final MTSStorage getInstance() {
|
|
return MTSStorage.instance;
|
|
}
|
|
|
|
public static final void load() {
|
|
if (MTSStorage.instance == null) {
|
|
(MTSStorage.instance = new MTSStorage()).loadBuyNow();
|
|
}
|
|
}
|
|
|
|
public final boolean check(final int packageid) {
|
|
return this.getSingleItem(packageid) != null;
|
|
}
|
|
|
|
public final boolean checkCart(final int packageid, final int charID) {
|
|
final MTSItemInfo item = this.getSingleItem(packageid);
|
|
return item != null && item.getCharacterId() != charID;
|
|
}
|
|
|
|
public final MTSItemInfo getSingleItem(final int packageid) {
|
|
this.mutex.readLock().lock();
|
|
try {
|
|
return (MTSItemInfo) this.buyNow.get(Integer.valueOf(packageid));
|
|
} finally {
|
|
this.mutex.readLock().unlock();
|
|
}
|
|
}
|
|
|
|
public final void addToBuyNow(final MTSCart cart, final IItem item, final int price, final int cid, final String seller, final long expiration) {
|
|
this.mutex.writeLock().lock();
|
|
int id;
|
|
try {
|
|
id = this.packageId.incrementAndGet();
|
|
this.buyNow.put(Integer.valueOf(id), new MTSItemInfo(price, item, seller, id, cid, expiration));
|
|
} finally {
|
|
this.mutex.writeLock().unlock();
|
|
}
|
|
cart.addToNotYetSold(id);
|
|
}
|
|
|
|
public final boolean removeFromBuyNow(final int id, final int cidBought, final boolean check) {
|
|
IItem item = null;
|
|
this.mutex.writeLock().lock();
|
|
try {
|
|
if (this.buyNow.containsKey(Integer.valueOf(id))) {
|
|
final MTSItemInfo r = (MTSItemInfo) this.buyNow.get(Integer.valueOf(id));
|
|
if (!check || r.getCharacterId() == cidBought) {
|
|
item = r.getItem();
|
|
this.buyNow.remove(Integer.valueOf(id));
|
|
}
|
|
}
|
|
} finally {
|
|
this.mutex.writeLock().unlock();
|
|
}
|
|
if (item != null) {
|
|
this.cart_mutex.readLock().lock();
|
|
try {
|
|
for (final Entry<Integer, MTSCart> c : this.idToCart.entrySet()) {
|
|
((MTSCart) c.getValue()).removeFromCart(id);
|
|
((MTSCart) c.getValue()).removeFromNotYetSold(id);
|
|
if (((Integer) c.getKey()).intValue() == cidBought) {
|
|
((MTSCart) c.getValue()).addToInventory(item);
|
|
}
|
|
}
|
|
} finally {
|
|
this.cart_mutex.readLock().unlock();
|
|
}
|
|
}
|
|
return item != null;
|
|
}
|
|
|
|
private void loadBuyNow() {
|
|
int lastPackage = 0;
|
|
try (final Connection con = (Connection) DBConPool.getInstance().getDataSource().getConnection();
|
|
final PreparedStatement ps = con.prepareStatement("SELECT * FROM mts_items WHERE tab = 1");
|
|
final ResultSet rs = ps.executeQuery()) {
|
|
while (rs.next()) {
|
|
lastPackage = rs.getInt("id");
|
|
final int cId = rs.getInt("characterid");
|
|
if (!this.idToCart.containsKey(Integer.valueOf(cId))) {
|
|
this.idToCart.put(Integer.valueOf(cId), new MTSCart(cId));
|
|
}
|
|
final Map<Long, Pair<IItem, MapleInventoryType>> items = ItemLoader.MTS.loadItems(false, Integer.valueOf(lastPackage));
|
|
if (items != null && items.size() > 0) {
|
|
for (final Pair<IItem, MapleInventoryType> i : items.values()) {
|
|
this.buyNow.put(Integer.valueOf(lastPackage), new MTSItemInfo(rs.getInt("price"), (IItem) i.getLeft(), rs.getString("seller"), lastPackage, cId, rs.getLong("expiration")));
|
|
}
|
|
}
|
|
}
|
|
rs.close();
|
|
ps.close();
|
|
con.close();
|
|
} catch (Exception e) {
|
|
FilePrinter.printError("MTSStorage.txt", (Throwable) e, "loadBuyNow");
|
|
FileoutputUtil.outError("logs/资料库异常.txt", (Throwable) e);
|
|
}
|
|
this.packageId.set(lastPackage);
|
|
}
|
|
|
|
public final void saveBuyNow(final boolean isShutDown) {
|
|
if (this.end) {
|
|
return;
|
|
}
|
|
this.end = isShutDown;
|
|
if (isShutDown) {
|
|
System.out.println("Saving MTS...");
|
|
}
|
|
final Map<Integer, ArrayList<IItem>> expire = (Map<Integer, ArrayList<IItem>>) new HashMap();
|
|
final List<Integer> toRemove = (List<Integer>) new ArrayList();
|
|
final long now = System.currentTimeMillis();
|
|
final Map<Integer, ArrayList<Pair<IItem, MapleInventoryType>>> items = (Map<Integer, ArrayList<Pair<IItem, MapleInventoryType>>>) new HashMap();
|
|
this.mutex.writeLock().lock();
|
|
try (final Connection con = (Connection) DBConPool.getInstance().getDataSource().getConnection()) {
|
|
PreparedStatement ps = con.prepareStatement("DELETE FROM mts_items WHERE tab = 1");
|
|
ps.execute();
|
|
ps.close();
|
|
ps = con.prepareStatement("INSERT INTO mts_items VALUES (?, ?, ?, ?, ?, ?)");
|
|
for (final MTSItemInfo m : this.buyNow.values()) {
|
|
if (now > m.getEndingDate()) {
|
|
if (!expire.containsKey(Integer.valueOf(m.getCharacterId()))) {
|
|
expire.put(Integer.valueOf(m.getCharacterId()), new ArrayList());
|
|
}
|
|
(expire.get(Integer.valueOf(m.getCharacterId()))).add(m.getItem());
|
|
toRemove.add(Integer.valueOf(m.getId()));
|
|
items.put(Integer.valueOf(m.getId()), null);
|
|
} else {
|
|
ps.setInt(1, m.getId());
|
|
ps.setByte(2, (byte) 1);
|
|
ps.setInt(3, m.getPrice());
|
|
ps.setInt(4, m.getCharacterId());
|
|
ps.setString(5, m.getSeller());
|
|
ps.setLong(6, m.getEndingDate());
|
|
ps.executeUpdate();
|
|
if (!items.containsKey(Integer.valueOf(m.getId()))) {
|
|
items.put(Integer.valueOf(m.getId()), new ArrayList());
|
|
}
|
|
(items.get(Integer.valueOf(m.getId()))).add(new Pair(m.getItem(), GameConstants.getInventoryType(m.getItem().getItemId())));
|
|
}
|
|
}
|
|
final Iterator<Integer> iterator2 = toRemove.iterator();
|
|
while (iterator2.hasNext()) {
|
|
final int i = ((Integer) iterator2.next()).intValue();
|
|
this.buyNow.remove(Integer.valueOf(i));
|
|
}
|
|
ps.close();
|
|
con.close();
|
|
} catch (SQLException e) {
|
|
FilePrinter.printError("MTSStorage.txt", (Throwable) e, "saveBuyNow");
|
|
FileoutputUtil.outError("logs/资料库异常.txt", (Throwable) e);
|
|
} finally {
|
|
this.mutex.writeLock().unlock();
|
|
}
|
|
if (isShutDown) {
|
|
System.out.println("Saving MTS items...");
|
|
}
|
|
try {
|
|
for (final Entry<Integer, ArrayList<Pair<IItem, MapleInventoryType>>> ite : items.entrySet()) {
|
|
ItemLoader.MTS.saveItems((List<Pair<IItem, MapleInventoryType>>) (ArrayList<Pair<IItem, MapleInventoryType>>) ite.getValue(), (Integer) ite.getKey());
|
|
}
|
|
} catch (SQLException e) {
|
|
FilePrinter.printError("MTSStorage.txt", (Throwable) e, "saveBuyNow");
|
|
FileoutputUtil.outError("logs/资料库异常.txt", (Throwable) e);
|
|
}
|
|
if (isShutDown) {
|
|
System.out.println("Saving MTS carts...");
|
|
}
|
|
this.cart_mutex.writeLock().lock();
|
|
try {
|
|
for (final Entry<Integer, MTSCart> c : this.idToCart.entrySet()) {
|
|
final Iterator<Integer> iterator5 = toRemove.iterator();
|
|
while (iterator5.hasNext()) {
|
|
final int j = ((Integer) iterator5.next()).intValue();
|
|
((MTSCart) c.getValue()).removeFromCart(j);
|
|
((MTSCart) c.getValue()).removeFromNotYetSold(j);
|
|
}
|
|
if (expire.containsKey(c.getKey())) {
|
|
for (final IItem item : expire.get(c.getKey())) {
|
|
((MTSCart) c.getValue()).addToInventory(item);
|
|
}
|
|
}
|
|
((MTSCart) c.getValue()).save();
|
|
}
|
|
} catch (SQLException e) {
|
|
FilePrinter.printError("MTSStorage.txt", (Throwable) e, "saveBuyNow");
|
|
FileoutputUtil.outError("logs/资料库异常.txt", (Throwable) e);
|
|
} finally {
|
|
this.cart_mutex.writeLock().unlock();
|
|
}
|
|
this.lastUpdate = System.currentTimeMillis();
|
|
}
|
|
|
|
public final void checkExpirations() {
|
|
if (System.currentTimeMillis() - this.lastUpdate > 3600000L) {
|
|
this.saveBuyNow(false);
|
|
}
|
|
}
|
|
|
|
public final MTSCart getCart(final int characterId) {
|
|
this.cart_mutex.readLock().lock();
|
|
MTSCart ret;
|
|
try {
|
|
ret = (MTSCart) this.idToCart.get(Integer.valueOf(characterId));
|
|
} finally {
|
|
this.cart_mutex.readLock().unlock();
|
|
}
|
|
if (ret == null) {
|
|
this.cart_mutex.writeLock().lock();
|
|
try {
|
|
ret = new MTSCart(characterId);
|
|
this.idToCart.put(Integer.valueOf(characterId), ret);
|
|
} catch (SQLException e) {
|
|
FilePrinter.printError("MTSStorage.txt", (Throwable) e, "getCart");
|
|
} finally {
|
|
this.cart_mutex.writeLock().unlock();
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
public final byte[] getCurrentMTS(final MTSCart cart) {
|
|
this.mutex.readLock().lock();
|
|
try {
|
|
if (cart.getTab() == 1) {
|
|
return MTSCSPacket.sendMTS(this.getBuyNow(cart.getType(), cart.getPage()), cart.getTab(), cart.getType(), cart.getPage(), this.buyNow.size() / 16 + ((this.buyNow.size() % 16 > 0) ? 1 : 0));
|
|
}
|
|
if (cart.getTab() == 4) {
|
|
return MTSCSPacket.sendMTS(this.getCartItems(cart), cart.getTab(), cart.getType(), cart.getPage(), 0);
|
|
}
|
|
return MTSCSPacket.sendMTS((List<MTSItemInfo>) new ArrayList(), cart.getTab(), cart.getType(), cart.getPage(), 0);
|
|
} finally {
|
|
this.mutex.readLock().unlock();
|
|
}
|
|
}
|
|
|
|
public final byte[] getCurrentNotYetSold(final MTSCart cart) {
|
|
this.mutex.readLock().lock();
|
|
try {
|
|
final List<MTSItemInfo> nys = (List<MTSItemInfo>) new ArrayList();
|
|
final List<Integer> nyss = new ArrayList(cart.getNotYetSold());
|
|
final Iterator<Integer> iterator = nyss.iterator();
|
|
while (iterator.hasNext()) {
|
|
final int i = ((Integer) iterator.next()).intValue();
|
|
final MTSItemInfo r = (MTSItemInfo) this.buyNow.get(Integer.valueOf(i));
|
|
if (r == null) {
|
|
cart.removeFromNotYetSold(i);
|
|
} else {
|
|
nys.add(r);
|
|
}
|
|
}
|
|
return MTSCSPacket.getNotYetSoldInv(nys);
|
|
} finally {
|
|
this.mutex.readLock().unlock();
|
|
}
|
|
}
|
|
|
|
public final byte[] getCurrentTransfer(final MTSCart cart, final boolean changed) {
|
|
return MTSCSPacket.getTransferInventory(cart.getInventory(), changed);
|
|
}
|
|
|
|
private List<MTSItemInfo> getBuyNow(final int type, int page) {
|
|
final int size = this.buyNow.size() / 16 + ((this.buyNow.size() % 16 > 0) ? 1 : 0);
|
|
final List<MTSItemInfo> ret = (List<MTSItemInfo>) new ArrayList();
|
|
final List<MTSItemInfo> rett = new ArrayList(this.buyNow.values());
|
|
if (page > size) {
|
|
page = 0;
|
|
}
|
|
for (int i = page * 16; i < page * 16 + 16 && this.buyNow.size() >= i + 1; ++i) {
|
|
final MTSItemInfo r = (MTSItemInfo) rett.get(i);
|
|
if (r != null && (type == 0 || GameConstants.getInventoryType(r.getItem().getItemId()).getType() == type)) {
|
|
ret.add(r);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
private List<MTSItemInfo> getCartItems(final MTSCart cart) {
|
|
final List<MTSItemInfo> ret = (List<MTSItemInfo>) new ArrayList();
|
|
final List<Integer> cartt = new ArrayList(cart.getCart());
|
|
final Iterator<Integer> iterator = cartt.iterator();
|
|
while (iterator.hasNext()) {
|
|
final int i = ((Integer) iterator.next()).intValue();
|
|
final MTSItemInfo r = (MTSItemInfo) this.buyNow.get(Integer.valueOf(i));
|
|
if (r == null) {
|
|
cart.removeFromCart(i);
|
|
} else {
|
|
if (cart.getType() != 0 && GameConstants.getInventoryType(r.getItem().getItemId()).getType() != cart.getType()) {
|
|
continue;
|
|
}
|
|
ret.add(r);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
public static class MTSItemInfo {
|
|
private final int price;
|
|
private final IItem item;
|
|
private final String seller;
|
|
private final int id;
|
|
private final int cid;
|
|
private final long date;
|
|
|
|
public MTSItemInfo(final int price, final IItem item, final String seller, final int id, final int cid, final long date) {
|
|
this.item = item;
|
|
this.price = price;
|
|
this.seller = seller;
|
|
this.id = id;
|
|
this.cid = cid;
|
|
this.date = date;
|
|
}
|
|
|
|
public IItem getItem() {
|
|
return this.item;
|
|
}
|
|
|
|
public int getPrice() {
|
|
return this.price;
|
|
}
|
|
|
|
public int getRealPrice() {
|
|
return this.price + this.getTaxes();
|
|
}
|
|
|
|
public int getTaxes() {
|
|
return 100 + this.price * 10 / 100;
|
|
}
|
|
|
|
public int getId() {
|
|
return this.id;
|
|
}
|
|
|
|
public int getCharacterId() {
|
|
return this.cid;
|
|
}
|
|
|
|
public long getEndingDate() {
|
|
return this.date;
|
|
}
|
|
|
|
public String getSeller() {
|
|
return this.seller;
|
|
}
|
|
}
|
|
}
|