/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 ~ 2010 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 version 3
as published by the Free Software Foundation. You may not use, modify
or distribute this program under any other version of the
GNU Affero General Public License.
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 handling.channel.handler;
import client.MapleCharacter;
import client.MapleClient;
import client.MapleQuestStatus;
import client.SkillFactory;
import client.inventory.Equip;
import client.inventory.Item;
import client.inventory.MapleInventory;
import client.inventory.MapleInventoryType;
import client.inventory.MapleWeaponType;
import constants.GameConstants;
import constants.ServerConfig;
import handling.cashshop.CashShopServer;
import handling.cashshop.handler.CashShopOperation;
import handling.channel.ChannelServer;
import handling.farm.FarmServer;
import handling.farm.handler.FarmOperation;
import handling.login.LoginServer;
import handling.world.*;
import handling.world.exped.MapleExpedition;
import handling.world.guild.*;
import java.util.ArrayList;
import java.util.List;
import scripting.NPCScriptManager;
import server.*;
import server.maps.FieldLimitType;
import server.maps.MapleMap;
import server.quest.*;
import tools.FileoutputUtil;
import tools.Triple;
import tools.data.LittleEndianAccessor;
import tools.packet.CField;
import tools.packet.CWvsContext;
import tools.packet.CWvsContext.BuddylistPacket;
import tools.packet.CWvsContext.GuildPacket;
import tools.packet.CSPacket;
import tools.packet.FarmPacket;
import tools.packet.JobPacket;
import tools.packet.JobPacket.AvengerPacket;
import tools.packet.PacketHelper;
public class InterServerHandler {
public static void EnterCS(final MapleClient c, final MapleCharacter chr) {
if (chr.hasBlockedInventory() || chr.getMap() == null || chr.getEventInstance() != null || c.getChannelServer() == null) {
c.getSession().write(CField.serverBlocked(2));
CharacterTransfer farmtransfer = FarmServer.getPlayerStorage().getPendingCharacter(chr.getId());
if (farmtransfer != null) {
c.getSession().write(FarmPacket.farmMessage("You cannot move into Cash Shop while visiting your farm, yet."));
}
c.getSession().write(CWvsContext.enableActions());
return;
}
if (World.getPendingCharacterSize() >= 10) {
chr.dropMessage(1, "The server is busy at the moment. Please try again in a minute or less.");
c.getSession().write(CWvsContext.enableActions());
return;
}
ChannelServer ch = ChannelServer.getInstance(c.getChannel());
chr.changeRemoval();
if (chr.getMessenger() != null) {
MapleMessengerCharacter messengerplayer = new MapleMessengerCharacter(chr);
World.Messenger.leaveMessenger(chr.getMessenger().getId(), messengerplayer);
}
PlayerBuffStorage.addBuffsToStorage(chr.getId(), chr.getAllBuffs());
PlayerBuffStorage.addCooldownsToStorage(chr.getId(), chr.getCooldowns());
PlayerBuffStorage.addDiseaseToStorage(chr.getId(), chr.getAllDiseases());
World.ChannelChange_Data(new CharacterTransfer(chr), chr.getId(), -10);
ch.removePlayer(chr);
c.updateLoginState(3, c.getSessionIPAddress());
chr.saveToDB(false, false);
chr.getMap().removePlayer(chr);
c.getSession().write(CField.getChannelChange(c, Integer.parseInt(CashShopServer.getIP().split(":")[1])));
c.setPlayer(null);
c.setReceiving(false);
}
public static void EnterFarm(final MapleClient c, final MapleCharacter chr) {
if (chr.hasBlockedInventory() || chr.getMap() == null || chr.getEventInstance() != null || c.getChannelServer() == null) {
c.getSession().write(CField.serverBlocked(2));
c.getSession().write(CWvsContext.enableActions());
return;
}
if (World.getPendingCharacterSize() >= 10) {
chr.dropMessage(1, "The server is busy at the moment. Please try again in a minute or less.");
c.getSession().write(CWvsContext.enableActions());
return;
}
ChannelServer ch = ChannelServer.getInstance(c.getChannel());
chr.changeRemoval();
if (chr.getMessenger() != null) {
MapleMessengerCharacter messengerplayer = new MapleMessengerCharacter(chr);
World.Messenger.leaveMessenger(chr.getMessenger().getId(), messengerplayer);
}
PlayerBuffStorage.addBuffsToStorage(chr.getId(), chr.getAllBuffs());
PlayerBuffStorage.addCooldownsToStorage(chr.getId(), chr.getCooldowns());
PlayerBuffStorage.addDiseaseToStorage(chr.getId(), chr.getAllDiseases());
World.ChannelChange_Data(new CharacterTransfer(chr), chr.getId(), -30);
ch.removePlayer(chr);
c.updateLoginState(3, c.getSessionIPAddress());
chr.saveToDB(false, false);
chr.getMap().removePlayer(chr);
c.getSession().write(CField.getChannelChange(c, Integer.parseInt(FarmServer.getIP().split(":")[1])));
c.setPlayer(null);
c.setReceiving(false);
}
public static void Loggedin(final int playerid, final MapleClient c) {
try {
MapleCharacter player;
CharacterTransfer transfer = CashShopServer.getPlayerStorage().getPendingCharacter(playerid);
if (transfer != null) {
// c.getSession().write(CWvsContext.BuffPacket.cancelBuff());
CashShopOperation.EnterCS(transfer, c);
return;
}
CharacterTransfer farmtransfer = FarmServer.getPlayerStorage().getPendingCharacter(playerid);
if (farmtransfer != null) {
FarmOperation.EnterFarm(farmtransfer, c);
return;
}
for (ChannelServer cserv : ChannelServer.getAllInstances()) {
transfer = cserv.getPlayerStorage().getPendingCharacter(playerid);
if (transfer != null) {
c.setChannel(cserv.getChannel());
break;
}
}
if (transfer == null) { // Player isn't in storage, probably isn't CC
Triple<String, String, Integer> ip = LoginServer.getLoginAuth(playerid);
String s = c.getSessionIPAddress();
if (ip == null || !s.substring(s.indexOf('/') + 1, s.length()).equals(ip.left)) {
if (ip != null) {
LoginServer.putLoginAuth(playerid, ip.left, ip.mid, ip.right);
}
c.getSession().close();
return;
}
c.setTempIP(ip.mid);
c.setChannel(ip.right);
player = MapleCharacter.loadCharFromDB(playerid, c, true);
} else {
player = MapleCharacter.ReconstructChr(transfer, c, true);
}
final ChannelServer channelServer = c.getChannelServer();
c.setPlayer(player);
c.setAccID(player.getAccountID());
if (!c.CheckIPAddress()) { // Remote hack
c.getSession().close();
return;
}
final int state = c.getLoginState();
boolean allowLogin = false;
if (state == MapleClient.LOGIN_SERVER_TRANSITION || state == MapleClient.CHANGE_CHANNEL || state == MapleClient.LOGIN_NOTLOGGEDIN) {
allowLogin = !World.isCharacterListConnected(c.loadCharacterNames(c.getWorld()));
}
if (!allowLogin) {
c.setPlayer(null);
c.getSession().close();
return;
}
c.updateLoginState(MapleClient.LOGIN_LOGGEDIN, c.getSessionIPAddress());
channelServer.addPlayer(player);
player.giveCoolDowns(PlayerBuffStorage.getCooldownsFromStorage(player.getId()));
player.silentGiveBuffs(PlayerBuffStorage.getBuffsFromStorage(player.getId()));
player.giveSilentDebuff(PlayerBuffStorage.getDiseaseFromStorage(player.getId()));
c.getSession().write(CWvsContext.updateCrowns(new int[]{-1, -1, -1, -1, -1}));
c.getSession().write(CField.getCharInfo(player));
PlayersHandler.calcHyperSkillPointCount(c);
c.getSession().write(CSPacket.enableCSUse());
c.getSession().write(CWvsContext.updateSkills(c.getPlayer().getSkills(), false));//skill to 0 "fix"
player.getStolenSkills();
// c.getSession().write(JobPacket.addStolenSkill());
player.getMap().addPlayer(player);
try {
// Start of buddylist
final int buddyIds[] = player.getBuddylist().getBuddyIds();
World.Buddy.loggedOn(player.getName(), player.getId(), c.getChannel(), buddyIds);
if (player.getParty() != null) {
final MapleParty party = player.getParty();
World.Party.updateParty(party.getId(), PartyOperation.LOG_ONOFF, new MaplePartyCharacter(player));
if (party != null && party.getExpeditionId() > 0) {
final MapleExpedition me = World.Party.getExped(party.getExpeditionId());
if (me != null) {
c.getSession().write(CWvsContext.ExpeditionPacket.expeditionStatus(me, false, true));
}
}
}
final CharacterIdChannelPair[] onlineBuddies = World.Find.multiBuddyFind(player.getId(), buddyIds);
for (CharacterIdChannelPair onlineBuddy : onlineBuddies) {
player.getBuddylist().get(onlineBuddy.getCharacterId()).setChannel(onlineBuddy.getChannel());
}
c.getSession().write(BuddylistPacket.updateBuddylist(player.getBuddylist().getBuddies()));
// Start of Messenger
final MapleMessenger messenger = player.getMessenger();
if (messenger != null) {
World.Messenger.silentJoinMessenger(messenger.getId(), new MapleMessengerCharacter(c.getPlayer()));
World.Messenger.updateMessenger(messenger.getId(), c.getPlayer().getName(), c.getChannel());
}
// Start of Guild and alliance
if (player.getGuildId() > 0) {
World.Guild.setGuildMemberOnline(player.getMGC(), true, c.getChannel());
c.getSession().write(GuildPacket.showGuildInfo(player));
final MapleGuild gs = World.Guild.getGuild(player.getGuildId());
if (gs != null) {
final List<byte[]> packetList = World.Alliance.getAllianceInfo(gs.getAllianceId(), true);
if (packetList != null) {
for (byte[] pack : packetList) {
if (pack != null) {
c.getSession().write(pack);
}
}
}
} else { //guild not found, change guild id
player.setGuildId(0);
player.setGuildRank((byte) 5);
player.setAllianceRank((byte) 5);
player.saveGuildStatus();
}
}
if (player.getFamilyId() > 0) {
World.Family.setFamilyMemberOnline(player.getMFC(), true, c.getChannel());
}
//c.getSession().write(FamilyPacket.getFamilyData());
//c.getSession().write(FamilyPacket.getFamilyInfo(player));
} catch (Exception e) {
FileoutputUtil.outputFileError(FileoutputUtil.Login_Error, e);
}
player.getClient().getSession().write(CWvsContext.broadcastMsg(channelServer.getServerMessage()));
player.sendMacros();
player.showNote();
player.sendImp();
player.updatePartyMemberHP();
player.startFairySchedule(false);
player.baseSkills(); //fix people who've lost skills.
if (GameConstants.isZero(player.getJob())) {
c.getSession().write(CWvsContext.updateSkills(player.getSkills(), false));
}
c.getSession().write(CField.getKeymap(player.getKeyLayout()));
player.updatePetAuto();
player.expirationTask(true, transfer == null);
c.getSession().write(CWvsContext.updateMaplePoint(player.getCSPoints(2)));
if (player.getJob() == 132) { // DARKKNIGHT
player.checkBerserk();
}
if (GameConstants.isXenon(player.getJob())) {
player.startXenonSupply();
}
if (GameConstants.isDemonAvenger(player.getJob())) {
c.getSession().write(AvengerPacket.giveAvengerHpBuff(player.getStat().getHp()));
}
player.spawnClones();
player.spawnSavedPets();
if (player.getStat().equippedSummon > 0) {
SkillFactory.getSkill(player.getStat().equippedSummon + (GameConstants.getBeginnerJob(player.getJob()) * 1000)).getEffect(1).applyTo(player);
}
MapleQuestStatus stat = player.getQuestNoAdd(MapleQuest.getInstance(GameConstants.PENDANT_SLOT));
c.getSession().write(CWvsContext.pendantSlot(stat != null && stat.getCustomData() != null && Long.parseLong(stat.getCustomData()) > System.currentTimeMillis()));
stat = player.getQuestNoAdd(MapleQuest.getInstance(GameConstants.QUICK_SLOT));
c.getSession().write(CField.quickSlot(stat != null && stat.getCustomData() != null ? stat.getCustomData() : null));
// c.getSession().write(CWvsContext.getFamiliarInfo(player));
MapleInventory equipped = player.getInventory(MapleInventoryType.EQUIPPED);
MapleInventory equip = player.getInventory(MapleInventoryType.EQUIP);
List<Short> slots = new ArrayList<>();
for (Item item : equipped.newList()) {
slots.add(item.getPosition());
}
for (short slot : slots) {
if (GameConstants.isIllegalItem(equipped.getItem(slot).getItemId())) {
MapleInventoryManipulator.removeFromSlot(player.getClient(), MapleInventoryType.EQUIPPED, slot, (short) 1, false);
}
}
//c.getSession().write(CWvsContext.shopDiscount(ServerConstants.SHOP_DISCOUNT));
//List<Pair<Integer, String>> npcs = new ArrayList<>();
//npcs.add(new Pair<>(9070006, "Why...why has this happened to me? My knightly honor... My knightly pride..."));
//npcs.add(new Pair<>(9000021, "Are you enjoying the event?"));
//c.getSession().write(NPCPacket.setNpcScriptable(npcs));
//c.getSession().write(NPCPacket.setNPCScriptable());
player.updateReward();
// player.setDeathCount(99);
// c.getSession().write(CField.EffectPacket.updateDeathCount(99)); //for fun
player.getClient().getSession().write(CWvsContext.broadcastMsg(channelServer.getServerMessage()));
Thread.sleep(3100);
if (c.getPlayer().getLevel() < 11 && ServerConfig.RED_EVENT_10) {
NPCScriptManager.getInstance().start(c, 9000108, "LoginTot");
} else if (c.getPlayer().getLevel() > 10 && ServerConfig.RED_EVENT) {
NPCScriptManager.getInstance().start(c, 9000108, "LoginRed");
}
if (!GameConstants.isZero(player.getJob())) { //tell all players 2 login so u can remove this from ther
Equip a = (Equip) player.getInventory(MapleInventoryType.EQUIPPED).getItem((short) -11);
if (GameConstants.getWeaponType(a.getItemId()) == MapleWeaponType.LONG_SWORD) {
player.getInventory(MapleInventoryType.EQUIPPED).removeItem((short) -11);
}
Equip b = (Equip) player.getInventory(MapleInventoryType.EQUIPPED).getItem((short) -10);
if (GameConstants.getWeaponType(b.getItemId()) == MapleWeaponType.BIG_SWORD) {
player.getInventory(MapleInventoryType.EQUIPPED).removeItem((short) -10);
}
}
} catch (InterruptedException e) {
}
}
public static final void ChangeChannel(final LittleEndianAccessor slea, final MapleClient c, final MapleCharacter chr, final boolean room) {
if (chr == null || chr.hasBlockedInventory() || chr.getEventInstance() != null || chr.getMap() == null || chr.isInBlockedMap() || FieldLimitType.ChannelSwitch.check(chr.getMap().getFieldLimit())) {
c.getSession().write(CWvsContext.enableActions());
return;
}
if (World.getPendingCharacterSize() >= 10) {
chr.dropMessage(1, "The server is busy at the moment. Please try again in less than a minute.");
c.getSession().write(CWvsContext.enableActions());
return;
}
final int chc = slea.readByte() + 1;
int mapid = 0;
if (room) {
mapid = slea.readInt();
}
chr.updateTick(slea.readInt());
if (!World.isChannelAvailable(chc, chr.getWorld())) {
chr.dropMessage(1, "Request denied due to an unknown error.");
c.getSession().write(CWvsContext.enableActions());
return;
}
if (room && (mapid < 910000001 || mapid > 910000022)) {
chr.dropMessage(1, "Request denied due to an unknown error.");
c.getSession().write(CWvsContext.enableActions());
return;
}
if (room) {
if (chr.getMapId() == mapid) {
if (c.getChannel() == chc) {
chr.dropMessage(1, "You are already in " + chr.getMap().getMapName());
c.getSession().write(CWvsContext.enableActions());
} else { // diff channel
chr.changeChannel(chc);
}
} else { // diff map
if (c.getChannel() != chc) {
chr.changeChannel(chc);
}
final MapleMap warpz = ChannelServer.getInstance(c.getChannel()).getMapFactory().getMap(mapid);
if (warpz != null) {
chr.changeMap(warpz, warpz.getPortal("out00"));
} else {
chr.dropMessage(1, "Request denied due to an unknown error.");
c.getSession().write(CWvsContext.enableActions());
}
}
} else {
chr.changeChannel(chc);
}
}
}