package javastory.channel.server; import java.util.List; import com.google.common.collect.Lists; import javastory.channel.ChannelCharacter; import javastory.game.GameConstants; import javastory.game.Item; import javastory.game.ItemFlag; import javastory.tools.packets.ChannelPackets; public final class Trade { private Trade partner = null; private final List<Item> items = Lists.newLinkedList(); private List<Item> exchangeItems; private int meso = 0, exchangeMeso = 0; private boolean locked = false; private final ChannelCharacter chr; private final byte tradingslot; public Trade(final byte tradingslot, final ChannelCharacter chr) { this.tradingslot = tradingslot; this.chr = chr; } public void CompleteTrade() { for (final Item item : this.exchangeItems) { final byte flag = item.getFlag(); if (ItemFlag.KARMA_EQ.check(flag)) { item.setFlag((byte) (flag - ItemFlag.KARMA_EQ.getValue())); } else if (ItemFlag.KARMA_USE.check(flag)) { item.setFlag((byte) (flag - ItemFlag.KARMA_USE.getValue())); } InventoryManipulator.addFromDrop(this.chr.getClient(), item, false); } if (this.exchangeMeso > 0) { this.chr.gainMeso(this.exchangeMeso - GameConstants.getTaxAmount(this.exchangeMeso), false, true, false); } this.exchangeMeso = 0; this.exchangeItems.clear(); this.chr.getClient().write(ChannelPackets.TradeMessage(this.tradingslot, (byte) 0x07)); } public void cancel() { for (final Item item : this.items) { InventoryManipulator.addFromDrop(this.chr.getClient(), item, false); } if (this.meso > 0) { this.chr.gainMeso(this.meso, false, true, false); } this.meso = 0; this.items.clear(); this.chr.getClient().write(ChannelPackets.getTradeCancel(this.tradingslot)); } public boolean isLocked() { return this.locked; } public void setMeso(final int meso) { if (this.locked || this.partner == null || meso <= 0 || this.meso + meso <= 0) { return; } if (this.chr.getMeso() >= meso) { this.chr.gainMeso(-meso, false, true, false); this.meso += meso; this.chr.getClient().write(ChannelPackets.getTradeMesoSet((byte) 0, this.meso)); if (this.partner != null) { this.partner.getChr().getClient().write(ChannelPackets.getTradeMesoSet((byte) 1, this.meso)); } } } public void addItem(final Item item) { if (this.locked || this.partner == null) { return; } this.items.add(item); this.chr.getClient().write(ChannelPackets.getTradeItemAdd((byte) 0, item)); if (this.partner != null) { this.partner.getChr().getClient().write(ChannelPackets.getTradeItemAdd((byte) 1, item)); } } public void chat(final String message) { this.chr.getClient().write(ChannelPackets.getPlayerShopChat(this.chr, message, true)); if (this.partner != null) { this.partner.getChr().getClient().write(ChannelPackets.getPlayerShopChat(this.chr, message, false)); } } public Trade getPartner() { return this.partner; } public void setPartner(final Trade partner) { if (this.locked) { return; } this.partner = partner; } public ChannelCharacter getChr() { return this.chr; } private boolean check() { if (this.chr.getMeso() + this.exchangeMeso < 0) { return false; } byte eq = 0, use = 0, setup = 0, etc = 0; for (final Item item : this.exchangeItems) { switch (GameConstants.getInventoryType(item.getItemId())) { case EQUIP: eq++; break; case USE: use++; break; case SETUP: setup++; break; case ETC: etc++; break; case CASH: // Not allowed, probably hacking return false; } } if (this.chr.getEquipInventory().getNumFreeSlot() <= eq || this.chr.getUseInventory().getNumFreeSlot() <= use || this.chr.getSetupInventory().getNumFreeSlot() <= setup || this.chr.getEtcInventory().getNumFreeSlot() <= etc) { return false; } return true; } public static void completeTrade(final ChannelCharacter c) { final Trade local = c.getTrade(); final Trade partner = local.getPartner(); if (partner == null || local.locked) { return; } local.locked = true; // Locking the trade partner.getChr().getClient().write(ChannelPackets.getTradeConfirmation()); partner.exchangeItems = local.items; // Copy this to partner's trade since it's alreadt accepted partner.exchangeMeso = local.meso; // Copy this to partner's trade since it's alreadt accepted if (partner.isLocked()) { // Both locked if (!local.check() || !partner.check()) { // Check for full inventories // NOTE : IF accepted = other party but inventory is full, the item is lost. partner.cancel(); local.cancel(); c.getClient().write(ChannelPackets.serverNotice(5, "There is not enough inventory space to complete the trade.")); partner.getChr().getClient().write(ChannelPackets.serverNotice(5, "There is not enough inventory space to complete the trade.")); } else { local.CompleteTrade(); partner.CompleteTrade(); } partner.getChr().setTrade(null); c.setTrade(null); } } public static void cancelTrade(final Trade Localtrade) { Localtrade.cancel(); final Trade partner = Localtrade.getPartner(); if (partner != null) { partner.cancel(); partner.getChr().setTrade(null); } Localtrade.chr.setTrade(null); } public static void startTrade(final ChannelCharacter c) { if (c.getTrade() == null) { c.setTrade(new Trade((byte) 0, c)); c.getClient().write(ChannelPackets.getTradeStart(c.getClient(), c.getTrade(), (byte) 0)); } else { c.getClient().write(ChannelPackets.serverNotice(5, "You are already in a trade")); } } public static void inviteTrade(final ChannelCharacter c1, final ChannelCharacter c2) { if (c2.getTrade() == null) { c2.setTrade(new Trade((byte) 1, c2)); c2.getTrade().setPartner(c1.getTrade()); c1.getTrade().setPartner(c2.getTrade()); c2.getClient().write(ChannelPackets.getTradeInvite(c1)); } else { c1.getClient().write(ChannelPackets.serverNotice(5, "The other player is already trading with someone else.")); cancelTrade(c1.getTrade()); } } public static void visitTrade(final ChannelCharacter c1, final ChannelCharacter c2) { if (c1.getTrade() != null && c1.getTrade().getPartner() == c2.getTrade() && c2.getTrade() != null && c2.getTrade().getPartner() == c1.getTrade()) { // We don't need to check for map here as the user is found via MapleMap.getCharacterById_InMap() c2.getClient().write(ChannelPackets.getTradePartnerAdd(c1)); c1.getClient().write(ChannelPackets.getTradeStart(c1.getClient(), c1.getTrade(), (byte) 1)); } else { c1.getClient().write(ChannelPackets.serverNotice(5, "The other player has already closed the trade")); } } public static void declineTrade(final ChannelCharacter c) { final Trade trade = c.getTrade(); if (trade != null) { if (trade.getPartner() != null) { final ChannelCharacter other = trade.getPartner().getChr(); other.getTrade().cancel(); other.setTrade(null); other.getClient().write(ChannelPackets.serverNotice(5, c.getName() + " has declined your trade request")); } trade.cancel(); c.setTrade(null); } } }