package javastory.channel.handling;
import javastory.channel.ChannelCharacter;
import javastory.channel.ChannelClient;
import javastory.channel.life.Npc;
import javastory.channel.server.AutobanManager;
import javastory.channel.server.InventoryManipulator;
import javastory.channel.server.Shop;
import javastory.channel.server.Storage;
import javastory.game.GameConstants;
import javastory.game.Inventory;
import javastory.game.InventoryType;
import javastory.game.Item;
import javastory.game.quest.QuestInfoProvider;
import javastory.game.quest.QuestInfoProvider.QuestInfo;
import javastory.io.PacketBuilder;
import javastory.io.PacketFormatException;
import javastory.io.PacketReader;
import javastory.scripting.NpcConversationManager;
import javastory.scripting.NpcScriptManager;
import javastory.server.handling.ServerPacketOpcode;
import javastory.tools.packets.ChannelPackets;
public class NpcHandler {
public static void handleNpcAnimation(final PacketReader reader, final ChannelClient c) throws PacketFormatException {
final PacketBuilder builder = new PacketBuilder();
final int length = (int) reader.remaining();
if (length == 6) { // NPC Talk
builder.writeAsShort(ServerPacketOpcode.NPC_ACTION.getValue());
builder.writeInt(reader.readInt());
builder.writeAsShort(reader.readShort());
c.write(builder.getPacket());
} else if (length > 6) { // NPC Move
final byte[] bytes = reader.readBytes(length - 9);
builder.writeAsShort(ServerPacketOpcode.NPC_ACTION.getValue());
builder.writeBytes(bytes);
c.write(builder.getPacket());
}
}
public static void handleNpcShop(final PacketReader reader, final ChannelClient c, final ChannelCharacter chr) throws PacketFormatException {
final byte bmode = reader.readByte();
switch (bmode) {
case 0: {
final Shop shop = chr.getShop();
if (shop == null) {
return;
}
reader.skip(2);
final int itemId = reader.readInt();
final short quantity = reader.readShort();
shop.buy(c, itemId, quantity);
break;
}
case 1: {
final Shop shop = chr.getShop();
if (shop == null) {
return;
}
final byte slot = (byte) reader.readShort();
final int itemId = reader.readInt();
final short quantity = reader.readShort();
shop.sell(c, chr.getInventoryForItem(itemId), slot, quantity);
break;
}
case 2: {
final Shop shop = chr.getShop();
if (shop == null) {
return;
}
final byte slot = (byte) reader.readShort();
shop.recharge(c, slot);
break;
}
default:
chr.setConversationState(0);
break;
}
}
public static void handleNpcTalk(final PacketReader reader, final ChannelClient c, final ChannelCharacter chr) throws PacketFormatException {
final Npc npc = chr.getMap().getNPCByOid(reader.readInt());
if (npc == null || chr.getConversationState() != 0) {
return;
}
if (npc.hasShop()) {
chr.setConversationState(1);
npc.sendShop(c);
} else {
NpcScriptManager.getInstance().start(c, npc.getId());
}
}
public static void handleQuestAction(final PacketReader reader, final ChannelClient c, final ChannelCharacter chr) throws PacketFormatException {
final byte action = reader.readByte();
final int questId = reader.readUnsignedShort();
final QuestInfo quest = QuestInfoProvider.getInfo(questId);
switch (action) {
case 0: {
// Restore lost item
reader.skip(4);
final int itemid = reader.readInt();
quest.restoreLostItems(chr, itemid);
break;
}
case 1: {
// Start Quest
final int npc = reader.readInt();
reader.skip(4);
quest.start(chr, npc);
break;
}
case 2: {
// Complete Quest
final int npcId = reader.readInt();
reader.skip(4);
if (reader.remaining() >= 4) {
final int selection = reader.readInt();
quest.complete(chr, npcId, selection);
} else {
quest.complete(chr, npcId);
}
// c.getSession().writeAsByte(MaplePacketCreator.completeQuest(c.getPlayer(),
// quest));
// c.getSession().writeAsByte(MaplePacketCreator.updateQuestInfo(c.getPlayer(),
// quest, npc, (byte)14));
// 6 = start quest
// 7 = unknown error
// 8 = equip is full
// 9 = not enough mesos
// 11 = due to the equipment currently being worn wtf o.o
// 12 = you may not posess more than one of this item
break;
}
case 3: {
// Forefit Quest
quest.forfeit(chr);
break;
}
case 4: {
// Scripted Start Quest
final int npc = reader.readInt();
reader.skip(4);
NpcScriptManager.getInstance().startQuest(c, npc, questId);
break;
}
case 5: {
// Scripted End Quest
final int npc = reader.readInt();
reader.skip(4);
NpcScriptManager.getInstance().endQuest(c, npc, questId, false);
c.write(ChannelPackets.showSpecialEffect(9)); // Quest completion
chr.getMap().broadcastMessage(chr, ChannelPackets.showSpecialEffect(chr.getId(), 9), false);
break;
}
}
}
public static void handleStorage(final PacketReader reader, final ChannelClient c, final ChannelCharacter chr) throws PacketFormatException {
final byte mode = reader.readByte();
final Storage storage = chr.getStorage();
switch (mode) {
case 4: {
// Take Out
handleStorageTakeOutItem(reader, storage, c, chr);
break;
}
case 5: {
// Store
handleStoragePutInItem(reader, storage, c, chr);
break;
}
case 7: {
handleStorageMesoTransaction(reader, storage, chr, c);
break;
}
case 8: {
storage.close();
chr.setConversationState(0);
break;
}
default:
System.out.println("Unhandled Storage mode : " + mode);
break;
}
}
private static void handleStorageMesoTransaction(final PacketReader reader, final Storage storage, final ChannelCharacter chr, final ChannelClient c)
throws PacketFormatException {
int meso = reader.readInt();
final int storageMesos = storage.getMeso();
final int playerMesos = chr.getMeso();
if (meso > 0 && storageMesos >= meso || meso < 0 && playerMesos >= -meso) {
if (meso < 0 && storageMesos - meso < 0) {
// storing with overflow
meso = -(Integer.MAX_VALUE - storageMesos);
if (-meso > playerMesos) {
return;
}
} else if (meso > 0 && playerMesos + meso < 0) {
// taking out with overflow
meso = Integer.MAX_VALUE - playerMesos;
if (meso > storageMesos) {
return;
}
}
storage.setMeso(storageMesos - meso);
chr.gainMeso(meso, false, true, false);
} else {
final StringBuilder builder = new StringBuilder();
builder.append("Trying to store or take out unavailable amount of mesos (");
builder.append(meso).append("/");
builder.append(storage.getMeso()).append("/");
builder.append(c.getPlayer().getMeso()).append(")");
AutobanManager.getInstance().addPoints(c, 1000, 0, builder.toString());
return;
}
storage.sendMeso(c);
}
private static void handleStoragePutInItem(final PacketReader reader, final Storage storage, final ChannelClient c, final ChannelCharacter chr)
throws PacketFormatException {
final byte slot = (byte) reader.readShort();
final int itemId = reader.readInt();
short quantity = reader.readShort();
if (quantity < 1) {
return;
}
if (storage.isFull()) {
c.write(ChannelPackets.getStorageFull());
return;
}
if (chr.getMeso() < 100) {
chr.sendNotice(1, "You don't have enough mesos to store the item");
} else {
final Inventory inventory = chr.getInventoryForItem(itemId);
final Item item = inventory.getItem(slot).copy();
if (GameConstants.isPet(item.getItemId())) {
c.write(ChannelPackets.enableActions());
return;
}
if (item.getItemId() == itemId && (item.getQuantity() >= quantity || GameConstants.isThrowingStar(itemId) || GameConstants.isBullet(itemId))) {
if (GameConstants.isThrowingStar(itemId) || GameConstants.isBullet(itemId)) {
quantity = item.getQuantity();
}
chr.gainMeso(-100, false, true, false);
InventoryManipulator.removeFromSlot(c, inventory, slot, quantity, false);
item.setQuantity(quantity);
storage.store(item);
} else {
AutobanManager.getInstance().addPoints(
c,
1000,
0,
"Trying to store non-matching itemid (" + itemId + "/" + item.getItemId() + ") or quantity not in posession (" + quantity + "/"
+ item.getQuantity() + ")");
return;
}
}
storage.sendStored(c, GameConstants.getInventoryType(itemId));
}
private static void handleStorageTakeOutItem(final PacketReader reader, final Storage storage, final ChannelClient c, final ChannelCharacter chr)
throws PacketFormatException {
final byte type = reader.readByte();
final byte slot = storage.getSlot(InventoryType.fromNumber(type), reader.readByte());
final Item item = storage.takeOut(slot);
if (item != null) {
if (InventoryManipulator.checkSpace(c, item.getItemId(), item.getQuantity(), item.getOwner())) {
InventoryManipulator.addFromDrop(c, item, false);
} else {
storage.store(item);
chr.sendNotice(1, "Your inventory is full");
}
storage.sendTakenOut(c, GameConstants.getInventoryType(item.getItemId()));
}
}
public static void handleNpcTalkMore(final PacketReader reader, final ChannelClient c) throws PacketFormatException {
final byte lastMsg = reader.readByte(); // 00 (last msg type I think)
final byte action = reader.readByte(); // 00 = end chat, 01 == follow
final NpcConversationManager cm = NpcScriptManager.getInstance().getConversationManager(c);
if (cm == null || c.getPlayer().getConversationState() == 0) {
return;
}
if (lastMsg == 3) {
if (action != 0) {
cm.setGetText(reader.readLengthPrefixedString());
if (cm.getType() == 0) {
NpcScriptManager.getInstance().startQuest(c, action, lastMsg, -1);
} else if (cm.getType() == 1) {
NpcScriptManager.getInstance().endQuest(c, action, lastMsg, -1);
} else {
NpcScriptManager.getInstance().action(c, action, lastMsg, -1);
}
} else {
cm.dispose();
}
} else {
int selection = -1;
if (reader.remaining() >= 4) {
selection = reader.readInt();
} else if (reader.remaining() > 0) {
selection = reader.readByte();
}
if (action != -1) {
if (cm.getType() == 0) {
NpcScriptManager.getInstance().startQuest(c, action, lastMsg, selection);
} else if (cm.getType() == 1) {
NpcScriptManager.getInstance().endQuest(c, action, lastMsg, selection);
} else {
NpcScriptManager.getInstance().action(c, action, lastMsg, selection);
}
} else {
cm.dispose();
}
}
}
}