/* 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.Equip; import client.IItem; import client.Item; import client.MapleCharacter; import client.MapleClient; import client.MapleInventoryType; import constants.ItemConstants; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Calendar; import java.util.LinkedList; import java.util.List; import net.AbstractMaplePacketHandler; import net.server.Channel; import server.DueyPackages; import server.MapleInventoryManipulator; import tools.DatabaseConnection; import tools.MaplePacketCreator; import tools.data.input.SeekableLittleEndianAccessor; public final class DueyHandler extends AbstractMaplePacketHandler { private enum Actions { TOSERVER_SEND_ITEM(0x02), TOSERVER_CLAIM_PACKAGE(0x04), TOSERVER_REMOVE_PACKAGE(0x05), TOSERVER_CLOSE_DUEY(0x07), TOCLIENT_OPEN_DUEY(0x08), TOCLIENT_NOT_ENOUGH_MESOS(0x0A), TOCLIENT_NAME_DOES_NOT_EXIST(0x0C), TOCLIENT_SAMEACC_ERROR(0x0D), TOCLIENT_SUCCESSFULLY_SENT(0x12), TOCLIENT_SUCCESSFUL_MSG(0x17), TOCLIENT_PACKAGE_MSG(0x1B); // Ending // byte; // 4 // if // recieved. // 3 // if // delete. final byte code; private Actions(int code) { this.code = (byte) code; } public byte getCode() { return code; } } private int getAccIdFromCNAME(String name, boolean accountid) { try { PreparedStatement ps; String text = "SELECT accountid FROM characters WHERE name = ?"; if (accountid) { text = "SELECT accountid FROM characters WHERE name = ?"; } ps = DatabaseConnection.getConnection().prepareStatement(text); ps.setString(1, name); ResultSet rs = ps.executeQuery(); if (!rs.next()) { rs.close(); ps.close(); return -1; } int id_ = accountid ? rs.getInt("accountid") : rs.getInt("id"); rs.close(); ps.close(); return id_; } catch (SQLException e) { } return -1; } public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) { byte operation = slea.readByte(); if (operation == Actions.TOSERVER_SEND_ITEM.getCode()) { final int fee = 5000; byte inventId = slea.readByte(); short itemPos = slea.readShort(); short amount = slea.readShort(); int mesos = slea.readInt(); String recipient = slea.readMapleAsciiString(); if (mesos < 0 || (long) mesos > Integer.MAX_VALUE || ((long) mesos + fee + getFee(mesos)) > Integer.MAX_VALUE) { return; } int finalcost = mesos + fee + getFee(mesos); boolean send = false; if (c.getPlayer().getMeso() >= finalcost) { int accid = getAccIdFromCNAME(recipient, true); if (accid != -1) { if (accid != c.getAccID()) { c.getPlayer().gainMeso(-finalcost, false); c.announce(MaplePacketCreator.sendDueyMSG(Actions.TOCLIENT_SUCCESSFULLY_SENT.getCode())); send = true; } else { c.announce(MaplePacketCreator.sendDueyMSG(Actions.TOCLIENT_SAMEACC_ERROR.getCode())); } } else { c.announce(MaplePacketCreator.sendDueyMSG(Actions.TOCLIENT_NAME_DOES_NOT_EXIST.getCode())); } } else { c.announce(MaplePacketCreator.sendDueyMSG(Actions.TOCLIENT_NOT_ENOUGH_MESOS.getCode())); } boolean recipientOn = false; MapleClient rClient = null; byte channel = c.getWorldServer().find(recipient); if (channel > -1) { recipientOn = true; Channel rcserv = c.getWorldServer().getChannel(channel); rClient = rcserv.getPlayerStorage().getCharacterByName(recipient).getClient(); } if (send) { if (inventId > 0) { MapleInventoryType inv = MapleInventoryType.getByType(inventId); IItem item = c.getPlayer().getInventory(inv).getItem((byte) itemPos); if (item != null && c.getPlayer().getItemQuantity(item.getItemId(), false) > amount) { if (ItemConstants.isRechargable(item.getItemId())) { MapleInventoryManipulator.removeFromSlot(c, inv, (byte) itemPos, item.getQuantity(), true); } else { MapleInventoryManipulator.removeFromSlot(c, inv, (byte) itemPos, amount, true, false); } addItemToDB(item, amount, mesos, c.getPlayer().getName(), getAccIdFromCNAME(recipient, false)); } else { return; } } else { addMesoToDB(mesos, c.getPlayer().getName(), getAccIdFromCNAME(recipient, false)); } if (recipientOn && rClient != null) { rClient.announce(MaplePacketCreator.sendDueyMSG(Actions.TOCLIENT_PACKAGE_MSG.getCode())); } c.getPlayer().gainMeso(-fee, false); } } else if (operation == Actions.TOSERVER_REMOVE_PACKAGE.getCode()) { int packageid = slea.readInt(); removeItemFromDB(packageid); c.announce(MaplePacketCreator.removeItemFromDuey(true, packageid)); } else if (operation == Actions.TOSERVER_CLAIM_PACKAGE.getCode()) { int packageid = slea.readInt(); List<DueyPackages> packages = new LinkedList<DueyPackages>(); DueyPackages dp = null; Connection con = DatabaseConnection.getConnection(); try { PreparedStatement ps = con.prepareStatement("SELECT * FROM dueypackages LEFT JOIN dueyitems USING (PackageId) WHERE PackageId = ?"); // PLEASE // WORK // D: ps.setInt(1, packageid); ResultSet rs = ps.executeQuery(); DueyPackages dueypack = null; if (rs.next()) { dueypack = getItemByPID(rs); dueypack.setSender(rs.getString("SenderName")); dueypack.setMesos(rs.getInt("Mesos")); dueypack.setSentTime(rs.getString("TimeStamp")); packages.add(dueypack); } rs.close(); ps.close(); dp = dueypack; } catch (SQLException e) { } if (dp.getItem() != null) { if (!MapleInventoryManipulator.checkSpace(c, dp.getItem().getItemId(), dp.getItem().getQuantity(), dp.getItem().getOwner())) { c.getPlayer().dropMessage(1, "Your inventory is full"); c.announce(MaplePacketCreator.enableActions()); return; } else { MapleInventoryManipulator.addFromDrop(c, dp.getItem(), false); } } int gainmesos = 0; long totalmesos = (long) dp.getMesos() + (long) c.getPlayer().getMeso(); if (totalmesos >= Integer.MAX_VALUE) { gainmesos = c.getPlayer().getMeso() - Integer.MAX_VALUE; } else if (totalmesos < 0 || dp.getMesos() < 0) { c.getPlayer().gainMeso(c.getPlayer().getMeso(), false); } else { c.getPlayer().gainMeso(gainmesos, false); } removeItemFromDB(packageid); c.announce(MaplePacketCreator.removeItemFromDuey(false, packageid)); } } private void addMesoToDB(int mesos, String sName, int recipientID) { addItemToDB(null, 1, mesos, sName, recipientID); } private void addItemToDB(IItem item, int quantity, int mesos, String sName, int recipientID) { Connection con = DatabaseConnection.getConnection(); try { PreparedStatement ps = con.prepareStatement("INSERT INTO dueypackages (RecieverId, SenderName, Mesos, TimeStamp, Checked, Type) VALUES (?, ?, ?, ?, ?, ?)"); ps.setInt(1, recipientID); ps.setString(2, sName); ps.setInt(3, mesos); ps.setString(4, getCurrentDate()); ps.setInt(5, 1); if (item == null) { ps.setInt(6, 3); ps.executeUpdate(); } else { ps.setInt(6, item.getType()); ps.executeUpdate(); ResultSet rs = ps.getGeneratedKeys(); rs.next(); PreparedStatement ps2; if (item.getType() == 1) { // equips ps2 = con.prepareStatement("INSERT INTO dueyitems (PackageId, itemid, quantity, upgradeslots, level, str, dex, `int`, luk, hp, mp, watk, matk, wdef, mdef, acc, avoid, hands, speed, jump, owner) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); Equip eq = (Equip) item; ps2.setInt(2, eq.getItemId()); ps2.setInt(3, 1); ps2.setInt(4, eq.getUpgradeSlots()); ps2.setInt(5, eq.getLevel()); ps2.setInt(6, eq.getStr()); ps2.setInt(7, eq.getDex()); ps2.setInt(8, eq.getInt()); ps2.setInt(9, eq.getLuk()); ps2.setInt(10, eq.getHp()); ps2.setInt(11, eq.getMp()); ps2.setInt(12, eq.getWatk()); ps2.setInt(13, eq.getMatk()); ps2.setInt(14, eq.getWdef()); ps2.setInt(15, eq.getMdef()); ps2.setInt(16, eq.getAcc()); ps2.setInt(17, eq.getAvoid()); ps2.setInt(18, eq.getHands()); ps2.setInt(19, eq.getSpeed()); ps2.setInt(20, eq.getJump()); ps2.setString(21, eq.getOwner()); } else { ps2 = con.prepareStatement("INSERT INTO dueyitems (PackageId, itemid, quantity, owner) VALUES (?, ?, ?, ?)"); ps2.setInt(2, item.getItemId()); ps2.setInt(3, quantity); ps2.setString(4, item.getOwner()); } ps2.setInt(1, rs.getInt(1)); ps2.executeUpdate(); ps2.close(); rs.close(); } ps.close(); } catch (SQLException e) { } } public static List<DueyPackages> loadItems(MapleCharacter chr) { List<DueyPackages> packages = new LinkedList<DueyPackages>(); Connection con = DatabaseConnection.getConnection(); try { PreparedStatement ps = con.prepareStatement("SELECT * FROM dueypackages LEFT JOIN dueyitems USING (PackageId) WHERE RecieverId = ?"); // PLEASE // WORK // D: ps.setInt(1, chr.getId()); ResultSet rs = ps.executeQuery(); while (rs.next()) { DueyPackages dueypack = getItemByPID(rs); dueypack.setSender(rs.getString("SenderName")); dueypack.setMesos(rs.getInt("Mesos")); dueypack.setSentTime(rs.getString("TimeStamp")); packages.add(dueypack); } rs.close(); ps.close(); return packages; } catch (SQLException e) { return null; } } private String getCurrentDate() { String date = ""; Calendar cal = Calendar.getInstance(); int day = cal.get(Calendar.DATE) - 1; // instant duey ? int month = cal.get(Calendar.MONTH) + 1; // its an array of months. int year = cal.get(Calendar.YEAR); date += day < 9 ? "0" : "" + day + "-"; date += month < 9 ? "0" : "" + month + "-"; date += year; return date; } private static int getFee(int meso) { int fee = 0; if (meso >= 10000000) { fee = meso / 25; } else if (meso >= 5000000) { fee = meso * 3 / 100; } else if (meso >= 1000000) { fee = meso / 50; } else if (meso >= 100000) { fee = meso / 100; } else if (meso >= 50000) { fee = meso / 200; } return fee; } private void removeItemFromDB(int packageid) { Connection con = DatabaseConnection.getConnection(); try { PreparedStatement ps = con.prepareStatement("DELETE FROM dueypackages WHERE PackageId = ?"); ps.setInt(1, packageid); ps.executeUpdate(); ps.close(); ps = con.prepareStatement("DELETE FROM dueyitems WHERE PackageId = ?"); ps.setInt(1, packageid); ps.executeUpdate(); ps.close(); } catch (SQLException e) { } } private static DueyPackages getItemByPID(ResultSet rs) { try { DueyPackages dueypack; if (rs.getInt("type") == 1) { Equip eq = new Equip(rs.getInt("itemid"), (byte) 0, -1); eq.setUpgradeSlots((byte) rs.getInt("upgradeslots")); eq.setLevel((byte) rs.getInt("level")); eq.setStr((short) rs.getInt("str")); eq.setDex((short) rs.getInt("dex")); eq.setInt((short) rs.getInt("int")); eq.setLuk((short) rs.getInt("luk")); eq.setHp((short) rs.getInt("hp")); eq.setMp((short) rs.getInt("mp")); eq.setWatk((short) rs.getInt("watk")); eq.setMatk((short) rs.getInt("matk")); eq.setWdef((short) rs.getInt("wdef")); eq.setMdef((short) rs.getInt("mdef")); eq.setAcc((short) rs.getInt("acc")); eq.setAvoid((short) rs.getInt("avoid")); eq.setHands((short) rs.getInt("hands")); eq.setSpeed((short) rs.getInt("speed")); eq.setJump((short) rs.getInt("jump")); eq.setOwner(rs.getString("owner")); dueypack = new DueyPackages(rs.getInt("PackageId"), eq); } else if (rs.getInt("type") == 2) { Item newItem = new Item(rs.getInt("itemid"), (byte) 0, (short) rs.getInt("quantity")); newItem.setOwner(rs.getString("owner")); dueypack = new DueyPackages(rs.getInt("PackageId"), newItem); } else { dueypack = new DueyPackages(rs.getInt("PackageId")); } return dueypack; } catch (SQLException se) { se.printStackTrace(); return null; } } }