/*
OrpheusMS: MapleStory Private Server based on OdinMS
Copyright (C) 2012 Aaron Weiss <aaron@deviant-core.net>
Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.server.handlers.channel;
import client.IEquip;
import client.IItem;
import client.MapleCharacter;
import client.MapleClient;
import client.MapleInventory;
import client.MapleInventoryType;
import client.MapleRing;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import net.AbstractMaplePacketHandler;
import server.CashShop;
import server.CashShop.CashItem;
import server.CashShop.CashItemFactory;
import server.MapleInventoryManipulator;
import server.MapleItemInformationProvider;
import tools.MaplePacketCreator;
import tools.Output;
import tools.data.input.SeekableLittleEndianAccessor;
public final class CashOperationHandler extends AbstractMaplePacketHandler {
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
MapleCharacter chr = c.getPlayer();
CashShop cs = chr.getCashShop();
if (!cs.isOpened()) {
c.announce(MaplePacketCreator.enableActions());
return;
}
final int action = slea.readByte();
if (action == 0x03 || action == 0x1E) {
slea.readByte();
final int useNX = slea.readInt();
final int snCS = slea.readInt();
CashItem cItem = CashItemFactory.getItem(snCS);
if (cItem == null || !cItem.isOnSale() || cs.getCash(useNX) < cItem.getPrice()) {
return;
}
if (action == 0x03) { // Item
IItem item = cItem.toItem();
cs.addToInventory(item);
c.announce(MaplePacketCreator.showBoughtCashItem(item, c.getAccID()));
} else { // Package
List<IItem> cashPackage = CashItemFactory.getPackage(cItem.getItemId());
for (IItem item : cashPackage) {
cs.addToInventory(item);
}
c.announce(MaplePacketCreator.showBoughtCashPackage(cashPackage, c.getAccID()));
}
cs.gainCash(useNX, -cItem.getPrice());
c.announce(MaplePacketCreator.showCash(chr));
} else if (action == 0x04) {// TODO check for gender
int birthday = slea.readInt();
CashItem cItem = CashItemFactory.getItem(slea.readInt());
Map<String, String> recipient = MapleCharacter.getCharacterFromDatabase(slea.readMapleAsciiString());
String message = slea.readMapleAsciiString();
if (!canBuy(cItem, cs.getCash(4)) || message.length() < 1 || message.length() > 73) {
return;
}
if (!checkBirthday(c, birthday)) {
c.announce(MaplePacketCreator.showCashShopMessage((byte) 0xC4));
return;
} else if (recipient == null) {
c.announce(MaplePacketCreator.showCashShopMessage((byte) 0xA9));
return;
} else if (recipient.get("accountid").equals(String.valueOf(c.getAccID()))) {
c.announce(MaplePacketCreator.showCashShopMessage((byte) 0xA8));
return;
}
cs.gift(Integer.parseInt(recipient.get("id")), chr.getName(), message, cItem.getSN());
c.announce(MaplePacketCreator.showGiftSucceed(recipient.get("name"), cItem));
cs.gainCash(4, -cItem.getPrice());
c.announce(MaplePacketCreator.showCash(chr));
try {
chr.sendNote(recipient.get("name"), chr.getName() + " has sent you a gift! Go check out the Cash Shop.", (byte) 0); // fame
// or
// not
} catch (SQLException ex) {
}
MapleCharacter receiver = c.getChannelServer().getPlayerStorage().getCharacterByName(recipient.get("name"));
if (receiver != null)
receiver.showNote();
} else if (action == 0x05) { // Modify wish list
cs.clearWishList();
for (byte i = 0; i < 10; i++) {
int sn = slea.readInt();
CashItem cItem = CashItemFactory.getItem(sn);
if (cItem != null && cItem.isOnSale() && sn != 0) {
cs.addToWishList(sn);
}
}
c.announce(MaplePacketCreator.showWishList(chr, true));
} else if (action == 0x06) { // Increase Inventory Slots
slea.skip(1);
int cash = slea.readInt();
byte mode = slea.readByte();
if (mode == 0) {
byte type = slea.readByte();
if (cs.getCash(cash) < 4000) {
return;
}
if (chr.gainSlots(type, 4, false)) {
c.announce(MaplePacketCreator.showBoughtInventorySlots(type, chr.getSlots(type)));
cs.gainCash(cash, -4000);
c.announce(MaplePacketCreator.showCash(chr));
}
} else {
CashItem cItem = CashItemFactory.getItem(slea.readInt());
int type = (cItem.getItemId() - 9110000) / 1000;
if (!canBuy(cItem, cs.getCash(cash))) {
return;
}
if (chr.gainSlots(type, 8, false)) {
c.announce(MaplePacketCreator.showBoughtInventorySlots(type, chr.getSlots(type)));
cs.gainCash(cash, -cItem.getPrice());
c.announce(MaplePacketCreator.showCash(chr));
}
}
} else if (action == 0x07) { // Increase Storage Slots
slea.skip(1);
int cash = slea.readInt();
byte mode = slea.readByte();
if (mode == 0) {
if (cs.getCash(cash) < 4000) {
return;
}
if (chr.getStorage().gainSlots(4)) {
c.announce(MaplePacketCreator.showBoughtStorageSlots(chr.getStorage().getSlots()));
cs.gainCash(cash, -4000);
c.announce(MaplePacketCreator.showCash(chr));
}
} else {
CashItem cItem = CashItemFactory.getItem(slea.readInt());
if (!canBuy(cItem, cs.getCash(cash))) {
return;
}
if (chr.getStorage().gainSlots(8)) {
c.announce(MaplePacketCreator.showBoughtStorageSlots(chr.getStorage().getSlots()));
cs.gainCash(cash, -cItem.getPrice());
c.announce(MaplePacketCreator.showCash(chr));
}
}
} else if (action == 0x08) { // Increase Character Slots
slea.skip(1);
int cash = slea.readInt();
CashItem cItem = CashItemFactory.getItem(slea.readInt());
if (!canBuy(cItem, cs.getCash(cash)))
return;
if (c.gainCharacterSlot()) {
c.announce(MaplePacketCreator.showBoughtCharacterSlot(c.getCharacterSlots()));
cs.gainCash(cash, -cItem.getPrice());
c.announce(MaplePacketCreator.showCash(chr));
}
} else if (action == 0x0D) { // Take from Cash Inventory
IItem item = cs.findByCashId(slea.readInt());
if (item == null) {
return;
}
if (chr.getInventory(MapleItemInformationProvider.getInstance().getInventoryType(item.getItemId())).addItem(item) != -1) {
cs.removeFromInventory(item);
c.announce(MaplePacketCreator.takeFromCashInventory(item));
}
} else if (action == 0x0E) { // Put into Cash Inventory
int cashId = slea.readInt();
slea.skip(4);
MapleInventory mi = chr.getInventory(MapleInventoryType.getByType(slea.readByte()));
IItem item = mi.findByCashId(cashId);
if (item == null) {
return;
}
cs.addToInventory(item);
mi.removeSlot(item.getPosition());
c.announce(MaplePacketCreator.putIntoCashInventory(item, c.getAccID()));
} else if (action == 0x1D) { // crush ring (action 28)
if (checkBirthday(c, slea.readInt())) {
int toCharge = slea.readInt();
int SN = slea.readInt();
String recipient = slea.readMapleAsciiString();
String text = slea.readMapleAsciiString();
CashItem ring = CashItemFactory.getItem(SN);
MapleCharacter partner = c.getChannelServer().getPlayerStorage().getCharacterByName(recipient);
if (partner == null) {
chr.getClient().announce(MaplePacketCreator.serverNotice(1, "The partner you specified cannot be found.\r\nPlease make sure your partner is online and in the same channel."));
} else {
if (partner.getGender() == chr.getGender()) {
chr.dropMessage("You and your partner are the same gender, please buy a friendship ring.");
return;
}
IEquip item = (IEquip) ring.toItem();
int ringid = MapleRing.createRing(ring.getItemId(), chr, partner);
item.setRingId(ringid);
cs.addToInventory(item);
c.announce(MaplePacketCreator.showBoughtCashItem(item, c.getAccID()));
cs.gift(partner.getId(), chr.getName(), text, item.getSN(), (ringid + 1));
cs.gainCash(toCharge, -ring.getPrice());
chr.addCrushRing(MapleRing.loadFromDb(ringid));
try {
chr.sendNote(partner.getName(), text, (byte) 1);
} catch (SQLException ex) {
}
partner.showNote();
}
} else {
chr.dropMessage("The birthday you entered was incorrect.");
}
c.announce(MaplePacketCreator.showCash(c.getPlayer()));
} else if (action == 0x20) { // everything is 1 meso...
int itemId = CashItemFactory.getItem(slea.readInt()).getItemId();
if (chr.getMeso() > 0) {
if (itemId == 4031180 || itemId == 4031192 || itemId == 4031191) {
chr.gainMeso(-1, false);
MapleInventoryManipulator.addById(c, itemId, (short) 1);
c.announce(MaplePacketCreator.showBoughtQuestItem(itemId));
}
}
c.announce(MaplePacketCreator.showCash(c.getPlayer()));
} else if (action == 0x23) { // Friendship :3
if (checkBirthday(c, slea.readInt())) {
int payment = slea.readByte();
slea.skip(3); // 0s
int snID = slea.readInt();
CashItem ring = CashItemFactory.getItem(snID);
String sentTo = slea.readMapleAsciiString();
int available = slea.readShort() - 1;
String text = slea.readAsciiString(available);
slea.readByte();
MapleCharacter partner = c.getChannelServer().getPlayerStorage().getCharacterByName(sentTo);
if (partner == null) {
chr.dropMessage("The partner you specified cannot be found.\r\nPlease make sure your partner is online and in the same channel.");
} else {
IEquip item = (IEquip) ring.toItem();
int ringid = MapleRing.createRing(ring.getItemId(), chr, partner);
item.setRingId(ringid);
cs.addToInventory(item);
c.announce(MaplePacketCreator.showBoughtCashItem(item, c.getAccID()));
cs.gift(partner.getId(), chr.getName(), text, item.getSN(), (ringid + 1));
cs.gainCash(payment, -ring.getPrice());
chr.addFriendshipRing(MapleRing.loadFromDb(ringid));
try {
chr.sendNote(partner.getName(), text, (byte) 1);
} catch (SQLException ex) {
}
partner.showNote();
}
} else {
chr.dropMessage("The birthday you entered was incorrect.");
}
c.announce(MaplePacketCreator.showCash(c.getPlayer()));
} else {
Output.print(slea.toString());
}
}
private boolean checkBirthday(MapleClient c, int idate) {
int year = idate / 10000;
int month = (idate - year * 10000) / 100;
int day = idate - year * 10000 - month * 100;
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(0);
cal.set(year, month - 1, day);
return c.checkBirthDate(cal);
}
public boolean canBuy(CashItem item, int cash) {
return item != null && item.isOnSale() && item.getPrice() <= cash;
}
}