package server.shops;
import client.MapleCharacter;
import client.MapleClient;
import client.inventory.Item;
import client.inventory.ItemLoader;
import constants.ItemConstants;
import database.DatabaseConnection;
import handling.channel.ChannelServer;
import handling.world.WorldFindService;
import java.lang.ref.WeakReference;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.log4j.Logger;
import server.maps.MapleMap;
import server.maps.MapleMapObject;
import server.maps.MapleMapObjectType;
import tools.FileoutputUtil;
import tools.Pair;
import tools.packet.PlayerShopPacket;
public abstract class AbstractPlayerStore extends MapleMapObject implements IMaplePlayerShop {
private static final Logger log = Logger.getLogger(AbstractPlayerStore.class);
protected boolean open = false;
protected boolean available = false;
protected String ownerName;
protected String des;
protected String pass;
protected int ownerId;
protected int owneraccount;
protected int itemId;
protected int channel;
protected int map;
protected AtomicInteger meso = new AtomicInteger(0);
protected WeakReference<MapleCharacter>[] chrs;
protected Map<String, VisitorInfo> visitorsList = new HashMap();
protected List<BoughtItem> bought = new LinkedList();
protected List<MaplePlayerShopItem> items = new LinkedList();
private final List<Pair<String, Byte>> messages = new LinkedList();
public AbstractPlayerStore(MapleCharacter owner, int itemId, String desc, String pass, int slots) {
setPosition(owner.getTruePosition());
this.ownerName = owner.getName();
this.ownerId = owner.getId();
this.owneraccount = owner.getAccountID();
this.itemId = itemId;
this.des = desc;
this.pass = pass;
this.map = owner.getMapId();
this.channel = owner.getClient().getChannel();
this.chrs = new WeakReference[slots];
for (int i = 0; i < this.chrs.length; i++) {
this.chrs[i] = new WeakReference(null);
}
this.visitorsList.clear();
}
@Override
public int getMaxSize() {
return this.chrs.length + 1;
}
@Override
public int getSize() {
return getFreeSlot() == -1 ? getMaxSize() : getFreeSlot();
}
@Override
public void broadcastToVisitors(byte[] packet) {
broadcastToVisitors(packet, true);
}
public void broadcastToVisitors(byte[] packet, boolean owner) {
for (WeakReference chr : this.chrs) {
if ((chr != null) && (chr.get() != null)) {
((MapleCharacter) chr.get()).getClient().getSession().write(packet);
}
}
if ((getShopType() != 1) && (owner) && (getMCOwner() != null)) {
getMCOwner().getClient().getSession().write(packet);
}
}
public void broadcastToVisitors(byte[] packet, int exception) {
for (WeakReference chr : this.chrs) {
if ((chr != null) && (chr.get() != null) && (getVisitorSlot((MapleCharacter) chr.get()) != exception)) {
((MapleCharacter) chr.get()).getClient().getSession().write(packet);
}
}
if ((getShopType() != 1) && (getMCOwner() != null) && (exception != this.ownerId)) {
getMCOwner().getClient().getSession().write(packet);
}
}
@Override
public int getMeso() {
return this.meso.get();
}
@Override
public void setMeso(int meso) {
this.meso.set(meso);
}
@Override
public void setOpen(boolean open) {
this.open = open;
}
@Override
public boolean isOpen() {
return this.open;
}
@Override
public boolean saveItems() {
if (getShopType() != 1) {
return false;
}
Connection con = DatabaseConnection.getConnection();
try {
PreparedStatement ps = con.prepareStatement("DELETE FROM hiredmerch WHERE characterid = ?");
ps.setInt(1, this.ownerId);
ps.executeUpdate();
ps.close();
ps = con.prepareStatement("INSERT INTO hiredmerch (characterid, accountid, Mesos, map, channel, time) VALUES (?, ?, ?, ?, ?, ?)", 1);
ps.setInt(1, this.ownerId);
ps.setInt(2, this.owneraccount);
ps.setInt(3, this.meso.get());
ps.setInt(4, this.map);
ps.setInt(5, this.channel);
ps.setLong(6, System.currentTimeMillis());
ps.executeUpdate();
ResultSet rs = ps.getGeneratedKeys();
if (!rs.next()) {
rs.close();
ps.close();
FileoutputUtil.log("[SaveItems] 保存雇佣商店信息出错 - 1");
throw new RuntimeException("保存雇佣商店信息出错.");
}
rs.close();
ps.close();
List itemsWithType = new ArrayList();
for (MaplePlayerShopItem pItems : this.items) {
if ((pItems.item == null) || (pItems.bundles <= 0) || ((pItems.item.getQuantity() <= 0) && (!ItemConstants.isRechargable(pItems.item.getItemId())))) {
continue;
}
Item item = pItems.item.copy();
item.setQuantity((short) (item.getQuantity() * pItems.bundles));
itemsWithType.add(new Pair(item, ItemConstants.getInventoryType(item.getItemId())));
}
ItemLoader.雇佣道具.saveItems(itemsWithType, this.ownerId);
return true;
} catch (SQLException se) {
FileoutputUtil.log("[SaveItems] 保存雇佣商店信息出错 - 2 " + se);
}
return false;
}
public MapleCharacter getVisitor(int num) {
return (MapleCharacter) this.chrs[num].get();
}
@Override
public void update() {
if (isAvailable()) {
if (getShopType() == 1) {
getMap().broadcastMessage(PlayerShopPacket.updateHiredMerchant((HiredMerchant) this));
} else if (getMCOwner() != null) {
getMap().broadcastMessage(PlayerShopPacket.sendPlayerShopBox(getMCOwner()));
}
}
}
@Override
public void addVisitor(MapleCharacter visitor) {
int i = getFreeSlot();
if (i > 0) {
if (getShopType() >= 3) {
broadcastToVisitors(PlayerShopPacket.getMiniGameNewVisitor(visitor, i, (MapleMiniGame) this));
} else {
broadcastToVisitors(PlayerShopPacket.shopVisitorAdd(visitor, i));
}
this.chrs[(i - 1)] = new WeakReference(visitor);
updateVisitorsList(visitor, false);
if (i == 6) {
update();
}
}
}
public boolean isInVisitorsList(String visitorName) {
return this.visitorsList.containsKey(visitorName);
}
public void updateVisitorsList(MapleCharacter visitor, boolean leave) {
if ((visitor != null) && (!isOwner(visitor)) && (!visitor.isGM())) {
if (this.visitorsList.containsKey(visitor.getName())) {
if (leave) {
((VisitorInfo) this.visitorsList.get(visitor.getName())).updateInTime();
} else {
((VisitorInfo) this.visitorsList.get(visitor.getName())).updateStartTime();
}
} else {
this.visitorsList.put(visitor.getName(), new VisitorInfo());
}
}
}
public void removeVisitorsList(String visitorName) {
if (this.visitorsList.containsKey(visitorName)) {
this.visitorsList.remove(visitorName);
}
}
@Override
public void removeVisitor(MapleCharacter visitor) {
byte slot = getVisitorSlot(visitor);
boolean shouldUpdate = getFreeSlot() == -1;
if (slot > 0) {
broadcastToVisitors(PlayerShopPacket.shopVisitorLeave(slot), slot);
this.chrs[(slot - 1)] = new WeakReference(null);
if (shouldUpdate) {
update();
}
updateVisitorsList(visitor, true);
}
}
@Override
public byte getVisitorSlot(MapleCharacter visitor) {
for (byte i = 0; i < this.chrs.length; i = (byte) (i + 1)) {
if ((this.chrs[i] != null) && (this.chrs[i].get() != null) && (((MapleCharacter) this.chrs[i].get()).getId() == visitor.getId())) {
return (byte) (i + 1);
}
}
if (visitor.getId() == this.ownerId) {
return 0;
}
return -1;
}
@Override
public void removeAllVisitors(int error, int type) {
for (int i = 0; i < this.chrs.length; i++) {
MapleCharacter visitor = getVisitor(i);
if (visitor != null) {
if (type != -1) {
visitor.getClient().getSession().write(PlayerShopPacket.shopErrorMessage(error, i + 1));
}
broadcastToVisitors(PlayerShopPacket.shopVisitorLeave(getVisitorSlot(visitor)), getVisitorSlot(visitor));
visitor.setPlayerShop(null);
this.chrs[i] = new WeakReference(null);
updateVisitorsList(visitor, true);
}
}
update();
}
@Override
public String getOwnerName() {
return this.ownerName;
}
@Override
public int getOwnerId() {
return this.ownerId;
}
@Override
public int getOwnerAccId() {
return this.owneraccount;
}
@Override
public String getDescription() {
if (this.des == null) {
return "";
}
return this.des;
}
@Override
public void setDescription(String desc) {
if (this.des.equalsIgnoreCase(desc)) {
return;
}
this.des = desc;
if ((isAvailable()) && (getShopType() == 1)) {
getMap().broadcastMessage(PlayerShopPacket.updateHiredMerchant((HiredMerchant) this, false));
}
}
@Override
public List<Pair<Byte, MapleCharacter>> getVisitors() {
List chrz = new LinkedList();
for (byte i = 0; i < this.chrs.length; i = (byte) (i + 1)) {
if ((this.chrs[i] != null) && (this.chrs[i].get() != null)) {
chrz.add(new Pair((byte) (i + 1), this.chrs[i].get()));
}
}
return chrz;
}
@Override
public List<MaplePlayerShopItem> getItems() {
return this.items;
}
@Override
public void addItem(MaplePlayerShopItem item) {
this.items.add(item);
}
@Override
public boolean removeItem(int item) {
return false;
}
@Override
public void removeFromSlot(int slot) {
this.items.remove(slot);
}
@Override
public byte getFreeSlot() {
for (byte i = 0; i < this.chrs.length; i = (byte) (i + 1)) {
if ((this.chrs[i] == null) || (this.chrs[i].get() == null)) {
return (byte) (i + 1);
}
}
return -1;
}
@Override
public int getItemId() {
return this.itemId;
}
@Override
public boolean isOwner(MapleCharacter chr) {
return (chr.getId() == this.ownerId) && (chr.getName().equals(this.ownerName));
}
@Override
public String getPassword() {
if (this.pass == null) {
return "";
}
return this.pass;
}
@Override
public void sendDestroyData(MapleClient client) {
}
@Override
public void sendSpawnData(MapleClient client) {
}
@Override
public MapleMapObjectType getType() {
return MapleMapObjectType.SHOP;
}
public MapleCharacter getMCOwnerWorld() {
int ourChannel = WorldFindService.getInstance().findChannel(this.ownerId);
if (ourChannel <= 0) {
return null;
}
return ChannelServer.getInstance(ourChannel).getPlayerStorage().getCharacterById(this.ownerId);
}
public MapleCharacter getMCOwnerChannel() {
return ChannelServer.getInstance(this.channel).getPlayerStorage().getCharacterById(this.ownerId);
}
public MapleCharacter getMCOwner() {
return getMap().getCharacterById(this.ownerId);
}
public MapleMap getMap() {
return ChannelServer.getInstance(this.channel).getMapFactory().getMap(this.map);
}
@Override
public int getGameType() {
if (getShopType() == 1) {
return 6;
}
if (getShopType() == 2) {
return 5;
}
if (getShopType() == 3) {
return 1;
}
if (getShopType() == 4) {
return 2;
}
return 0;
}
@Override
public boolean isAvailable() {
return this.available;
}
@Override
public void setAvailable(boolean b) {
this.available = b;
}
@Override
public List<BoughtItem> getBoughtItems() {
return this.bought;
}
@Override
public List<Pair<String, Byte>> getMessages() {
return this.messages;
}
@Override
public int getMapId() {
return this.map;
}
@Override
public int getChannel() {
return this.channel;
}
public static final class VisitorInfo {
public int inTime;
public long startTime;
public VisitorInfo() {
this.inTime = 0;
this.startTime = System.currentTimeMillis();
}
public void updateInTime() {
int time = (int) (System.currentTimeMillis() - this.startTime);
if (time > 0) {
this.inTime += time;
}
}
public int getInTime() {
return this.inTime;
}
public void updateStartTime() {
this.startTime = System.currentTimeMillis();
}
}
public static final class BoughtItem {
public int id;
public int quantity;
public int totalPrice;
public String buyer;
public BoughtItem(int id, int quantity, int totalPrice, String buyer) {
this.id = id;
this.quantity = quantity;
this.totalPrice = totalPrice;
this.buyer = buyer;
}
}
}