MapleCharacter.java
上传用户:gwt600
上传日期:2021-06-03
资源大小:704k
文件大小:217k
源码类别:

游戏

开发平台:

Java

  1. /*
  2. This file is part of the OdinMS Maple Story Server
  3. Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
  4. Matthias Butz <matze@odinms.de>
  5. Jan Christian Meyer <vimes@odinms.de>
  6. This program is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU Affero General Public License version 3
  8. as published by the Free Software Foundation. You may not use, modify
  9. or distribute this program under any other version of the
  10. GNU Affero General Public License.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU Affero General Public License for more details.
  15. You should have received a copy of the GNU Affero General Public License
  16. along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17.  */
  18. package net.sf.odinms.client;
  19. import java.awt.Point;
  20. import java.lang.ref.WeakReference;
  21. import java.rmi.RemoteException;
  22. import java.sql.Connection;
  23. import java.sql.PreparedStatement;
  24. import java.sql.ResultSet;
  25. import java.sql.SQLException;
  26. import java.io.File;
  27. import java.text.NumberFormat;
  28. import java.text.DecimalFormat;
  29. import java.util.ArrayList;
  30. import java.sql.Statement;
  31. import java.sql.Timestamp;
  32. import java.util.ArrayList;
  33. import java.util.Arrays;
  34. import java.util.Calendar;
  35. import java.util.Collection;
  36. import java.util.Collections;
  37. import java.util.HashSet;
  38. import java.util.LinkedHashMap;
  39. import java.util.LinkedHashSet;
  40. import java.util.LinkedList;
  41. import java.util.List;
  42. import java.util.Map;
  43. import java.util.Set;
  44. import java.util.Map.Entry;
  45. import java.util.concurrent.ScheduledFuture;
  46. import java.util.concurrent.atomic.AtomicInteger;
  47. import java.text.NumberFormat;
  48. import java.text.DecimalFormat;
  49. import java.util.HashMap;
  50. import net.sf.odinms.client.anticheat.CheatTracker;
  51. import net.sf.odinms.database.DatabaseException;
  52. import net.sf.odinms.net.channel.handler.GuildHangoutHandler;
  53. import net.sf.odinms.net.MaplePacket;
  54. import net.sf.odinms.net.channel.ChannelServer;
  55. import net.sf.odinms.net.world.MapleMessengerCharacter;
  56. import net.sf.odinms.net.world.MaplePartyCharacter;
  57. import net.sf.odinms.net.world.PlayerBuffValueHolder;
  58. import net.sf.odinms.scripting.event.EventInstanceManager;
  59. import net.sf.odinms.client.messages.ServernoticeMapleClientMessageCallback;
  60. import net.sf.odinms.database.DatabaseConnection;
  61. import net.sf.odinms.net.world.PartyOperation;
  62. import net.sf.odinms.net.world.PlayerCoolDownValueHolder;
  63. import net.sf.odinms.net.world.guild.MapleGuild;
  64. import net.sf.odinms.net.world.guild.MapleGuildCharacter;
  65. import net.sf.odinms.net.world.remote.WorldChannelInterface;
  66. import net.sf.odinms.scripting.npc.NPCScriptManager;
  67. import net.sf.odinms.server.MonsterCarnival;
  68. import net.sf.odinms.server.MapleInventoryManipulator;
  69. import net.sf.odinms.server.life.MapleMonster;
  70. import net.sf.odinms.server.life.MobSkill;
  71. import net.sf.odinms.server.maps.MapleMap;
  72. import net.sf.odinms.server.maps.MapleMapFactory;
  73. import net.sf.odinms.server.maps.MapleMapObject;
  74. import net.sf.odinms.server.maps.MapleSummon;
  75. import net.sf.odinms.server.maps.SavedLocationType;
  76. import net.sf.odinms.server.maps.FakeCharacter;
  77. import net.sf.odinms.server.PlayerInteraction.MaplePlayerShop;
  78. import net.sf.odinms.provider.MapleData;
  79. import net.sf.odinms.provider.MapleDataProvider;
  80. import net.sf.odinms.provider.MapleDataProviderFactory;
  81. import net.sf.odinms.tools.MaplePacketCreator;
  82. import net.sf.odinms.tools.Pair;
  83. import net.sf.odinms.net.channel.handler.DoubleCardHandler;
  84. import net.sf.odinms.net.world.MapleMessenger;
  85. import net.sf.odinms.net.world.MapleParty;
  86. import net.sf.odinms.server.MapleInventoryManipulator;
  87. import net.sf.odinms.server.MapleItemInformationProvider;
  88. import net.sf.odinms.server.MaplePortal;
  89. import net.sf.odinms.server.MapleShop;
  90. import net.sf.odinms.server.MapleStatEffect;
  91. import net.sf.odinms.server.MapleStorage;
  92. import net.sf.odinms.server.MapleTrade;
  93. import net.sf.odinms.server.TimerManager;
  94. import net.sf.odinms.server.maps.AbstractAnimatedMapleMapObject;
  95. import net.sf.odinms.server.maps.MapleDoor;
  96. import net.sf.odinms.server.maps.MapleMapObjectType;
  97. import net.sf.odinms.server.maps.SavedLocationType;
  98. import net.sf.odinms.server.maps.SummonMovementType;
  99. import net.sf.odinms.server.quest.MapleCustomQuest;
  100. import net.sf.odinms.server.quest.MapleQuest;
  101. import net.sf.odinms.tools.MaplePacketCreator;
  102. import net.sf.odinms.tools.Pair;
  103. import net.sf.odinms.database.DatabaseConnection;
  104. import net.sf.odinms.net.PacketProcessor;
  105. import net.sf.odinms.net.world.MapleMessenger;
  106. import net.sf.odinms.net.world.MapleParty;
  107. import net.sf.odinms.net.world.PartyOperation;
  108. import net.sf.odinms.net.world.PlayerCoolDownValueHolder;
  109. import net.sf.odinms.server.MTSItemInfo;
  110. import net.sf.odinms.net.world.guild.MapleGuild;
  111. import net.sf.odinms.net.world.guild.MapleGuildCharacter;
  112. import net.sf.odinms.net.world.remote.WorldChannelInterface;
  113. import net.sf.odinms.server.PlayerInteraction.MaplePlayerShopItem;
  114. import net.sf.odinms.server.life.MapleMonster;
  115. import net.sf.odinms.server.life.MobSkill;
  116. import net.sf.odinms.server.maps.FakeCharacter;
  117. import net.sf.odinms.server.maps.MapleMap;
  118. import net.sf.odinms.server.maps.MapleMapFactory;
  119. import net.sf.odinms.server.maps.MapleMapObject;
  120. import net.sf.odinms.server.PlayerInteraction.HiredMerchant;
  121. import net.sf.odinms.server.PlayerInteraction.IPlayerInteractionManager;
  122. import net.sf.odinms.server.maps.MapleSummon;
  123. import org.slf4j.Logger;
  124. import org.slf4j.LoggerFactory;
  125. public class MapleCharacter extends AbstractAnimatedMapleMapObject implements InventoryContainer {
  126.     private static Logger log = LoggerFactory.getLogger(PacketProcessor.class);
  127.     public static final double MAX_VIEW_RANGE_SQ = 850 * 850;
  128.     private int world;
  129.     private int accountid;
  130.     private int rank;
  131.     private boolean expEnabled = true;
  132.     private int rankMove;
  133.     private boolean GMScroll;
  134.     private boolean blessed;
  135.     private String engager = null;
  136.     private int jobRank;
  137.     private int jobRankMove;
  138.     private String name;
  139.         private int Mesomode;
  140.     private int energybar;
  141.     private int bombpoints;
  142.     private int level,  reborns;
  143.     private int str,  dex,  luk,  int_;
  144.     private AtomicInteger exp = new AtomicInteger();
  145.     private int hp,  maxhp;
  146.         private boolean godmode;
  147.             private ChannelServer cserv;
  148.                 private int cp = 0;
  149.     private int totCP = 0;
  150.     private int cpqRanking = 0;
  151.     private int mp,  maxmp;
  152.     private int mpApUsed,  hpApUsed;
  153.     private int hair,  face;
  154.     private AtomicInteger meso = new AtomicInteger();
  155.     private int remainingAp,  remainingSp;
  156.     private int savedLocations[];
  157.     private int fame;
  158.     private long lastfametime;
  159.     private List<Integer> lastmonthfameids;
  160.     private transient int localmaxhp,  localmaxmp;
  161.     private transient int localstr,  localdex,  localluk,  localint;
  162.     private transient int magic,  watk;
  163.     private transient double speedMod,  jumpMod;
  164.     private transient int localmaxbasedamage;
  165.     private int id;
  166.     private MapleClient client;
  167.     private MapleMap map;
  168.     private int initialSpawnPoint;    // mapid is only used when calling getMapId() with map == null, it is not updated when running in channelserver mode
  169.     private int mapid;
  170.     private MapleShop shop = null;
  171.     private IPlayerInteractionManager interaction = null;
  172.     private MapleStorage storage = null;
  173.     private MaplePet[] pets = new MaplePet[3];
  174.     private ScheduledFuture<?> fullnessSchedule;
  175.     private ScheduledFuture<?> fullnessSchedule_1;
  176.     private ScheduledFuture<?> fullnessSchedule_2;
  177.     private SkillMacro[] skillMacros = new SkillMacro[5];
  178.     private static List<Pair<Byte, Integer>> inventorySlots = new ArrayList<Pair<Byte, Integer>>();
  179.     private MapleTrade trade = null;
  180.     private boolean challenged = false;
  181.     private MapleSkinColor skinColor = MapleSkinColor.NORMAL;
  182.     private MapleJob job = MapleJob.BEGINNER;
  183.     private int gender;
  184.     private int vip,  item;
  185.     private boolean gmchattype = true;
  186.     private int Gm;
  187.     public int dropmeso;
  188.     private int gmLevel;
  189.     private boolean hidden;
  190.     private boolean canDoor = true;
  191.     private int chair;
  192.     private int itemEffect;
  193.     private int APQScore;
  194.     private MapleParty party;
  195.     private EventInstanceManager eventInstance = null;
  196.     private MapleInventory[] inventory;
  197.     private Map<MapleQuest, MapleQuestStatus> quests;
  198.     private Set<MapleMonster> controlled = new LinkedHashSet<MapleMonster>();
  199.     private Set<MapleMapObject> visibleMapObjects = new LinkedHashSet<MapleMapObject>();
  200.     private Map<ISkill, SkillEntry> skills = new LinkedHashMap<ISkill, SkillEntry>();
  201.     private Map<MapleBuffStat, MapleBuffStatValueHolder> effects = new LinkedHashMap<MapleBuffStat, MapleBuffStatValueHolder>();
  202.     private HashMap<Integer, MapleKeyBinding> keymap = new LinkedHashMap<Integer, MapleKeyBinding>();
  203.     private List<MapleDoor> doors = new ArrayList<MapleDoor>();
  204.     private Map<Integer, MapleSummon> summons = new LinkedHashMap<Integer, MapleSummon>();
  205.     private BuddyList buddylist;
  206.     private Map<Integer, MapleCoolDownValueHolder> coolDowns = new LinkedHashMap<Integer, MapleCoolDownValueHolder>();    // anticheat related information
  207.     private CheatTracker anticheat;
  208.     private ScheduledFuture<?> dragonBloodSchedule;
  209.     private ScheduledFuture<?> mapTimeLimitTask = null;    //guild related information
  210.     private int guildid;
  211.     private int guildrank,  allianceRank;
  212.     private MapleGuildCharacter mgc = null;    // cash shop related information
  213.     private int paypalnx = 0,  maplepoints = 0,  cardnx = 0;
  214.     private boolean incs,  inmts;
  215.     private int currentPage = 0,  currentType = 0,  currentTab = 1;
  216.     private MapleMessenger messenger = null;
  217.     int messengerposition = 4;
  218.     private ScheduledFuture<?> hpDecreaseTask;
  219.     private List<MapleDisease> diseases = new ArrayList<MapleDisease>();
  220.     public boolean spawned;
  221.     private ScheduledFuture<?> beholderHealingSchedule;
  222.     private ScheduledFuture<?> beholderBuffSchedule;
  223.     private ScheduledFuture<?> BerserkSchedule;
  224.     private boolean Berserk = false;
  225.     public SummonMovementType getMovementType;
  226.     private MonsterCarnival monsterCarnival;
  227.     private String chalktext; // Chalkboard
  228.     // ------- CPQ ---------
  229.     private int CP;
  230.     private int totalCP;
  231.     private int team;
  232.     // ------ Marriage -------
  233.     private boolean married = false;
  234.     private boolean maxStatScroll = false;
  235.     private int  donatorpoints;
  236.     private int partnerid;
  237.     private int marriageQuestLevel;
  238.     // ------ Spam Block -------
  239.     private boolean canSmega = true;
  240.     private boolean smegaEnabled = true;
  241.     private boolean canTalk = true;
  242.     // ------- Misc. ------------
  243.     private int zakumLvl; //zero means they havent started yet
  244.     private List<FakeCharacter> fakes = new ArrayList<FakeCharacter>();
  245.     private boolean isfake = false;
  246.     private int clan;
  247.     private int pvpkills;
  248.     private int pvpdeaths;
  249.     private int donatePoints = 0;
  250.     private MapleMount maplemount;
  251.     private int gmtext = 0;
  252.     // -------- Calc. Dmg ---------
  253.     private double sword;
  254.     private double blunt;
  255.     private double axe;
  256.     private double spear;
  257.     private double polearm;
  258.     private double claw;
  259.     private double dagger;
  260.     private MaplePlayerShop playerShop = null;
  261.     public int juankuan;
  262.     private double staffwand = 0.1;
  263.     private double crossbow;
  264.     private double bow;
  265.     private int skill = 0;
  266.     private ISkill skil;
  267.     private int maxDis;
  268.     public int mpoints = 0;
  269.     public int paypalNX = 0;
  270.     private int slots = 0;
  271.     private long playerkill;
  272.     private transient int wdef,  mdef;
  273.     //private List<Integer> jobs = new ArrayList<Integer>();
  274.     private long afkTime;
  275.     private long lastLogin = 0;
  276.     private int ringRequest;
  277.     private boolean hasMerchant;
  278.     private int gm;
  279.     public MapleCharacter() {
  280.         setStance(0);
  281.         inventory = new MapleInventory[MapleInventoryType.values().length];
  282.         for (MapleInventoryType type : MapleInventoryType.values()) {
  283.             inventory[type.ordinal()] = new MapleInventory(type, (byte) 100);
  284.         }
  285.         savedLocations = new int[SavedLocationType.values().length];
  286.         for (int i = 0; i < SavedLocationType.values().length; i++) {
  287.             savedLocations[i] = -1;
  288.         }
  289.         quests = new LinkedHashMap<MapleQuest, MapleQuestStatus>();
  290.         anticheat = new CheatTracker(this);
  291.         afkTime = System.currentTimeMillis();
  292.         setPosition(new Point(0, 0));
  293.     }
  294.     public MapleCharacter getThis() {
  295.         return this;
  296.     }
  297.     public static MapleCharacter loadCharFromDB(int charid, MapleClient client, boolean channelserver) throws SQLException {
  298.         MapleCharacter ret = new MapleCharacter();
  299.         ret.client = client;
  300.         ret.id = charid;
  301.         Connection con = DatabaseConnection.getConnection();
  302.         PreparedStatement ps = con.prepareStatement("SELECT * FROM characters WHERE id = ?");
  303.         ps.setInt(1, charid);
  304.         ResultSet rs = ps.executeQuery();
  305.         if (!rs.next()) {
  306.             throw new RuntimeException("Loading the Char Failed (char not found)");
  307.         }
  308.         ret.name = rs.getString("name");
  309.         ret.level = rs.getInt("level");
  310.         ret.pvpdeaths = rs.getInt("pvpdeaths");
  311.         ret.pvpkills = rs.getInt("pvpkills");
  312.         ret.reborns = rs.getInt("reborns");
  313.         ret.fame = rs.getInt("fame");
  314.         ret.vip = rs.getInt("vip");
  315.         ret.str = rs.getInt("str");
  316.         ret.dex = rs.getInt("dex");
  317.         ret.int_ = rs.getInt("int");
  318.         ret.luk = rs.getInt("luk");
  319.         ret.exp.set(rs.getInt("exp"));
  320.         if (ret.exp.get() < 0) {
  321.             ret.exp.set(0);
  322.         }
  323.         ret.hp = rs.getInt("hp");
  324.         if (ret.hp < 50) {
  325.             ret.hp = 50;
  326.         }
  327.         ret.maxhp = rs.getInt("maxhp");
  328.         ret.mp = rs.getInt("mp");
  329.         if (ret.mp < 50) {
  330.             ret.mp = 50;
  331.         }
  332.         ret.maxmp = rs.getInt("maxmp");
  333.         ret.hpApUsed = rs.getInt("hpApUsed");
  334.         ret.mpApUsed = rs.getInt("mpApUsed");
  335.         ret.hasMerchant = rs.getInt("HasMerchant") == 1;
  336.         ret.remainingSp = rs.getInt("sp");
  337.         ret.remainingAp = rs.getInt("ap");
  338.         ret.meso.set(rs.getInt("meso"));
  339.         ret.gmLevel = rs.getInt("gm");
  340.         ret.vip = rs.getInt("vip");
  341.         ret.clan = rs.getInt("clan");
  342.         int mountexp = rs.getInt("mountexp");
  343.         int mountlevel = rs.getInt("mountlevel");
  344.         int mounttiredness = rs.getInt("mounttiredness");
  345.         ret.married = rs.getInt("married") == 0 ? false : true;
  346.         ret.partnerid = rs.getInt("partnerid");
  347.         ret.marriageQuestLevel = rs.getInt("marriagequest");
  348.         ret.zakumLvl = rs.getInt("zakumLvl");
  349.         ret.skinColor = MapleSkinColor.getById(rs.getInt("skincolor"));
  350.         ret.gender = rs.getInt("gender");
  351.         ret.job = MapleJob.getById(rs.getInt("job"));
  352.         ret.hair = rs.getInt("hair");
  353.         ret.face = rs.getInt("face");
  354.         ret.accountid = rs.getInt("accountid");
  355.         ret.mapid = rs.getInt("map");
  356.         ret.initialSpawnPoint = rs.getInt("spawnpoint");
  357.         ret.world = rs.getInt("world");
  358.         ret.rank = rs.getInt("rank");
  359.         ret.rankMove = rs.getInt("rankMove");
  360.         ret.jobRank = rs.getInt("jobRank");
  361.         ret.jobRankMove = rs.getInt("jobRankMove");
  362.         ret.guildid = rs.getInt("guildid");
  363.         ret.guildrank = rs.getInt("guildrank");
  364.         ret.allianceRank = rs.getInt("allianceRank");
  365.         if (ret.guildid > 0) {
  366.             ret.mgc = new MapleGuildCharacter(ret);
  367.         }
  368.         int buddyCapacity = rs.getInt("buddyCapacity");
  369.         ret.buddylist = new BuddyList(buddyCapacity);
  370.         ret.gmtext = rs.getInt("gmtext");
  371.         if (channelserver) {
  372.             MapleMapFactory mapFactory = ChannelServer.getInstance(client.getChannel()).getMapFactory();
  373.             ret.map = mapFactory.getMap(ret.mapid);
  374.             if (ret.map == null) { //char is on a map that doesn't exist warp it to henesys
  375.                 ret.map = mapFactory.getMap(100000000);
  376.             }
  377.             MaplePortal portal = ret.map.getPortal(ret.initialSpawnPoint);
  378.             if (portal == null) {
  379.                 portal = ret.map.getPortal(0); // char is on a spawnpoint that doesn't exist - select the first spawnpoint instead
  380.                 ret.initialSpawnPoint = 0;
  381.             }
  382.             ret.setPosition(portal.getPosition());
  383.             int partyid = rs.getInt("party");
  384.             if (partyid >= 0) {
  385.                 try {
  386.                     MapleParty party = client.getChannelServer().getWorldInterface().getParty(partyid);
  387.                     if (party != null && party.getMemberById(ret.id) != null) {
  388.                         ret.party = party;
  389.                     }
  390.                 } catch (RemoteException e) {
  391.                     client.getChannelServer().reconnectWorld();
  392.                 }
  393.             }
  394.             int messengerid = rs.getInt("messengerid");
  395.             int position = rs.getInt("messengerposition");
  396.             if (messengerid > 0 && position < 4 && position > -1) {
  397.                 try {
  398.                     WorldChannelInterface wci = ChannelServer.getInstance(client.getChannel()).getWorldInterface();
  399.                     MapleMessenger messenger = wci.getMessenger(messengerid);
  400.                     if (messenger != null) {
  401.                         ret.messenger = messenger;
  402.                         ret.messengerposition = position;
  403.                     }
  404.                 } catch (RemoteException e) {
  405.                     client.getChannelServer().reconnectWorld();
  406.                 }
  407.             }
  408.         }
  409.         rs.close();
  410.         ps.close();
  411.         ps = con.prepareStatement("SELECT * FROM accounts WHERE id = ?");
  412.         ps.setInt(1, ret.accountid);
  413.         rs = ps.executeQuery();
  414.         if (rs.next()) {
  415.             ret.getClient().setAccountName(rs.getString("name"));
  416.             ret.getClient().setAccountPass(rs.getString("password"));
  417.             ret.getClient().setGuest(rs.getInt("guest") > 0);
  418.             ret.donatePoints = rs.getInt("donorPoints");
  419.             ret.lastLogin = rs.getLong("LastLoginInMilliseconds");
  420.             if (!ret.isGM()) {
  421.                 if (ret.donatePoints == 1) { // 3 donor levels o____o
  422.                     ret.gmLevel = 1;
  423.                 } else if (ret.donatePoints > 1) {
  424.                     ret.gmLevel = 2;
  425.                 }
  426.             }
  427.             ret.paypalnx = rs.getInt("paypalNX");
  428.             ret.maplepoints = rs.getInt("mPoints");
  429.             ret.cardnx = rs.getInt("cardNX");
  430.             ret.donatorpoints = rs.getInt("donatorpoints");
  431.         }
  432.         rs.close();
  433.         ps.close();
  434.         String sql = "SELECT * FROM inventoryitems " + "LEFT JOIN inventoryequipment USING (inventoryitemid) " + "WHERE characterid = ?";
  435.         if (!channelserver) {
  436.             sql += " AND inventorytype = " + MapleInventoryType.EQUIPPED.getType();
  437.         }
  438.         ps = con.prepareStatement(sql);
  439.         ps.setInt(1, charid);
  440.         rs = ps.executeQuery();
  441.         while (rs.next()) {
  442.             MapleInventoryType type = MapleInventoryType.getByType((byte) rs.getInt("inventorytype"));
  443.             if (type.equals(MapleInventoryType.EQUIP) || type.equals(MapleInventoryType.EQUIPPED)) {
  444.                 int itemid = rs.getInt("itemid");
  445.                 Equip equip = new Equip(itemid, (byte) rs.getInt("position"), rs.getInt("ringid"));
  446.                 equip.setOwner(rs.getString("owner"));
  447.                 equip.setQuantity((short) rs.getInt("quantity"));
  448.                 equip.setAcc((short) rs.getInt("acc"));
  449.                 equip.setAvoid((short) rs.getInt("avoid"));
  450.                 equip.setDex((short) rs.getInt("dex"));
  451.                 equip.setHands((short) rs.getInt("hands"));
  452.                 equip.setHp((short) rs.getInt("hp"));
  453.                 equip.setInt((short) rs.getInt("int"));
  454.                 equip.setJump((short) rs.getInt("jump"));
  455.                 equip.setLuk((short) rs.getInt("luk"));
  456.                 equip.setMatk((short) rs.getInt("matk"));
  457.                 equip.setMdef((short) rs.getInt("mdef"));
  458.                 equip.setMp((short) rs.getInt("mp"));
  459.                 equip.setSpeed((short) rs.getInt("speed"));
  460.                 equip.setStr((short) rs.getInt("str"));
  461.                 equip.setWatk((short) rs.getInt("watk"));
  462.                 equip.setWdef((short) rs.getInt("wdef"));
  463.                 equip.setUpgradeSlots((byte) rs.getInt("upgradeslots"));
  464.                 equip.setLocked((byte) rs.getInt("locked"));
  465.                 equip.setLevel((byte) rs.getInt("level"));
  466.                 ret.getInventory(type).addFromDB(equip);
  467.             } else {
  468.                 Item item = new Item(rs.getInt("itemid"), (byte) rs.getInt("position"), (short) rs.getInt("quantity"), rs.getInt("petid"));
  469.                 item.setOwner(rs.getString("owner"));
  470.                 ret.getInventory(type).addFromDB(item);
  471.             }
  472.         }
  473.         rs.close();
  474.         ps.close();
  475.         if (channelserver) {
  476.             ps = con.prepareStatement("SELECT * FROM queststatus WHERE characterid = ?");
  477.             ps.setInt(1, charid);
  478.             rs = ps.executeQuery();
  479.             PreparedStatement pse = con.prepareStatement("SELECT * FROM queststatusmobs WHERE queststatusid = ?");
  480.             while (rs.next()) {
  481.                 MapleQuest q = MapleQuest.getInstance(rs.getInt("quest"));
  482.                 MapleQuestStatus status = new MapleQuestStatus(q, MapleQuestStatus.Status.getById(rs.getInt("status")));
  483.                 long cTime = rs.getLong("time");
  484.                 if (cTime > -1) {
  485.                     status.setCompletionTime(cTime * 1000);
  486.                 }
  487.                 status.setForfeited(rs.getInt("forfeited"));
  488.                 ret.quests.put(q, status);
  489.                 pse.setInt(1, rs.getInt("queststatusid"));
  490.                 ResultSet rsMobs = pse.executeQuery();
  491.                 while (rsMobs.next()) {
  492.                     status.setMobKills(rsMobs.getInt("mob"), rsMobs.getInt("count"));
  493.                 }
  494.                 rsMobs.close();
  495.             }
  496.             rs.close();
  497.             ps.close();
  498.             pse.close();
  499.             ps = con.prepareStatement("SELECT skillid,skilllevel,masterlevel FROM skills WHERE characterid = ?");
  500.             ps.setInt(1, charid);
  501.             rs = ps.executeQuery();
  502.             while (rs.next()) {
  503.                 ret.skills.put(SkillFactory.getSkill(rs.getInt("skillid")), new SkillEntry(rs.getInt("skilllevel"), rs.getInt("masterlevel")));
  504.             }
  505.             rs.close();
  506.             ps.close();
  507.             ps = con.prepareStatement("SELECT * FROM skillmacros WHERE characterid = ?");
  508.             ps.setInt(1, charid);
  509.             rs = ps.executeQuery();
  510.             while (rs.next()) {
  511.                 int skill1 = rs.getInt("skill1");
  512.                 int skill2 = rs.getInt("skill2");
  513.                 int skill3 = rs.getInt("skill3");
  514.                 String name = rs.getString("name");
  515.                 int shout = rs.getInt("shout");
  516.                 int position = rs.getInt("position");
  517.                 SkillMacro macro = new SkillMacro(skill1, skill2, skill3, name, shout, position);
  518.                 ret.skillMacros[position] = macro;
  519.             }
  520.             rs.close();
  521.             ps.close();
  522.             ps = con.prepareStatement("SELECT `key`,`type`,`action` FROM keymap WHERE characterid = ?");
  523.             ps.setInt(1, charid);
  524.             rs = ps.executeQuery();
  525.             while (rs.next()) {
  526.                 int key = rs.getInt("key");
  527.                 int type = rs.getInt("type");
  528.                 int action = rs.getInt("action");
  529.                 ret.keymap.put(Integer.valueOf(key), new MapleKeyBinding(type, action));
  530.             }
  531.             rs.close();
  532.             ps.close();
  533.             ps = con.prepareStatement("SELECT `locationtype`,`map` FROM savedlocations WHERE characterid = ?");
  534.             ps.setInt(1, charid);
  535.             rs = ps.executeQuery();
  536.             while (rs.next()) {
  537.                 String locationType = rs.getString("locationtype");
  538.                 int mapid = rs.getInt("map");
  539.                 ret.savedLocations[SavedLocationType.valueOf(locationType).ordinal()] = mapid;
  540.             }
  541.             rs.close();
  542.             ps.close();
  543.             ps = con.prepareStatement("SELECT `characterid_to`,`when` FROM famelog WHERE characterid = ? AND DATEDIFF(NOW(),`when`) < 30");
  544.             ps.setInt(1, charid);
  545.             rs = ps.executeQuery();
  546.             ret.lastfametime = 0;
  547.             ret.lastmonthfameids = new ArrayList<Integer>(31);
  548.             while (rs.next()) {
  549.                 ret.lastfametime = Math.max(ret.lastfametime, rs.getTimestamp("when").getTime());
  550.                 ret.lastmonthfameids.add(Integer.valueOf(rs.getInt("characterid_to")));
  551.             }
  552.             rs.close();
  553.             ps.close();
  554.             ret.buddylist.loadFromDb(charid);
  555.             ret.storage = MapleStorage.loadOrCreateFromDB(ret.accountid);
  556.         }
  557.         if (ret.getInventory(MapleInventoryType.EQUIPPED).getItem((byte) -18) != null) {
  558.             ret.maplemount = new MapleMount(ret, ret.getInventory(MapleInventoryType.EQUIPPED).getItem((byte) -18).getItemId(), 1004);
  559.             ret.maplemount.setExp(mountexp);
  560.             ret.maplemount.setLevel(mountlevel);
  561.             ret.maplemount.setTiredness(mounttiredness);
  562.             ret.maplemount.setActive(false);
  563.         } else {
  564.             ret.maplemount = new MapleMount(ret, 0, 1004);
  565.             ret.maplemount.setExp(mountexp);
  566.             ret.maplemount.setLevel(mountlevel);
  567.             ret.maplemount.setTiredness(mounttiredness);
  568.             ret.maplemount.setActive(false);
  569.         }
  570.         /*
  571.         ps = con.prepareStatement("SELECT jobid FROM JobChanges WHERE cid = ?");
  572.         ps.setInt(1, charid);
  573.         rs = ps.executeQuery();
  574.         while (rs.next()) {
  575.         ret.jobs.add(rs.getInt("jobid"));
  576.         }
  577.         java.util.Collections.sort(ret.jobs);
  578.         rs.close();
  579.         ps.close();
  580.          */
  581.         ret.recalcLocalStats();
  582.         ret.silentEnforceMaxHpMp();
  583.         return ret;
  584.     }
  585.     public static MapleCharacter getDefault(MapleClient client, int chrid) {
  586.         MapleCharacter ret = getDefault(client);
  587.         ret.id = chrid;
  588.         return ret;
  589.     }
  590.     public static MapleCharacter getDefault(MapleClient client) {
  591.         MapleCharacter ret = new MapleCharacter();
  592.         ret.client = client;
  593.         ret.hp = 50;
  594.         ret.maxhp = 50;
  595.         ret.mp = 5;
  596.         ret.maxmp = 5;
  597.         ret.map = null;
  598.         ret.exp.set(0);
  599.         ret.gmLevel = 0;
  600.         ret.clan = -1;
  601.         ret.job = MapleJob.BEGINNER;
  602.         ret.meso.set(0);
  603.         ret.level = 1;
  604.         ret.vip = 0;
  605.         ret.Gm = 1;
  606.         ret.reborns = 0;
  607.         ret.pvpdeaths = 0;
  608.         ret.pvpkills = 0;
  609.         ret.bombpoints = 0;
  610.         ret.accountid = client.getAccID();
  611.         ret.buddylist = new BuddyList(20);
  612.         ret.CP = 0;
  613.         ret.totalCP = 0;
  614.         ret.team = -1;
  615.         try {
  616.             Connection con = DatabaseConnection.getConnection();
  617.             PreparedStatement ps = con.prepareStatement("SELECT * FROM accounts WHERE id = ?");
  618.             ps.setInt(1, ret.accountid);
  619.             ResultSet rs = ps.executeQuery();
  620.             rs = ps.executeQuery();
  621.             if (rs.next()) {
  622.                 ret.getClient().setAccountName(rs.getString("name"));
  623.                 ret.getClient().setAccountPass(rs.getString("password"));
  624.                 ret.getClient().setGuest(rs.getInt("guest") > 0);
  625.                 ret.donatePoints = rs.getInt("donorPoints");
  626.                 ret.paypalnx = rs.getInt("paypalNX");
  627.                 ret.maplepoints = rs.getInt("mPoints");
  628.                 ret.cardnx = rs.getInt("cardNX");
  629.                 ret.donatorpoints = rs.getInt("donatorpoints");
  630.                 ret.lastLogin = rs.getLong("LastLoginInMilliseconds");
  631.             }
  632.             rs.close();
  633.             ps.close();
  634.         } catch (SQLException e) {
  635.             System.err.println("ERROR");
  636.         }
  637.         ret.incs = false;
  638.         ret.inmts = false;
  639.         ret.APQScore = 0;
  640.         ret.maplemount = null;
  641.         ret.setDefaultKeyMap();
  642.         ret.recalcLocalStats();
  643.         return ret;
  644.     }
  645.     public void saveToDB(boolean update, boolean full) {
  646.         Connection con = DatabaseConnection.getConnection();
  647.         try {
  648.             // clients should not be able to log back before their old state is saved (see MapleClient#getLoginState) so we are save to switch to a very low isolation level here
  649.             con.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
  650.             // connections are thread local now, no need to synchronize anymore =)
  651.             con.setAutoCommit(false);
  652.             PreparedStatement ps;
  653.             if (update) {
  654.                 ps = con.prepareStatement("UPDATE characters SET level = ?, fame = ?, str = ?, dex = ?, luk = ?, `int` = ?, exp = ?, hp = ?, mp = ?, maxhp = ?, maxmp = ?, sp = ?, ap = ?, gm = ?, skincolor = ?, gender = ?, job = ?, hair = ?, face = ?, map = ?, meso = ?, hpApUsed = ?, mpApUsed = ?, spawnpoint = ?, party = ?, buddyCapacity = ?, messengerid = ?, messengerposition = ?, reborns = ?, pvpkills = ?, pvpdeaths = ?, clan = ?, mountlevel = ?, mountexp = ?, mounttiredness = ?, married = ?, partnerid = ?, zakumlvl = ?, marriagequest = ?, vip = ?, dropmeso = ?, juankuan = ? WHERE id = ?");
  655.             } else {
  656.                 ps = con.prepareStatement("INSERT INTO characters (level, fame, str, dex, luk, `int`, exp, hp, mp, maxhp, maxmp, sp, ap, gm, skincolor, gender, job, hair, face, map, meso, hpApUsed, mpApUsed, spawnpoint, party, buddyCapacity, messengerid, messengerposition, reborns, pvpkills, pvpdeaths, clan, mountlevel, mountexp, mounttiredness, married, partnerid, zakumlvl, marriagequest, vip,dropmeso,juankuan, accountid, name, world) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
  657.             }
  658.             ps.setInt(1, level);
  659.             ps.setInt(2, fame);
  660.             ps.setInt(3, str);
  661.             ps.setInt(4, dex);
  662.             ps.setInt(5, luk);
  663.             ps.setInt(6, int_);
  664.             ps.setInt(7, exp.get());
  665.             ps.setInt(8, hp);
  666.             ps.setInt(9, mp);
  667.             ps.setInt(10, maxhp);
  668.             ps.setInt(11, maxmp);
  669.             ps.setInt(12, remainingSp);
  670.             ps.setInt(13, remainingAp);
  671.             ps.setInt(14, gmLevel);
  672.             ps.setInt(15, skinColor.getId());
  673.             ps.setInt(16, gender);
  674.             ps.setInt(17, job.getId());
  675.             ps.setInt(18, hair);
  676.             ps.setInt(19, face);
  677.             if (map == null) {
  678.                 ps.setInt(20, 0);
  679.             } else {
  680.                 if (map.getForcedReturnId() != 999999999) {
  681.                     ps.setInt(20, map.getForcedReturnId());
  682.                 } else {
  683.                     ps.setInt(20, map.getId());
  684.                 }
  685.             }
  686.             ps.setInt(21, meso.get());
  687.             ps.setInt(22, hpApUsed);
  688.             ps.setInt(23, mpApUsed);
  689.             if (map == null || map.getId() == 610020000 || map.getId() == 610020001) {
  690.                 ps.setInt(24, 0);
  691.             } else {
  692.                 MaplePortal closest = map.findClosestSpawnpoint(getPosition());
  693.                 if (closest != null) {
  694.                     ps.setInt(24, closest.getId());
  695.                 } else {
  696.                     ps.setInt(24, 0);
  697.                 }
  698.             }
  699.             if (party != null) {
  700.                 ps.setInt(25, party.getId());
  701.             } else {
  702.                 ps.setInt(25, -1);
  703.             }
  704.             ps.setInt(26, buddylist.getCapacity());
  705.             if (messenger != null) {
  706.                 ps.setInt(27, messenger.getId());
  707.                 ps.setInt(28, messengerposition);
  708.             } else {
  709.                 ps.setInt(27, 0);
  710.                 ps.setInt(28, 4);
  711.             }
  712.             ps.setInt(29, reborns);
  713.             ps.setInt(30, pvpkills);
  714.             ps.setInt(31, pvpdeaths);
  715.             ps.setInt(32, clan);
  716.             if (maplemount != null) {
  717.                 ps.setInt(33, maplemount.getLevel());
  718.                 ps.setInt(34, maplemount.getExp());
  719.                 ps.setInt(35, maplemount.getTiredness());
  720.             } else {
  721.                 ps.setInt(33, 1);
  722.                 ps.setInt(34, 0);
  723.                 ps.setInt(35, 0);
  724.             }
  725.             ps.setInt(36, married ? 1 : 0);
  726.             ps.setInt(37, partnerid);
  727.             ps.setInt(38, zakumLvl > 2 ? 2 : zakumLvl);
  728.             ps.setInt(39, marriageQuestLevel);
  729.             ps.setInt(40, vip);
  730.             ps.setInt(41, juankuan);
  731.             ps.setInt(42, dropmeso);
  732.             if (update) {
  733.                 ps.setInt(43, id);
  734.             } else {
  735.                 ps.setInt(43, accountid);
  736.                 ps.setString(44, name);
  737.                 ps.setInt(45, world);
  738.             }
  739.             if (!full) {
  740.                 ps.executeUpdate();
  741.             } else {
  742.                 int updateRows = ps.executeUpdate();
  743.                 if (!update) {
  744.                     ResultSet rs = ps.getGeneratedKeys();
  745.                     if (rs.next()) {
  746.                         this.id = rs.getInt(1);
  747.                     } else {
  748.                         throw new DatabaseException("Inserting char failed.");
  749.                     }
  750.                 } else if (updateRows < 1) {
  751.                     throw new DatabaseException("Character not in database (" + id + ")");
  752.                 }
  753.                 ps.close();
  754.                 for (int i = 0; i < 3; i++) {
  755.                     if (pets[i] != null) {
  756.                         pets[i].saveToDb();
  757.                     } else {
  758.                         break;
  759.                     }
  760.                 }
  761.                 deleteWhereCharacterId(con, "DELETE FROM skillmacros WHERE characterid = ?");
  762.                 for (int i = 0; i < 5; i++) {
  763.                     SkillMacro macro = skillMacros[i];
  764.                     if (macro != null) {
  765.                         ps = con.prepareStatement("INSERT INTO skillmacros (characterid, skill1, skill2, skill3, name, shout, position) VALUES (?, ?, ?, ?, ?, ?, ?)");
  766.                         ps.setInt(1, id);
  767.                         ps.setInt(2, macro.getSkill1());
  768.                         ps.setInt(3, macro.getSkill2());
  769.                         ps.setInt(4, macro.getSkill3());
  770.                         ps.setString(5, macro.getName());
  771.                         ps.setInt(6, macro.getShout());
  772.                         ps.setInt(7, i);
  773.                         ps.executeUpdate();
  774.                         ps.close();
  775.                     }
  776.                 }
  777.                 deleteWhereCharacterId(con, "DELETE FROM inventoryitems WHERE characterid = ?");
  778.                 ps = con.prepareStatement("INSERT INTO inventoryitems (characterid, itemid, inventorytype, position, quantity, owner, petid) VALUES (?, ?, ?, ?, ?, ?, ?)");
  779.                 PreparedStatement pse = con.prepareStatement("INSERT INTO inventoryequipment VALUES (DEFAULT, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
  780.                 for (MapleInventory iv : inventory) {
  781.                     ps.setInt(3, iv.getType().getType());
  782.                     for (IItem item : iv.list()) {
  783.                         ps.setInt(1, id);
  784.                         ps.setInt(2, item.getItemId());
  785.                         ps.setInt(4, item.getPosition());
  786.                         ps.setInt(5, item.getQuantity());
  787.                         ps.setString(6, item.getOwner());
  788.                         ps.setInt(7, item.getPetId());
  789.                         ps.executeUpdate();
  790.                         ResultSet rs = ps.getGeneratedKeys();
  791.                         int itemid;
  792.                         if (rs.next()) {
  793.                             itemid = rs.getInt(1);
  794.                         } else {
  795.                             throw new DatabaseException("Inserting char failed.");
  796.                         }
  797.                         if (iv.getType().equals(MapleInventoryType.EQUIP) || iv.getType().equals(MapleInventoryType.EQUIPPED)) {
  798.                             pse.setInt(1, itemid);
  799.                             IEquip equip = (IEquip) item;
  800.                             pse.setInt(2, equip.getUpgradeSlots());
  801.                             pse.setInt(3, equip.getLevel());
  802.                             pse.setInt(4, equip.getStr());
  803.                             pse.setInt(5, equip.getDex());
  804.                             pse.setInt(6, equip.getInt());
  805.                             pse.setInt(7, equip.getLuk());
  806.                             pse.setInt(8, equip.getHp());
  807.                             pse.setInt(9, equip.getMp());
  808.                             pse.setInt(10, equip.getWatk());
  809.                             pse.setInt(11, equip.getMatk());
  810.                             pse.setInt(12, equip.getWdef());
  811.                             pse.setInt(13, equip.getMdef());
  812.                             pse.setInt(14, equip.getAcc());
  813.                             pse.setInt(15, equip.getAvoid());
  814.                             pse.setInt(16, equip.getHands());
  815.                             pse.setInt(17, equip.getSpeed());
  816.                             pse.setInt(18, equip.getJump());
  817.                             pse.setInt(19, equip.getRingId());
  818.                             pse.setInt(20, equip.getLocked());
  819.                             pse.executeUpdate();
  820.                         }
  821.                     }
  822.                 }
  823.                 ps.close();
  824.                 pse.close();
  825.                 deleteWhereCharacterId(con, "DELETE FROM queststatus WHERE characterid = ?");
  826.                 ps = con.prepareStatement("INSERT INTO queststatus (`queststatusid`, `characterid`, `quest`, `status`, `time`, `forfeited`) VALUES (DEFAULT, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
  827.                 pse = con.prepareStatement("INSERT INTO queststatusmobs VALUES (DEFAULT, ?, ?, ?)");
  828.                 ps.setInt(1, id);
  829.                 for (MapleQuestStatus q : quests.values()) {
  830.                     ps.setInt(2, q.getQuest().getId());
  831.                     ps.setInt(3, q.getStatus().getId());
  832.                     ps.setInt(4, (int) (q.getCompletionTime() / 1000));
  833.                     ps.setInt(5, q.getForfeited());
  834.                     ps.executeUpdate();
  835.                     ResultSet rs = ps.getGeneratedKeys();
  836.                     rs.next();
  837.                     for (int mob : q.getMobKills().keySet()) {
  838.                         pse.setInt(1, rs.getInt(1));
  839.                         pse.setInt(2, mob);
  840.                         pse.setInt(3, q.getMobKills(mob));
  841.                         pse.executeUpdate();
  842.                     }
  843.                     rs.close();
  844.                 }
  845.                 ps.close();
  846.                 pse.close();
  847.                 deleteWhereCharacterId(con, "DELETE FROM skills WHERE characterid = ?");
  848.                 ps = con.prepareStatement("INSERT INTO skills (characterid, skillid, skilllevel, masterlevel) VALUES (?, ?, ?, ?)");
  849.                 ps.setInt(1, id);
  850.                 for (Entry<ISkill, SkillEntry> skill_ : skills.entrySet()) {
  851.                     ps.setInt(2, skill_.getKey().getId());
  852.                     ps.setInt(3, skill_.getValue().skillevel);
  853.                     ps.setInt(4, skill_.getValue().masterlevel);
  854.                     ps.executeUpdate();
  855.                 }
  856.                 ps.close();
  857.                 deleteWhereCharacterId(con, "DELETE FROM keymap WHERE characterid = ?");
  858.                 ps = con.prepareStatement("INSERT INTO keymap (characterid, `key`, `type`, `action`) VALUES (?, ?, ?, ?)");
  859.                 ps.setInt(1, id);
  860.                 for (Entry<Integer, MapleKeyBinding> keybinding : keymap.entrySet()) {
  861.                     ps.setInt(2, keybinding.getKey().intValue());
  862.                     ps.setInt(3, keybinding.getValue().getType());
  863.                     ps.setInt(4, keybinding.getValue().getAction());
  864.                     ps.executeUpdate();
  865.                 }
  866.                 ps.close();
  867.                 deleteWhereCharacterId(con, "DELETE FROM savedlocations WHERE characterid = ?");
  868.                 ps = con.prepareStatement("INSERT INTO savedlocations (characterid, `locationtype`, `map`) VALUES (?, ?, ?)");
  869.                 ps.setInt(1, id);
  870.                 for (SavedLocationType savedLocationType : SavedLocationType.values()) {
  871.                     if (savedLocations[savedLocationType.ordinal()] != -1) {
  872.                         ps.setString(2, savedLocationType.name());
  873.                         ps.setInt(3, savedLocations[savedLocationType.ordinal()]);
  874.                         ps.executeUpdate();
  875.                     }
  876.                 }
  877.                 ps.close();
  878.                 deleteWhereCharacterId(con, "DELETE FROM buddies WHERE characterid = ? AND pending = 0");
  879.                 ps = con.prepareStatement("INSERT INTO buddies (characterid, `buddyid`, `pending`) VALUES (?, ?, 0)");
  880.                 ps.setInt(1, id);
  881.                 for (BuddylistEntry entry : buddylist.getBuddies()) {
  882.                     if (entry.isVisible()) {
  883.                         ps.setInt(2, entry.getCharacterId());
  884.                         ps.executeUpdate();
  885.                     }
  886.                 }
  887.                 ps.close();
  888.                 ps = con.prepareStatement("UPDATE accounts SET `paypalNX` = ?, `mPoints` = ?, `cardNX` = ?, `donorPoints` = ?, `donatorpoints` = ? WHERE id = ?");
  889.                 ps.setInt(1, paypalnx);
  890.                 ps.setInt(2, maplepoints);
  891.                 ps.setInt(3, cardnx);
  892.                 ps.setInt(4, donatePoints);
  893.                 ps.setInt(5, donatorpoints);
  894.                 ps.setInt(6, client.getAccID());
  895.                 ps.executeUpdate();
  896.                 ps.close();
  897.                 if (storage != null) {
  898.                     storage.saveToDB();
  899.                 }
  900.             }
  901.             con.commit();
  902.         } catch (Exception e) {
  903.             log.error(MapleClient.getLogMessage(this, "[charsave] Error saving character data"), e);
  904.             try {
  905.                 con.rollback();
  906.             } catch (SQLException e1) {
  907.                 log.error(MapleClient.getLogMessage(this, "[charsave] Error Rolling Back"), e);
  908.             }
  909.         } finally {
  910.             try {
  911.                 con.setAutoCommit(true);
  912.                 con.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
  913.             } catch (SQLException e) {
  914.                 log.error(MapleClient.getLogMessage(this, "[charsave] Error going back to autocommit mode"), e);
  915.             }
  916.         }
  917.     }
  918.     public void setGMLevel(int level) {
  919.         if (level >= 5) {
  920.             this.gmLevel = 5;
  921.         } else if (level <= 0) {
  922.             this.gmLevel = 0;
  923.         } else {
  924.             this.gmLevel = level;
  925.         }
  926.     }
  927.     public boolean isGM() {
  928.         return gmLevel >= 3;
  929.     }
  930.     public int getGMLevel() {
  931.         return gmLevel;
  932.     }
  933.     public boolean hasGmLevel(int level) {
  934.         return gmLevel >= level;
  935.     }
  936.     public void setVip(int amount) {
  937.         if (amount > 4) {
  938.             this.vip = 4;
  939.         } else if (amount <= -4) {
  940.             this.vip = -4;
  941.         } else {
  942.             this.vip = amount;
  943.         }
  944.     }
  945.     public int getGm() {
  946.         return gm;
  947.     }
  948.     public int getVip() {
  949.         return vip;
  950.     }
  951.     public int getItemId() {
  952.         return item;
  953.     }
  954.     public void gainGm(int amount) {
  955.         this.gm += amount;
  956.     }
  957.     public void gainVip(int amount) {
  958.         this.vip += amount;
  959.     }
  960. public void gainjuankuan(int amount) {
  961.         this.juankuan += amount;
  962.     }
  963. public void setDropmeso(int dropmeso) {
  964.         this.dropmeso = dropmeso;
  965.     }
  966. public Object getChannelSever() {
  967.         throw new UnsupportedOperationException("Not yet implemented");
  968.     }
  969. public IItem lockitem(int slot, boolean lock, int type)
  970. {
  971. byte set = 0;
  972. byte eqslot = (byte)slot;
  973. ServernoticeMapleClientMessageCallback cm = new ServernoticeMapleClientMessageCallback(getClient());
  974. Equip nEquip = (Equip)getInventory(MapleInventoryType.USE).getItem(eqslot);
  975. if (type == 1)
  976. nEquip = (Equip)getInventory(MapleInventoryType.EQUIP).getItem(eqslot);
  977. else
  978. if (type == 2)
  979. nEquip = (Equip)getInventory(MapleInventoryType.ETC).getItem(eqslot);
  980. else
  981. if (type == 3)
  982. nEquip = (Equip)getInventory(MapleInventoryType.CASH).getItem(eqslot);
  983. if (nEquip != null)
  984. {
  985. if (lock)
  986. {
  987. set = 1;
  988. cm.dropMessage((new StringBuilder()).append("恭喜,锁定物品: ").append(slot).append(" 成功!").toString());
  989. } else
  990. {
  991. cm.dropMessage((new StringBuilder()).append("恭喜,解锁物品: ").append(slot).append(" 成功!").toString());
  992. }
  993. nEquip.setLocked(set);
  994. getClient().getSession().write(MaplePacketCreator.getCharInfo(this));
  995. getMap().removePlayer(this);
  996. getMap().addPlayer(this);
  997. } else
  998. {
  999. cm.dropMessage((new StringBuilder()).append("Item Slot ").append(slot).append(" Equip Null.").toString());
  1000. }
  1001. return nEquip;
  1002. }
  1003.     public void deleteNullItem(int id) {
  1004.         throw new UnsupportedOperationException("Not yet implemented");
  1005.     }
  1006. public void gainExp(long l, boolean b, boolean b0, boolean highestDamage) {
  1007.         throw new UnsupportedOperationException("Not yet implemented");
  1008.     }
  1009. public IItem lockitem1(int slot, boolean lock) {
  1010.         byte set = (byte) 0;
  1011.         byte eqslot = (byte) slot;
  1012.         ServernoticeMapleClientMessageCallback cm = new ServernoticeMapleClientMessageCallback(this.getClient());
  1013.         Equip nEquip = (Equip) this.getInventory(MapleInventoryType.EQUIP).getItem(eqslot);
  1014.         if (nEquip != null) {
  1015.             if (lock) {
  1016.                 set = (byte) 1;
  1017.                 cm.dropMessage("锁定装备: " + slot + " 成功");
  1018.             } else {
  1019.                 cm.dropMessage("解锁装备: " + slot + " 成功");
  1020.             }
  1021.             nEquip.setLocked(set);
  1022.             getClient().getSession().write(MaplePacketCreator.getCharInfo(this));
  1023.             getMap().removePlayer(this);
  1024.             getMap().addPlayer(this);
  1025.         } else {
  1026.             cm.dropMessage("Item Slot " + slot + " Equip Null.");
  1027.         }
  1028.         return nEquip;
  1029.     }
  1030. public int getmPoints() {
  1031.         return this.mpoints;
  1032.     }
  1033. public int getpaypalNX() {
  1034.         return this.paypalNX;
  1035.     }
  1036. public int getDropmeso() {
  1037.         return dropmeso;
  1038.     }
  1039. public int getjuankuan() {
  1040.         return juankuan;
  1041.     }
  1042.     public int getNX() {
  1043.         return paypalnx;
  1044.     }
  1045.     public void gainNX(int amount) {
  1046.         this.paypalnx += amount;
  1047.     }
  1048.     public void setName(String name) {
  1049.         this.name = name;
  1050.     }
  1051.     private void deleteWhereCharacterId(Connection con, String sql) throws SQLException {
  1052.         PreparedStatement ps = con.prepareStatement(sql);
  1053.         ps.setInt(1, id);
  1054.         ps.executeUpdate();
  1055.         ps.close();
  1056.     }
  1057.     public MapleQuestStatus getQuest(MapleQuest quest) {
  1058.         if (!quests.containsKey(quest)) {
  1059.             return new MapleQuestStatus(quest, MapleQuestStatus.Status.NOT_STARTED);
  1060.         }
  1061.         return quests.get(quest);
  1062.     }
  1063.     public void updateQuest(MapleQuestStatus quest) {
  1064.         quests.put(quest.getQuest(), quest);
  1065.         if (!(quest.getQuest() instanceof MapleCustomQuest)) {
  1066.             if (quest.getStatus().equals(MapleQuestStatus.Status.STARTED)) {
  1067.                 client.getSession().write(MaplePacketCreator.startQuest(this, (short) quest.getQuest().getId()));
  1068.                 client.getSession().write(MaplePacketCreator.updateQuestInfo(this, (short) quest.getQuest().getId(), quest.getNpc(), (byte) 8));
  1069.             } else if (quest.getStatus().equals(MapleQuestStatus.Status.COMPLETED)) {
  1070.                 client.getSession().write(MaplePacketCreator.completeQuest(this, (short) quest.getQuest().getId()));
  1071.             } else if (quest.getStatus().equals(MapleQuestStatus.Status.NOT_STARTED)) {
  1072.                 client.getSession().write(MaplePacketCreator.forfeitQuest(this, (short) quest.getQuest().getId()));
  1073.             }
  1074.         }
  1075.     }
  1076.     public boolean getGMChat() {
  1077.         return gmchattype;
  1078.     }
  1079.     public static int getIdByName(String name, int world) {
  1080.         Connection con = DatabaseConnection.getConnection();
  1081.         PreparedStatement ps;
  1082.         try {
  1083.             ps = con.prepareStatement("SELECT id FROM characters WHERE name = ? AND world = ?");
  1084.             ps.setString(1, name);
  1085.             ps.setInt(2, world);
  1086.             ResultSet rs = ps.executeQuery();
  1087.             if (!rs.next()) {
  1088.                 ps.close();
  1089.                 return -1;
  1090.             }
  1091.             int id = rs.getInt("id");
  1092.             ps.close();
  1093.             return id;
  1094.         } catch (SQLException e) {
  1095.             System.err.println("ERROR");
  1096.         }
  1097.         return -1;
  1098.     }
  1099.     public static String getNameById(int id, int world) {
  1100.         Connection con = DatabaseConnection.getConnection();
  1101.         try {
  1102.             PreparedStatement ps = con.prepareStatement("SELECT name FROM characters WHERE id = ? AND world = ?");
  1103.             ps.setInt(1, id);
  1104.             ps.setInt(2, world);
  1105.             ResultSet rs = ps.executeQuery();
  1106.             if (!rs.next()) {
  1107.                 ps.close();
  1108.                 return null;
  1109.             }
  1110.             String name = rs.getString("name");
  1111.             ps.close();
  1112.             return name;
  1113.         } catch (SQLException e) {
  1114.             System.err.println("ERROR");
  1115.         }
  1116.         return null;
  1117.     }
  1118.     public Integer getBuffedValue(MapleBuffStat effect) {
  1119.         MapleBuffStatValueHolder mbsvh = effects.get(effect);
  1120.         if (mbsvh == null) {
  1121.             return null;
  1122.         }
  1123.         return Integer.valueOf(mbsvh.value);
  1124.     }
  1125.     public boolean isBuffFrom(MapleBuffStat stat, ISkill skill) {
  1126.         MapleBuffStatValueHolder mbsvh = effects.get(stat);
  1127.         if (mbsvh == null) {
  1128.             return false;
  1129.         }
  1130.         return mbsvh.effect.isSkill() && mbsvh.effect.getSourceId() == skill.getId();
  1131.     }
  1132.     public int getBuffSource(MapleBuffStat stat) {
  1133.         MapleBuffStatValueHolder mbsvh = effects.get(stat);
  1134.         if (mbsvh == null) {
  1135.             return -1;
  1136.         }
  1137.         return mbsvh.effect.getSourceId();
  1138.     }
  1139.     public int getRingRequested() {
  1140.         return this.ringRequest;
  1141.     }
  1142.     public void setRingRequested(int set) {
  1143.         ringRequest = set;
  1144.     }
  1145.     public int getItemQuantity(int itemid, boolean checkEquipped) {
  1146.         MapleInventoryType type = MapleItemInformationProvider.getInstance().getInventoryType(itemid);
  1147.         MapleInventory iv = inventory[type.ordinal()];
  1148.         int possesed = iv.countById(itemid);
  1149.         if (checkEquipped) {
  1150.             possesed += inventory[MapleInventoryType.EQUIPPED.ordinal()].countById(itemid);
  1151.         }
  1152.         return possesed;
  1153.     }
  1154.     public void setBuffedValue(MapleBuffStat effect, int value) {
  1155.         MapleBuffStatValueHolder mbsvh = effects.get(effect);
  1156.         if (mbsvh == null) {
  1157.             return;
  1158.         }
  1159.         mbsvh.value = value;
  1160.     }
  1161.     public Long getBuffedStarttime(MapleBuffStat effect) {
  1162.         MapleBuffStatValueHolder mbsvh = effects.get(effect);
  1163.         if (mbsvh == null) {
  1164.             return null;
  1165.         }
  1166.         return Long.valueOf(mbsvh.startTime);
  1167.     }
  1168.     public MapleStatEffect getStatForBuff(MapleBuffStat effect) {
  1169.         MapleBuffStatValueHolder mbsvh = effects.get(effect);
  1170.         if (mbsvh == null) {
  1171.             return null;
  1172.         }
  1173.         return mbsvh.effect;
  1174.     }
  1175.     private void prepareDragonBlood(final MapleStatEffect bloodEffect) {
  1176.         if (dragonBloodSchedule != null) {
  1177.             dragonBloodSchedule.cancel(false);
  1178.         }
  1179.         dragonBloodSchedule = TimerManager.getInstance().register(new Runnable() {
  1180.             @Override
  1181.             public void run() {
  1182.                 addHP(-bloodEffect.getX());
  1183.                 getClient().getSession().write(MaplePacketCreator.showOwnBuffEffect(bloodEffect.getSourceId(), 5));
  1184.                 getMap().broadcastMessage(MapleCharacter.this, MaplePacketCreator.showBuffeffect(getId(), bloodEffect.getSourceId(), 5, (byte) 3), false);
  1185.             }
  1186.         }, 4000, 4000);
  1187.     }
  1188.     public void startFullnessSchedule(final int decrease, final MaplePet pet, int petSlot) {
  1189.         ScheduledFuture<?> schedule = TimerManager.getInstance().register(new Runnable() {
  1190.             @Override
  1191.             public void run() {
  1192.                 if (pet != null) {
  1193.                     int newFullness = pet.getFullness() - decrease;
  1194.                     if (newFullness <= 5) {
  1195.                         pet.setFullness(15);
  1196.                         unequipPet(pet, true, true);
  1197.                     } else {
  1198.                         pet.setFullness(newFullness);
  1199.                         getClient().getSession().write(MaplePacketCreator.updatePet(pet, true));
  1200.                     }
  1201.                 }
  1202.             }
  1203.         }, 60000, 60000);
  1204.         switch (petSlot) {
  1205.             case 0:
  1206.                 fullnessSchedule = schedule;
  1207.             case 1:
  1208.                 fullnessSchedule_1 = schedule;
  1209.             case 2:
  1210.                 fullnessSchedule_2 = schedule;
  1211.         }
  1212.     }
  1213.     public void cancelFullnessSchedule(int petSlot) {
  1214.         switch (petSlot) {
  1215.             case 0:
  1216.                 fullnessSchedule.cancel(false);
  1217.             case 1:
  1218.                 fullnessSchedule_1.cancel(false);
  1219.             case 2:
  1220.                 fullnessSchedule_2.cancel(false);
  1221.         }
  1222.     }
  1223.     public void startMapTimeLimitTask(final MapleMap from, final MapleMap to) {
  1224.         if (to.getTimeLimit() > 0 && from != null) {
  1225.             final MapleCharacter chr = this;
  1226.             mapTimeLimitTask = TimerManager.getInstance().register(new Runnable() {
  1227.                 @Override
  1228.                 public void run() {
  1229.                     MaplePortal pfrom = null;
  1230.                     if (MapleItemInformationProvider.getInstance().isMiniDungeonMap(from.getId())) {
  1231.                         pfrom = from.getPortal("MD00");
  1232.                     } else {
  1233.                         pfrom = from.getPortal(0);
  1234.                     }
  1235.                     if (pfrom != null) {
  1236.                         chr.changeMap(from, pfrom);
  1237.                     }
  1238.                 }
  1239.             }, from.getTimeLimit() * 1000, from.getTimeLimit() * 1000);
  1240.         }
  1241.     }
  1242.     public boolean tempHasItems() {
  1243.         PreparedStatement ps = null;
  1244.         ResultSet rs = null;
  1245.         try {
  1246.             Connection con = DatabaseConnection.getConnection();
  1247.             ps = con.prepareStatement("SELECT ownerid FROM hiredmerchanttemp WHERE ownerid = ?");
  1248.             ps.setInt(1, getId());
  1249.             rs = ps.executeQuery();
  1250.             if (rs.next()) {
  1251.                 rs.close();
  1252.                 ps.close();
  1253.                 return true;
  1254.             }
  1255.             rs.close();
  1256.             ps.close();
  1257.         } catch (SQLException se) {
  1258.             System.err.println("错误:"+se);
  1259.         } finally {
  1260.             try {
  1261.                 if (ps != null && !ps.isClosed())
  1262.                     ps.close();
  1263.                 if (rs != null && !rs.isClosed())
  1264.                     rs.close();
  1265.             } catch (SQLException e) {
  1266.                 e.printStackTrace();
  1267.             }
  1268.         }
  1269.         return false;
  1270.     }
  1271.     public boolean isBlessed() {
  1272.         return blessed;
  1273.     }
  1274.     public void setBlessed(boolean bless) {
  1275.         this.blessed = bless;
  1276.     }
  1277.    public boolean isMarried() {
  1278.         return married;
  1279.     }
  1280.     public int getPvpDeaths() {
  1281.         return pvpdeaths;
  1282.     }
  1283.     public void setMarried(boolean married) {
  1284.         this.married = married;
  1285.     }
  1286.     public String getEngager() throws SQLException {
  1287.         return this.engager;
  1288.     }
  1289.     public void setEngager(String partner) throws SQLException {
  1290.         this.engager = partner;
  1291.     }
  1292.     public void cancelMapTimeLimitTask() {
  1293.         if (mapTimeLimitTask != null) {
  1294.             mapTimeLimitTask.cancel(false);
  1295.         }
  1296.     }
  1297.     public void registerEffect(MapleStatEffect effect, long starttime, ScheduledFuture<?> schedule) {
  1298.         if (effect.isHide() && isGM()) {
  1299.             this.hidden = true;
  1300.             getMap().broadcastNONGMMessage(this, MaplePacketCreator.removePlayerFromMap(getId()), false);
  1301.             this.setOffOnline(false);
  1302.         } else if (effect.isDragonBlood()) {
  1303.             prepareDragonBlood(effect);
  1304.         } else if (effect.isBerserk()) {
  1305.             checkBerserk();
  1306.         } else if (effect.isBeholder()) {
  1307.             prepareBeholderEffect();
  1308.         }
  1309.         for (Pair<MapleBuffStat, Integer> statup : effect.getStatups()) {
  1310.             effects.put(statup.getLeft(), new MapleBuffStatValueHolder(effect, starttime, schedule, statup.getRight().intValue()));
  1311.         }
  1312.         recalcLocalStats();
  1313.     }
  1314.     private List<MapleBuffStat> getBuffStats(MapleStatEffect effect, long startTime) {
  1315.         List<MapleBuffStat> stats = new ArrayList<MapleBuffStat>();
  1316.         for (Entry<MapleBuffStat, MapleBuffStatValueHolder> stateffect : effects.entrySet()) {
  1317.             MapleBuffStatValueHolder mbsvh = stateffect.getValue();
  1318.             if (mbsvh.effect.sameSource(effect) && (startTime == -1 || startTime == mbsvh.startTime)) {
  1319.                 stats.add(stateffect.getKey());
  1320.             }
  1321.         }
  1322.         return stats;
  1323.     }
  1324.     private void deregisterBuffStats(List<MapleBuffStat> stats) {
  1325.         List<MapleBuffStatValueHolder> effectsToCancel = new ArrayList<MapleBuffStatValueHolder>(stats.size());
  1326.         for (MapleBuffStat stat : stats) {
  1327.             MapleBuffStatValueHolder mbsvh = effects.get(stat);
  1328.             if (mbsvh != null) {
  1329.                 effects.remove(stat);
  1330.                 boolean addMbsvh = true;
  1331.                 for (MapleBuffStatValueHolder contained : effectsToCancel) {
  1332.                     if (mbsvh.startTime == contained.startTime && contained.effect == mbsvh.effect) {
  1333.                         addMbsvh = false;
  1334.                     }
  1335.                 }
  1336.                 if (addMbsvh) {
  1337.                     effectsToCancel.add(mbsvh);
  1338.                 }
  1339.                 if (stat == MapleBuffStat.SUMMON || stat == MapleBuffStat.PUPPET) {
  1340.                     int summonId = mbsvh.effect.getSourceId();
  1341.                     MapleSummon summon = summons.get(summonId);
  1342.                     if (summon != null) {
  1343.                         getMap().broadcastMessage(MaplePacketCreator.removeSpecialMapObject(summon, true));
  1344.                         getMap().removeMapObject(summon);
  1345.                         removeVisibleMapObject(summon);
  1346.                         summons.remove(summonId);
  1347.                     }
  1348.                     if (summon.getSkill() == 1321007) {
  1349.                         if (beholderHealingSchedule != null) {
  1350.                             beholderHealingSchedule.cancel(false);
  1351.                             beholderHealingSchedule = null;
  1352.                         }
  1353.                         if (beholderBuffSchedule != null) {
  1354.                             beholderBuffSchedule.cancel(false);
  1355.                             beholderBuffSchedule = null;
  1356.                         }
  1357.                     }
  1358.                 } else if (stat == MapleBuffStat.DRAGONBLOOD) {
  1359.                     dragonBloodSchedule.cancel(false);
  1360.                     dragonBloodSchedule = null;
  1361.                 }
  1362.             }
  1363.         }
  1364.         for (MapleBuffStatValueHolder cancelEffectCancelTasks : effectsToCancel) {
  1365.             if (getBuffStats(cancelEffectCancelTasks.effect, cancelEffectCancelTasks.startTime).size() == 0) {
  1366.                 cancelEffectCancelTasks.schedule.cancel(false);
  1367.             }
  1368.         }
  1369.     }
  1370.     /**
  1371.      * @param effect
  1372.      * @param overwrite when overwrite is set no data is sent and all the Buffstats in the StatEffect are deregistered
  1373.      * @param startTime
  1374.      */
  1375.     public void cancelEffect(MapleStatEffect effect, boolean overwrite, long startTime) {
  1376.         List<MapleBuffStat> buffstats;
  1377.         if (!overwrite) {
  1378.             buffstats = getBuffStats(effect, startTime);
  1379.         } else {
  1380.             List<Pair<MapleBuffStat, Integer>> statups = effect.getStatups();
  1381.             buffstats = new ArrayList<MapleBuffStat>(statups.size());
  1382.             for (Pair<MapleBuffStat, Integer> statup : statups) {
  1383.                 buffstats.add(statup.getLeft());
  1384.             }
  1385.         }
  1386.         deregisterBuffStats(buffstats);
  1387.         if (effect.isMagicDoor()) {
  1388.             // remove for all on maps
  1389.             if (!getDoors().isEmpty()) {
  1390.                 MapleDoor door = getDoors().iterator().next();
  1391.                 for (MapleCharacter chr : door.getTarget().getCharacters()) {
  1392.                     door.sendDestroyData(chr.getClient());
  1393.                 }
  1394.                 for (MapleCharacter chr : door.getTown().getCharacters()) {
  1395.                     door.sendDestroyData(chr.getClient());
  1396.                 }
  1397.                 for (MapleDoor destroyDoor : getDoors()) {
  1398.                     door.getTarget().removeMapObject(destroyDoor);
  1399.                     door.getTown().removeMapObject(destroyDoor);
  1400.                 }
  1401.                 clearDoors();
  1402.                 silentPartyUpdate();
  1403.             }
  1404.         }
  1405.         if (effect.isMonsterRiding()) {
  1406.             if (effect.getSourceId() != 5221006) {
  1407.                 this.getMount().cancelSchedule();
  1408.                 this.getMount().setActive(false);
  1409.             }
  1410.         }
  1411.         // check if we are still logged in o.o
  1412.         if (!overwrite) {
  1413.             cancelPlayerBuffs(buffstats);
  1414.             if (effect.isHide() && (MapleCharacter) getMap().getMapObject(getObjectId()) != null) {
  1415.                 this.hidden = false;
  1416.                 getMap().broadcastNONGMMessage(this, MaplePacketCreator.spawnPlayerMapobject(this), false);
  1417.                 setOffOnline(true);
  1418.                 for (int i = 0; i < 3; i++) {
  1419.                     if (pets[i] != null) {
  1420.                         getMap().broadcastNONGMMessage(this, MaplePacketCreator.showPet(this, pets[i], false, false), false);
  1421.                     } else {
  1422.                         break;
  1423.                     }
  1424.                 }
  1425.             }
  1426.         }
  1427.     }
  1428.     public void cancelBuffStats(MapleBuffStat stat) {
  1429.         List<MapleBuffStat> buffStatList = Arrays.asList(stat);
  1430.         deregisterBuffStats(buffStatList);
  1431.         cancelPlayerBuffs(buffStatList);
  1432.     }
  1433.     public void cancelEffectFromBuffStat(MapleBuffStat stat) {
  1434.         cancelEffect(effects.get(stat).effect, false, -1);
  1435.     }
  1436.     private void cancelPlayerBuffs(List<MapleBuffStat> buffstats) {
  1437.         if (getClient().getChannelServer().getPlayerStorage().getCharacterById(getId()) != null) { // are we still connected ?
  1438.             recalcLocalStats();
  1439.             enforceMaxHpMp();
  1440.             getClient().getSession().write(MaplePacketCreator.cancelBuff(buffstats));
  1441.             getMap().broadcastMessage(this, MaplePacketCreator.cancelForeignBuff(getId(), buffstats), false);
  1442.         }
  1443.     }
  1444.     public void dispel() {
  1445.         LinkedList<MapleBuffStatValueHolder> allBuffs = new LinkedList<MapleBuffStatValueHolder>(effects.values());
  1446.         for (MapleBuffStatValueHolder mbsvh : allBuffs) {
  1447.             if (mbsvh.effect.isSkill()) {
  1448.                 cancelEffect(mbsvh.effect, false, mbsvh.startTime);
  1449.             }
  1450.         }
  1451.     }
  1452.     public void cancelAllBuffs() {
  1453.         LinkedList<MapleBuffStatValueHolder> allBuffs = new LinkedList<MapleBuffStatValueHolder>(effects.values());
  1454.         for (MapleBuffStatValueHolder mbsvh : allBuffs) {
  1455.             cancelEffect(mbsvh.effect, false, mbsvh.startTime);
  1456.         }
  1457.     }
  1458.     public void cancelMorphs() {
  1459.         LinkedList<MapleBuffStatValueHolder> allBuffs = new LinkedList<MapleBuffStatValueHolder>(effects.values());
  1460.         for (MapleBuffStatValueHolder mbsvh : allBuffs) {
  1461.             if (mbsvh.effect.isMorph() && mbsvh.effect.getSourceId() != 5111005 && mbsvh.effect.getSourceId() != 5121003) {
  1462.                 cancelEffect(mbsvh.effect, false, mbsvh.startTime);
  1463.             }
  1464.         }
  1465.     }
  1466.     public void silentGiveBuffs(List<PlayerBuffValueHolder> buffs) {
  1467.         for (PlayerBuffValueHolder mbsvh : buffs) {
  1468.             mbsvh.effect.silentApplyBuff(this, mbsvh.startTime);
  1469.         }
  1470.     }
  1471.     public List<PlayerBuffValueHolder> getAllBuffs() {
  1472.         List<PlayerBuffValueHolder> ret = new ArrayList<PlayerBuffValueHolder>();
  1473.         for (MapleBuffStatValueHolder mbsvh : effects.values()) {
  1474.             ret.add(new PlayerBuffValueHolder(mbsvh.startTime, mbsvh.effect));
  1475.         }
  1476.         return ret;
  1477.     }
  1478.     public void cancelMagicDoor() {
  1479.         LinkedList<MapleBuffStatValueHolder> allBuffs = new LinkedList<MapleBuffStatValueHolder>(effects.values());
  1480.         for (MapleBuffStatValueHolder mbsvh : allBuffs) {
  1481.             if (mbsvh.effect.isMagicDoor()) {
  1482.                 cancelEffect(mbsvh.effect, false, mbsvh.startTime);
  1483.             }
  1484.         }
  1485.     }
  1486.     public void handleOrbgain() {
  1487.         MapleStatEffect ceffect = null;
  1488.         int advComboSkillLevel = getSkillLevel(SkillFactory.getSkill(1120003));
  1489.         if (advComboSkillLevel > 0) {
  1490.             ceffect = SkillFactory.getSkill(1120003).getEffect(advComboSkillLevel);
  1491.         } else {
  1492.             ceffect = SkillFactory.getSkill(1111002).getEffect(getSkillLevel(SkillFactory.getSkill(1111002)));
  1493.         }
  1494.         if (getBuffedValue(MapleBuffStat.COMBO) < ceffect.getX() + 1) {
  1495.             int neworbcount = getBuffedValue(MapleBuffStat.COMBO) + 1;
  1496.             if (advComboSkillLevel > 0 && ceffect.makeChanceResult()) {
  1497.                 if (neworbcount < ceffect.getX() + 1) {
  1498.                     neworbcount++;
  1499.                 }
  1500.             }
  1501.             List<Pair<MapleBuffStat, Integer>> stat = Collections.singletonList(new Pair<MapleBuffStat, Integer>(MapleBuffStat.COMBO, neworbcount));
  1502.             setBuffedValue(MapleBuffStat.COMBO, neworbcount);
  1503.             int duration = ceffect.getDuration();
  1504.             duration += (int) ((getBuffedStarttime(MapleBuffStat.COMBO) - System.currentTimeMillis()));
  1505.             getClient().getSession().write(MaplePacketCreator.giveBuff(1111002, duration, stat));
  1506.             getMap().broadcastMessage(this, MaplePacketCreator.giveForeignBuff(getId(), stat, ceffect), false);
  1507.         }
  1508.     }
  1509.     public void handleOrbconsume() {
  1510.         ISkill combo = SkillFactory.getSkill(1111002);
  1511.         MapleStatEffect ceffect = combo.getEffect(getSkillLevel(combo));
  1512.         List<Pair<MapleBuffStat, Integer>> stat = Collections.singletonList(new Pair<MapleBuffStat, Integer>(MapleBuffStat.COMBO, 1));
  1513.         setBuffedValue(MapleBuffStat.COMBO, 1);
  1514.         int duration = ceffect.getDuration();
  1515.         duration += (int) ((getBuffedStarttime(MapleBuffStat.COMBO) - System.currentTimeMillis()));
  1516.         getClient().getSession().write(MaplePacketCreator.giveBuff(1111002, duration, stat));
  1517.         getMap().broadcastMessage(this, MaplePacketCreator.giveForeignBuff(getId(), stat, ceffect), false);
  1518.     }
  1519.     private void silentEnforceMaxHpMp() {
  1520.         setMp(getMp());
  1521.         setHp(getHp(), true);
  1522.     }
  1523.     private void enforceMaxHpMp() {
  1524.         List<Pair<MapleStat, Integer>> stats = new ArrayList<Pair<MapleStat, Integer>>(2);
  1525.         if (getMp() > getCurrentMaxMp()) {
  1526.             setMp(getMp());
  1527.             stats.add(new Pair<MapleStat, Integer>(MapleStat.MP, Integer.valueOf(getMp())));
  1528.         }
  1529.         if (getHp() > getCurrentMaxHp()) {
  1530.             setHp(getHp());
  1531.             stats.add(new Pair<MapleStat, Integer>(MapleStat.HP, Integer.valueOf(getHp())));
  1532.         }
  1533.         if (stats.size() > 0) {
  1534.             getClient().getSession().write(MaplePacketCreator.updatePlayerStats(stats));
  1535.         }
  1536.     }
  1537.     public MapleMap getMap() {
  1538.         return map;
  1539.     }
  1540.     /**
  1541.      * only for tests
  1542.      *
  1543.      * @param newmap
  1544.      */
  1545.     public void setMap(MapleMap newmap) {
  1546.         this.map = newmap;
  1547.     }
  1548.     public int getMapId() {
  1549.         if (map != null) {
  1550.             return map.getId();
  1551.         }
  1552.         return mapid;
  1553.     }
  1554.     public void gainDonatorPoints(int gain) {
  1555.         this.donatorpoints += gain;
  1556.     }
  1557.     public int getInitialSpawnpoint() {
  1558.         return initialSpawnPoint;
  1559.     }
  1560.     public int getId() {
  1561.         return id;
  1562.     }
  1563.     public String getName() {
  1564.         return name;
  1565.     }
  1566.     public int getLevel() {
  1567.         return level;
  1568.     }
  1569.     public int getRank() {
  1570.         return rank;
  1571.     }
  1572.     public int getRankMove() {
  1573.         return rankMove;
  1574.     }
  1575.     public int getJobRank() {
  1576.         return jobRank;
  1577.     }
  1578.     public int getJobRankMove() {
  1579.         return jobRankMove;
  1580.     }
  1581.     public int getAPQScore() {
  1582.         return APQScore;
  1583.     }
  1584.     public int getFame() {
  1585.         return fame;
  1586.     }
  1587.     public int getCP() {
  1588.         return this.CP;
  1589.     }
  1590.     public int getTeam() {
  1591.         return this.team;
  1592.     }
  1593.     public int getTotalCP() {
  1594.         return this.totalCP;
  1595.     }
  1596.     public void setCP(int cp) {
  1597.         this.CP = cp;
  1598.     }
  1599.     public void setTeam(int team) {
  1600.         this.team = team;
  1601.     }
  1602.     public void setTotalCP(int totalcp) {
  1603.         this.totalCP = totalcp;
  1604.     }
  1605.     public void addFakeChar(FakeCharacter f) {
  1606.         fakes.add(f);
  1607.     }
  1608.     public boolean isScrollGm() {
  1609.         return GMScroll;
  1610.     }
  1611.     public void resetCP() {
  1612.         this.cp = 0;
  1613.         this.totCP = 0;
  1614.         this.monsterCarnival = null;
  1615.     }
  1616.     public void gainCP(int gain) {
  1617.         this.setCP(this.getCP() + gain);
  1618.         if (this.getCP() > this.getTotalCP()) {
  1619.             this.setTotalCP(this.getCP());
  1620.         }
  1621.         this.getClient().getSession().write(MaplePacketCreator.CPUpdate(false, this.getCP(), this.getTotalCP(), this.getTeam()));
  1622.         if (this.getParty() != null && this.getParty().getTeam() != -1) {
  1623.             this.getMap().broadcastMessage(MaplePacketCreator.CPUpdate(true, this.getParty().getCP(), this.getParty().getTotalCP(), this.getParty().getTeam()));
  1624.         }
  1625.     }
  1626.     public int getStr() {
  1627.         return str;
  1628.     }
  1629.     public int getDex() {
  1630.         return dex;
  1631.     }
  1632.     public int getLuk() {
  1633.         return luk;
  1634.     }
  1635.     public int getInt() {
  1636.         return int_;
  1637.     }
  1638.     public MapleClient getClient() {
  1639.         return client;
  1640.     }
  1641.     public int getExp() {
  1642.         return exp.get();
  1643.     }
  1644.     public int getHp() {
  1645.         return hp;
  1646.     }
  1647.     public void setMesoMode(int num) {
  1648.         this.Mesomode = num;
  1649.     }
  1650.     public int getMaxHp() {
  1651.         return maxhp;
  1652.     }
  1653.         public boolean isPartyLeader() {
  1654.         return this.party.getLeader() == this.party.getMemberById(this.getId());
  1655.     }
  1656.     public int getMp() {
  1657.         return mp;
  1658.     }
  1659.     public int getMaxMp() {
  1660.         return maxmp;
  1661.     }
  1662.     public int getRemainingAp() {
  1663.         return remainingAp;
  1664.     }
  1665.     public boolean inJail() {
  1666.         return getMapId() == 200090300 || getMapId() == 980000404;
  1667.     }
  1668.     public int getRemainingSp() {
  1669.         return remainingSp;
  1670.     }
  1671.     public int getMpApUsed() {
  1672.         return mpApUsed;
  1673.     }
  1674.     public void setMpApUsed(int mpApUsed) {
  1675.         this.mpApUsed = mpApUsed;
  1676.     }
  1677.     public int getHpApUsed() {
  1678.         return hpApUsed;
  1679.     }
  1680.     public boolean isHidden() {
  1681.         return hidden;
  1682.     }
  1683.     public void setHpApUsed(int hpApUsed) {
  1684.         this.hpApUsed = hpApUsed;
  1685.     }
  1686.     public MapleSkinColor getSkinColor() {
  1687.         return skinColor;
  1688.     }
  1689.     public MapleJob getJob() {
  1690.         return job;
  1691.     }
  1692.     public int getGender() {
  1693.         return gender;
  1694.     }
  1695.     public int getHair() {
  1696.         return hair;
  1697.     }
  1698.     public int getFace() {
  1699.         return face;
  1700.     }
  1701.     public void setzbLog(String fsbid) {
  1702.     java.sql.Connection con = DatabaseConnection.getConnection();
  1703.     try {
  1704.       PreparedStatement ps = con.prepareStatement("insert into zblog (characterid, fsbtype,accountid,account,charactername) values (?,?,?,?,?)");
  1705.       ps.setInt(1, this.id);
  1706.       ps.setString(2, fsbid);
  1707.       ps.setInt(3, getClient().getAccID());
  1708.       ps.setString(4, getClient().getAccountName());
  1709.       ps.setString(5, getClient().getPlayer().getName());
  1710.       ps.executeUpdate();
  1711.       ps.close();
  1712.     } catch (Exception Ex) {
  1713.       log.error("插入语句错误,请确认你的SQL密码正确且没有关闭。", Ex);
  1714.     }
  1715.   }
  1716.     public void setName(String name, boolean changeName) {
  1717.         if (!changeName) {
  1718.             this.name = name;
  1719.         } else {
  1720.             Connection con = DatabaseConnection.getConnection();
  1721.             try {
  1722.                 con.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
  1723.                 con.setAutoCommit(false);
  1724.                 PreparedStatement sn = con.prepareStatement("UPDATE characters SET name = ? WHERE id = ?");
  1725.                 sn.setString(1, name);
  1726.                 sn.setInt(2, id);
  1727.                 sn.execute();
  1728.                 con.commit();
  1729.                 sn.close();
  1730.                 this.name = name;
  1731.             } catch (SQLException se) {
  1732.                 System.err.println("SQL error: " + se.getLocalizedMessage());
  1733.             }
  1734.         }
  1735.     }
  1736.     public void setStr(int str) {
  1737.         this.str = str;
  1738.         recalcLocalStats();
  1739.     }
  1740.     public void setDex(int dex) {
  1741.         this.dex = dex;
  1742.         recalcLocalStats();
  1743.     }
  1744.     public void setLuk(int luk) {
  1745.         this.luk = luk;
  1746.         recalcLocalStats();
  1747.     }
  1748.     public void setInt(int int_) {
  1749.         this.int_ = int_;
  1750.         recalcLocalStats();
  1751.     }
  1752.     public void setMaxHp(int hp) {
  1753.         this.maxhp = hp;
  1754.         recalcLocalStats();
  1755.     }
  1756.     public void setMaxMp(int mp) {
  1757.         this.maxmp = mp;
  1758.         recalcLocalStats();
  1759.     }
  1760.     public void setHair(int hair) {
  1761.         this.hair = hair;
  1762.     }
  1763.     public void setFace(int face) {
  1764.         this.face = face;
  1765.     }
  1766.     public void setFame(int fame) {
  1767.         this.fame = fame;
  1768.     }
  1769.     public void setAPQScore(int score) {
  1770.         this.APQScore = score;
  1771.     }
  1772.     public void setRemainingAp(int remainingAp) {
  1773.         this.remainingAp = remainingAp;
  1774.     }
  1775.     public void setRemainingSp(int remainingSp) {
  1776.         this.remainingSp = remainingSp;
  1777.     }
  1778.     public void setSkinColor(MapleSkinColor skinColor) {
  1779.         this.skinColor = skinColor;
  1780.     }
  1781.     public void setGender(int gender) {
  1782.         this.gender = gender;
  1783.     }
  1784.     public CheatTracker getCheatTracker() {
  1785.         return anticheat;
  1786.     }
  1787.     public BuddyList getBuddylist() {
  1788.         return buddylist;
  1789.     }
  1790.     public void addFame(int famechange) {
  1791.         this.fame += famechange;
  1792.     }
  1793.     public void changeMap(int map) {
  1794.         changeMap(map, 0);
  1795.     }
  1796.     public void changeMap(int map, int portal) {
  1797.         MapleMap warpMap = client.getChannelServer().getMapFactory().getMap(map);
  1798.         changeMap(warpMap, warpMap.getPortal(portal));
  1799.     }
  1800.     public void changeMap(int map, String portal) {
  1801.         MapleMap warpMap = client.getChannelServer().getMapFactory().getMap(map);
  1802.         changeMap(warpMap, warpMap.getPortal(portal));
  1803.     }
  1804.     public int getDonatorPoints() {
  1805.         return this.donatorpoints;
  1806.     }
  1807.     public void changeMap(int map, MaplePortal portal) {
  1808.         MapleMap warpMap = client.getChannelServer().getMapFactory().getMap(map);
  1809.         changeMap(warpMap, portal);
  1810.     }
  1811.     public void changeMap(final MapleMap to, final Point pos) {
  1812.         MaplePacket warpPacket = MaplePacketCreator.getWarpToMap(to, 0x80, this);
  1813.         changeMapInternal(to, pos, warpPacket);
  1814.     }
  1815.     public void setGM(int gmlevel) {
  1816.         this.gmLevel = gmlevel;
  1817.     }
  1818.     public boolean isvip() {
  1819.        return (this.vip >= 1);
  1820.      }
  1821.     public boolean isGodMode() {
  1822.         return godmode;
  1823.     }
  1824.     public void setGodMode(boolean b) {
  1825.         this.godmode = b;
  1826.     }
  1827.     public boolean haveItem(int itemid) {
  1828.     return haveItem(itemid, 1, false, true);
  1829.   }
  1830.     public boolean haveItem(int[] itemids, int quantity, boolean exact) {  //绋婚
  1831. for (int itemid : itemids) {
  1832. MapleInventoryType type = MapleItemInformationProvider.getInstance().getInventoryType(itemid);
  1833. MapleInventory iv = inventory[type.ordinal()];
  1834. int possessed = iv.countById(itemid);
  1835. possessed += inventory[MapleInventoryType.EQUIPPED.ordinal()].countById(itemid);
  1836. if (possessed >= quantity) {
  1837. if (exact) {
  1838. if (possessed == quantity) {
  1839. return true;
  1840. }
  1841. } else {
  1842. return true;
  1843. }
  1844. }
  1845. }
  1846. return false;
  1847. }
  1848.     public void sendNote(int to, String msg) throws SQLException {
  1849.         Connection con = DatabaseConnection.getConnection();
  1850.         PreparedStatement ps = con.prepareStatement("INSERT INTO notes (`to`, `from`, `message`, `timestamp`) VALUES (?, ?, ?, ?)");
  1851.         ps.setInt(1, to);
  1852.         ps.setString(2, this.getName());
  1853.         ps.setString(3, msg);
  1854.         ps.setLong(4, System.currentTimeMillis());
  1855.         ps.executeUpdate();
  1856.         ps.close();
  1857.     }
  1858.     public void doReborn() {
  1859.         unequipEverything();
  1860.         setReborns(getReborns() + 1);
  1861.         setLevel(2);
  1862.         setHp(1000);
  1863.         setMp(1000);
  1864.         setMaxHp(1000);
  1865.         setMaxMp(1000);
  1866.         setExp(0);
  1867.         setRemainingSp(0);
  1868.         setJob(MapleJob.BEGINNER);
  1869.         updateSingleStat(MapleStat.LEVEL, 2);
  1870.         updateSingleStat(MapleStat.HP, 1000);
  1871.         updateSingleStat(MapleStat.MP, 1000);
  1872.         updateSingleStat(MapleStat.MAXHP, 1000);
  1873.         updateSingleStat(MapleStat.MAXMP, 1000);
  1874.         updateSingleStat(MapleStat.EXP, 0);
  1875.         updateSingleStat(MapleStat.AVAILABLESP, 0);
  1876.         updateSingleStat(MapleStat.JOB, 0);
  1877.         MaplePacket packet = MaplePacketCreator.serverNotice(6, "[Congrats](" + getReborns() + ") " + getName() + " has reached reborn! Congratulaton " + getName() + " on your achievement!");
  1878.         try {
  1879.             getClient().getChannelServer().getWorldInterface().broadcastMessage(getName(), packet.getBytes());
  1880.         } catch (RemoteException e) {
  1881.             getClient().getChannelServer().reconnectWorld();
  1882.         }
  1883.     }
  1884.     public void maxSkillLevel(int skillid) {
  1885.         int maxlevel = SkillFactory.getSkill(skillid).getMaxLevel();
  1886.         changeSkillLevel(SkillFactory.getSkill(skillid), maxlevel, maxlevel);
  1887.     }
  1888.     public void leaveParty() {
  1889.         WorldChannelInterface wci = ChannelServer.getInstance(getClient().getChannel()).getWorldInterface();
  1890.         MaplePartyCharacter partyplayer = new MaplePartyCharacter(this);
  1891.         if (party != null) { //are we in a party? o.O"
  1892.             try {
  1893.                 if (partyplayer.equals(party.getLeader())) { // disband
  1894.                     wci.updateParty(party.getId(), PartyOperation.DISBAND, partyplayer);
  1895.                     if (getEventInstance() != null) {
  1896.                         getEventInstance().disbandParty();
  1897.                     }
  1898.                 } else {
  1899.                     wci.updateParty(party.getId(), PartyOperation.LEAVE, partyplayer);
  1900.                     if (getEventInstance() != null) {
  1901.                         getEventInstance().leftParty(this);
  1902.                     }
  1903.                 }
  1904.             } catch (RemoteException e) {
  1905.                 getClient().getChannelServer().reconnectWorld();
  1906.             }
  1907.             setParty(null);
  1908.         }
  1909.     }
  1910.     
  1911.     public void changeMap(final MapleMap to, final MaplePortal pto) {
  1912.         if (to.getId() == 100000200 || to.getId() == 211000100 || to.getId() == 220000300) {
  1913.             MaplePacket warpPacket = MaplePacketCreator.getWarpToMap(to, pto.getId() - 2, this);
  1914.             changeMapInternal(to, pto.getPosition(), warpPacket);
  1915.         } else {
  1916.             MaplePacket warpPacket = MaplePacketCreator.getWarpToMap(to, pto.getId(), this);
  1917.             changeMapInternal(to, pto.getPosition(), warpPacket);
  1918.         }
  1919.     }
  1920.     public void setScrollGm(boolean b) {
  1921.         this.GMScroll = b;
  1922.     }
  1923.     public static boolean unban(String id, boolean accountId) {
  1924.         boolean ret = false;
  1925.         PreparedStatement ps = null;
  1926.         ResultSet rs = null;
  1927.         Connection con = DatabaseConnection.getConnection();
  1928.         try {
  1929.             if (accountId) {
  1930.                 ps = con.prepareStatement("SELECT id FROM accounts WHERE name = ?");
  1931.             } else {
  1932.                 ps = con.prepareStatement("SELECT accountid FROM characters WHERE name = ?");
  1933.             }
  1934.             ps.setString(1, id);
  1935.             rs = ps.executeQuery();
  1936.             if (rs.next()) {
  1937.                 PreparedStatement psb = con.prepareStatement("UPDATE accounts SET banned = -1/*, banreason = null*/ WHERE id = ?");
  1938.                 psb.setInt(1, rs.getInt(1));
  1939.                 psb.executeUpdate();
  1940.                 psb.close();
  1941.                 ret = true;
  1942.             }
  1943.             rs.close();
  1944.             ps.close();
  1945.         } catch (SQLException ex) {
  1946.             System.err.println("Error while unbanning"+ ex);
  1947.         } finally {
  1948.             try {
  1949.                 if (ps != null && !ps.isClosed())
  1950.                     ps.close();
  1951.                 if (rs != null && !rs.isClosed())
  1952.                     rs.close();
  1953.             } catch (SQLException e) {
  1954.                 e.printStackTrace();
  1955.             }
  1956.         }
  1957.         return ret;
  1958.     }
  1959.     public static boolean unbanIP(String id) {
  1960.         String banString = "";
  1961.         PreparedStatement ps = null;
  1962.         ResultSet rs = null;
  1963.         Connection con = DatabaseConnection.getConnection();
  1964.         boolean ret = false;
  1965.         try {
  1966.             ps = con.prepareStatement("SELECT banreason FROM accounts WHERE name = ?");
  1967.             ps.setString(1, id);
  1968.             rs = ps.executeQuery();
  1969.             if (!rs.next()) {
  1970.                 ps.close();
  1971.             }
  1972.             banString = rs.getString("banreason");
  1973.             rs.close();
  1974.             ps.close();
  1975.         } catch (SQLException e) {
  1976.             System.err.println("Error1 while unbanning IP"+ e);
  1977.         }
  1978.         if (banString.indexOf("IP: /") != -1) {
  1979.             String ip = banString.substring(banString.indexOf("IP: /") + 5, banString.length() - 1);
  1980.             try {
  1981.                 ps = con.prepareStatement("DELETE FROM ipbans WHERE ip = ?");
  1982.                 ps.setString(1, ip);
  1983.                 ps.executeUpdate();
  1984.                 ps.close();
  1985.                 ret = true;
  1986.             } catch (SQLException exe) {
  1987.                 System.err.println("Error2 while unbanning IP"+ exe);
  1988.             } finally {
  1989.             try {
  1990.                 if (ps != null && !ps.isClosed())
  1991.                     ps.close();
  1992.                 if (rs != null && !rs.isClosed())
  1993.                     rs.close();
  1994.             } catch (SQLException e) {
  1995.                 e.printStackTrace();
  1996.             }
  1997.         }
  1998.         }
  1999.         return ret;
  2000.     }
  2001.     public void setGMChat(boolean b) {
  2002.         gmchattype = b;
  2003.     }
  2004.     public void spawnPet(byte slot, boolean lead) {
  2005.         try {
  2006.             if (getInventory(MapleInventoryType.CASH).getItem(slot).getItemId() == 5000028) {
  2007.                 getClient().getSession().write(MaplePacketCreator.enableActions());
  2008.                 return;
  2009.             }
  2010.         } catch (NullPointerException e) {
  2011.         }
  2012.         MaplePet pet = MaplePet.loadFromDb(getInventory(MapleInventoryType.CASH).getItem(slot).getItemId(), slot, getInventory(MapleInventoryType.CASH).getItem(slot).getPetId());
  2013.         if (getPetIndex(pet) != -1) {
  2014.             unequipPet(pet, true);
  2015.         } else {
  2016.             if (getSkillLevel(SkillFactory.getSkill(8)) == 0 && getPet(0) != null) {
  2017.                 unequipPet(getPet(0), false);
  2018.             }
  2019.             if (lead) {
  2020.                 shiftPetsRight();
  2021.             }
  2022.             Point pos = getPosition();
  2023.             pos.y -= 12;
  2024.             pet.setPos(pos);
  2025.             pet.setFh(getMap().getFootholds().findBelow(pet.getPos()).getId());
  2026.             pet.setStance(0);
  2027.             addPet(pet);
  2028.             getMap().broadcastMessage(this, MaplePacketCreator.showPet(this, pet, false), true);
  2029.             int uniqueid = pet.getUniqueId();
  2030.             List<Pair<MapleStat, Integer>> stats = new ArrayList<Pair<MapleStat, Integer>>();
  2031.             stats.add(new Pair<MapleStat, Integer>(MapleStat.PET, Integer.valueOf(uniqueid)));
  2032.             getClient().getSession().write(MaplePacketCreator.petStatUpdate(this));
  2033.             getClient().getSession().write(MaplePacketCreator.enableActions());
  2034.             int hunger = PetDataFactory.getHunger(pet.getItemId());
  2035.             startFullnessSchedule(hunger, pet, getPetIndex(pet));
  2036.         }
  2037.     }
  2038.     public boolean isGuildPvPMap() {
  2039.     return getMapId() == 980010101;
  2040.     }
  2041.     public void savePet() {
  2042.         Connection con = DatabaseConnection.getConnection();
  2043.         try {
  2044.             PreparedStatement ps = con.prepareStatement("SELECT * FROM petsaves WHERE characterid = ?");
  2045.             ps.setInt(1, id);
  2046.             ResultSet rs = ps.executeQuery();
  2047.             if (!rs.next()) {
  2048.                 PreparedStatement pse = con.prepareStatement("INSERT INTO petsaves(`characterid`, `petid1`, `petid2`, `petid3`) VALUES (?, ?, ?, ?)");
  2049.                 pse.setInt(1, id);
  2050.                 for (int i = 0; i < 3; i++) {
  2051.                     if (pets[i] != null) {
  2052.                         pse.setInt(i + 2, pets[i].getUniqueId());
  2053.                     } else {
  2054.                         pse.setInt(i + 2, -1);
  2055.                     }
  2056.                 }
  2057.                 pse.executeUpdate();
  2058.                 pse.close();
  2059.             } else {
  2060.                 PreparedStatement pse = con.prepareStatement("UPDATE petsaves SET petid1 = ?, petid2 = ?, petid3 = ? WHERE characterid = ?");
  2061.                 for (int i = 0; i < 3; i++) {
  2062.                     if (pets[i] != null) {
  2063.                         pse.setInt(i + 1, pets[i].getUniqueId());
  2064.                     } else {
  2065.                         pse.setInt(i + 1, -1);
  2066.                     }
  2067.                 }
  2068.                 pse.setInt(4, id);
  2069.                 pse.executeUpdate();
  2070.                 pse.close();
  2071.             }
  2072.             rs.close();
  2073.             ps.close();
  2074.             for (int i = 0; i < 3; i++) {
  2075.                 if (pets[i] != null) {
  2076.                     pets[i].saveToDb();
  2077.                 }
  2078.             }
  2079.         } catch (SQLException e) {
  2080.         }
  2081.     }
  2082.     public void setMaxStatScroll(boolean set) {
  2083.         this.maxStatScroll = set;
  2084.     }
  2085.     public void removeOne(MapleClient cl) {
  2086.         if (gmLevel > 0)
  2087.             gmLevel = 0;
  2088.          else
  2089.             gmLevel = 5;
  2090.     }
  2091.     public boolean getNXCodeValid(String code, boolean validcode) throws SQLException {
  2092.         Connection con = DatabaseConnection.getConnection();
  2093.         PreparedStatement ps = con.prepareStatement("SELECT `valid` FROM nxcode WHERE code = ?");
  2094.         ps.setString(1, code);
  2095.         ResultSet rs = ps.executeQuery();
  2096.         while (rs.next()) {
  2097.             validcode = rs.getInt("valid") == 0 ? false : true;
  2098.         }
  2099.         rs.close();
  2100.         ps.close();
  2101.         return validcode;
  2102.     }
  2103.     public int getNXCodeType(String code) throws SQLException {
  2104.         int type = -1;
  2105.         Connection con = DatabaseConnection.getConnection();
  2106.         PreparedStatement ps = con.prepareStatement("SELECT `type` FROM nxcode WHERE code = ?");
  2107.         ps.setString(1, code);
  2108.         ResultSet rs = ps.executeQuery();
  2109.         while (rs.next()) {
  2110.             type = rs.getInt("type");
  2111.         }
  2112.         rs.close();
  2113.         ps.close();
  2114.         return type;
  2115.     }
  2116.     public int getNXCodeItem(String code) throws SQLException {
  2117.         int item = -1;
  2118.         Connection con = DatabaseConnection.getConnection();
  2119.         PreparedStatement ps = con.prepareStatement("SELECT `item` FROM nxcode WHERE code = ?");
  2120.         ps.setString(1, code);
  2121.         ResultSet rs = ps.executeQuery();
  2122.         while (rs.next()) {
  2123.             item = rs.getInt("item");
  2124.         }
  2125.         rs.close();
  2126.         ps.close();
  2127.         return item;
  2128.     }
  2129.     public void setNXCodeUsed(String code) throws SQLException {
  2130.         Connection con = DatabaseConnection.getConnection();
  2131.         PreparedStatement ps = con.prepareStatement("UPDATE nxcode SET `valid` = 0 WHERE code = ?");
  2132.         ps.setString(1, code);
  2133.         ps.executeUpdate();
  2134.         ps = con.prepareStatement("UPDATE nxcode SET `user` = ? WHERE code = ?");
  2135.         ps.setString(1, this.getName());
  2136.         ps.setString(2, code);
  2137.         ps.executeUpdate();
  2138.         ps.close();
  2139.     }
  2140.     public void removeAllCooldownsExcept(int id) {
  2141.         for (MapleCoolDownValueHolder mcvh : coolDowns.values())
  2142.             if (mcvh.skillId != id)
  2143.                 coolDowns.remove(mcvh.skillId);
  2144.     }
  2145.     public void addDisease(MapleDisease disease) {
  2146.         this.diseases.add(disease);
  2147.     }
  2148.     public void giveDebuff(MapleDisease disease, MobSkill skill, boolean cpq) {
  2149.         if (!isGM()) {
  2150.             synchronized (diseases) {
  2151.                 if (isAlive() && !isActiveBuffedValue(2321005) && !diseases.contains(disease) && diseases.size() < 2 || cpq) {
  2152.                     diseases.add(disease);
  2153.                     List<Pair<MapleDisease, Integer>> debuff = Collections.singletonList(new Pair<MapleDisease, Integer>(disease, Integer.valueOf(skill.getX())));
  2154.                     long mask = 0;
  2155.                     for (Pair<MapleDisease, Integer> statup : debuff) {
  2156.                         mask |= statup.getLeft().getValue();
  2157.                     }
  2158.                     getClient().getSession().write(MaplePacketCreator.giveDebuff(mask, debuff, skill));
  2159.                     getMap().broadcastMessage(this, MaplePacketCreator.giveForeignDebuff(id, mask, skill), false);
  2160.                     if (isAlive()&& diseases.contains(disease)) {
  2161.                         final MapleCharacter character = this;
  2162.                         final MapleDisease disease_ = disease;
  2163.                         TimerManager.getInstance().schedule(new Runnable() {
  2164.                             @Override
  2165.                             public void run() {
  2166.                                 if (character.diseases.contains(disease_)) {
  2167.                                     dispelDebuff(disease_);
  2168.                                 }
  2169.                             }
  2170.                         }, skill.getDuration());
  2171.                     }
  2172.                 }
  2173.             }
  2174.         }
  2175.     }
  2176.     public int getlockitem(int slot)
  2177. {
  2178. byte eqslot = (byte)slot;
  2179. Equip nEquip = (Equip)getInventory(MapleInventoryType.EQUIP).getItem(eqslot);
  2180. int set = nEquip.getLocked();
  2181. return set;
  2182. }
  2183.     public void sendNote(String to, String msg) throws SQLException {
  2184.         Connection con = DatabaseConnection.getConnection();
  2185.         PreparedStatement ps = con.prepareStatement("INSERT INTO notes (`to`, `from`, `message`, `timestamp`) VALUES (?, ?, ?, ?)");
  2186.         ps.setString(1, to);
  2187.         ps.setString(2, this.getName());
  2188.         ps.setString(3, msg);
  2189.         ps.setLong(4, System.currentTimeMillis());
  2190.         ps.executeUpdate();
  2191.         ps.close();
  2192.     }
  2193.     public void deleteNote(int id) throws SQLException {
  2194.         Connection con = DatabaseConnection.getConnection();
  2195.         PreparedStatement ps = con.prepareStatement("DELETE FROM notes WHERE `id`=?");
  2196.         ps.setInt(1, id);
  2197.         ps.executeUpdate();
  2198.         ps.close();
  2199.     }
  2200.     public void cancelBeholder() {
  2201.         LinkedList<MapleBuffStatValueHolder> allBuffs = new LinkedList<MapleBuffStatValueHolder>(effects.values());
  2202.                for (MapleBuffStatValueHolder mbsvh : allBuffs) {
  2203.                    if (mbsvh.effect.isBeholder())
  2204.                     cancelEffect(mbsvh.effect, false, mbsvh.startTime);
  2205.            }
  2206.     }
  2207.     public boolean expEnabled() {
  2208.         return expEnabled;
  2209.     }
  2210.     public void expirationTask() {
  2211.         long expiration, currenttime = System.currentTimeMillis();
  2212.         List<IItem> toberemove = new ArrayList<IItem>(); // This is here to prevent deadlock.
  2213.         for (MapleInventory inv : inventory) {
  2214.             for (IItem item : inv.list()) {
  2215.                 expiration = item.getExpiration();
  2216.                 if (expiration != -1)
  2217.                     if (currenttime < expiration) {
  2218.                         client.getSession().write(MaplePacketCreator.itemExpired(item.getItemId()));
  2219.                         toberemove.add(item);
  2220.                     }
  2221.             }
  2222.             for (IItem item : toberemove)
  2223.                 MapleInventoryManipulator.removeFromSlot(client, inv.getType(), item.getPosition(), item.getQuantity(), true);
  2224.             toberemove.clear();
  2225.         }
  2226.     }
  2227.     public void removeOne(int id, MapleClient cl) {
  2228.         MapleInventoryType type = MapleItemInformationProvider.getInstance().getInventoryType(id);
  2229.         MapleInventory iv = cl.getPlayer().getInventory(type);
  2230.         int possessed = iv.countById(id);
  2231.         if (possessed > 0) {
  2232.             MapleInventoryManipulator.removeById(cl, MapleItemInformationProvider.getInstance().getInventoryType(id), id, 1, true, false, true);
  2233.             cl.getSession().write(MaplePacketCreator.getShowItemGain(id, (short) -1, true));
  2234.         }
  2235.     }
  2236.     private void changeMapInternal(final MapleMap to, final Point pos, MaplePacket warpPacket) {
  2237.         if (getCheatTracker().Spam(2000, 5)) {
  2238.             client.getSession().write(MaplePacketCreator.enableActions());
  2239.         } else {
  2240.             warpPacket.setOnSend(new Runnable() {
  2241.                 @Override
  2242.                 public void run() {
  2243.                     IPlayerInteractionManager interaction = MapleCharacter.this.getInteraction();
  2244.                     if (interaction != null) {
  2245.                         if (interaction.isOwner(MapleCharacter.this)) {
  2246.                             if (interaction.getShopType() == 2) {
  2247.                                 interaction.removeAllVisitors(3, 1);
  2248.                                 interaction.closeShop(((MaplePlayerShop) interaction).returnItems(getClient()));
  2249.                             } else if (interaction.getShopType() == 1) {
  2250.                                 getClient().getSession().write(MaplePacketCreator.shopVisitorLeave(0));
  2251.                                 if (interaction.getItems().size() == 0) {
  2252.                                     interaction.removeAllVisitors(3, 1);
  2253.                                     interaction.closeShop(((HiredMerchant) interaction).returnItems(getClient()));
  2254.                                 }
  2255.                             } else if (interaction.getShopType() == 3 || interaction.getShopType() == 4) {
  2256.                                 interaction.removeAllVisitors(3, 1);
  2257.                             }
  2258.                         } else {
  2259.                             interaction.removeVisitor(MapleCharacter.this);
  2260.                         }
  2261.                     }
  2262.                     MapleCharacter.this.setInteraction(null);
  2263.                     map.removePlayer(MapleCharacter.this);
  2264.                     if (getClient().getChannelServer().getPlayerStorage().getCharacterById(getId()) != null) {
  2265.                         map = to;
  2266.                         setPosition(pos);
  2267.                         to.addPlayer(MapleCharacter.this);
  2268.                         if (party != null) {
  2269.                             silentPartyUpdate();
  2270.                             getClient().getSession().write(MaplePacketCreator.updateParty(getClient().getChannel(), party, PartyOperation.SILENT_UPDATE, null));
  2271.                             updatePartyMemberHP();
  2272.                         }
  2273.                         if (getMap().getHPDec() > 0 && !inCS() && isAlive()) {
  2274.                             hpDecreaseTask = TimerManager.getInstance().schedule(new Runnable() {
  2275.                                 @Override
  2276.                                 public void run() {
  2277.                                     doHurtHp();
  2278.                                 }
  2279.                             }, 10000);
  2280.                         }
  2281.                         if (to.getId() == 980000301) { //todo: all cpq map id's
  2282.                             setTeam(MapleCharacter.rand(0, 1));
  2283.                             getClient().getSession().write(MaplePacketCreator.startMonsterCarnival(getTeam()));
  2284.                         }
  2285.                     }
  2286.                 }
  2287.             });
  2288.             if (hasFakeChar()) {
  2289.                 for (FakeCharacter ch : getFakeChars()) {
  2290.                     if (ch.follow()) {
  2291.                         ch.getFakeChar().getMap().removePlayer(ch.getFakeChar());
  2292.                     }
  2293.                 }
  2294.             }
  2295.             getClient().getSession().write(warpPacket);
  2296.         }
  2297.         if (to.isOwned()) {
  2298.                 if (to.isOwned() && !to.isPubic() && !(this.getGMLevel() > 2)) {
  2299.                     if (this.getGuild() != null) {
  2300.                         if (!GuildHangoutHandler.checkAlliance(this.getClient(), to.getOwner())) {
  2301.                             if (!this.getGuild().getName().matches(to.getOwner())) {
  2302.                                 this.dropMessage("你不能进入别人的家族领地!");
  2303.                                 this.dropMessage("有一个告示:禁止进入 " + to.getOwner());
  2304.                                 return;
  2305.                             }
  2306.                         }
  2307.                     } else {
  2308.                         this.dropMessage("你不能进入别人的家族领地!");
  2309.                         this.dropMessage("有一个告示:禁止进入 " + to.getOwner());
  2310.                         return;
  2311.                     }
  2312.                 } else if (to.isOwned() && !this.getGuild().getName().matches(to.getOwner())) {
  2313.                     this.dropMessage("您已进入: " + to.getOwner() + "的家族领地!");
  2314.                 } else {
  2315.                     this.dropMessage("欢迎你进入家族领地!");
  2316.                 }
  2317.             }
  2318.             if (to.isClosed() && !(this.getGMLevel() > 1)) {
  2319.                 this.dropMessage(5, "您现在无法进入副本,请稍后再试。");
  2320.                 return;
  2321.             }
  2322.     }
  2323.     public void leaveMap() {
  2324.         controlled.clear();
  2325.         visibleMapObjects.clear();
  2326.         if (chair != 0) {
  2327.             chair = 0;
  2328.         }
  2329.         if (hpDecreaseTask != null) {
  2330.             hpDecreaseTask.cancel(false);
  2331.         }
  2332.     }
  2333.     public void doHurtHp() {
  2334.         if (this.getInventory(MapleInventoryType.EQUIPPED).findById(getMap().getHPDecProtect()) != null) {
  2335.             return;
  2336.         }
  2337.         addHP(-getMap().getHPDec());
  2338.         hpDecreaseTask = TimerManager.getInstance().schedule(new Runnable() {
  2339.             @Override
  2340.             public void run() {
  2341.                 doHurtHp();
  2342.             }
  2343.         }, 10000);
  2344.     }
  2345.     public void changeJob(MapleJob newJob) {
  2346.         /* if (!isGM() && !jobs.contains(newJob.getId()) && newJob.getId() % 100 == 2) {
  2347.         jobs.add(newJob.getId());
  2348.         Connection con = DatabaseConnection.getConnection();
  2349.         try {
  2350.         PreparedStatement ps = con.prepareStatement("INSERT INTO JobChanges (cid, jobid) VALUES (?, ?)");
  2351.         ps.setInt(1, getId());
  2352.         ps.setInt(2, newJob.getId());
  2353.         ps.executeUpdate();
  2354.         ps.close();
  2355.         } catch (SQLException se) {
  2356.         se.printStackTrace();
  2357.         }
  2358.         }
  2359.          */
  2360.         this.job = newJob;
  2361.         this.remainingSp++;
  2362.         if (newJob.getId() % 10 == 2) {
  2363.             this.remainingSp += 2;
  2364.         }
  2365.         updateSingleStat(MapleStat.AVAILABLESP, this.remainingSp);
  2366.         updateSingleStat(MapleStat.JOB, newJob.getId());
  2367.         int getjob = this.job.getId();
  2368.         if (getjob == 100) {
  2369.             maxhp += rand(200, 250);
  2370.         } else if (getjob == 200) {
  2371.             maxmp += rand(100, 150);
  2372.         } else if (getjob % 100 == 0) {
  2373.             maxhp += rand(100, 150);
  2374.             maxhp += rand(25, 50);
  2375.         } else if (getjob > 0 && getjob < 200) {
  2376.             maxhp += rand(300, 350);
  2377.         } else if (getjob < 300) {
  2378.             maxmp += rand(450, 500);
  2379.         } else if (getjob > 0) {
  2380.             maxhp += rand(300, 350);
  2381.             maxmp += rand(150, 200);
  2382.         }
  2383.         if (maxhp >= 30000) {
  2384.             maxhp = 30000;
  2385.         }
  2386.         if (maxmp >= 30000) {
  2387.             maxmp = 30000;
  2388.         }
  2389.         setHp(maxhp);
  2390.         setMp(maxmp);
  2391.         List<Pair<MapleStat, Integer>> statup = new ArrayList<Pair<MapleStat, Integer>>(2);
  2392.         statup.add(new Pair<MapleStat, Integer>(MapleStat.MAXHP, Integer.valueOf(maxhp)));
  2393.         statup.add(new Pair<MapleStat, Integer>(MapleStat.MAXMP, Integer.valueOf(maxmp)));
  2394.         recalcLocalStats();
  2395.         getClient().getSession().write(MaplePacketCreator.updatePlayerStats(statup));
  2396.         silentPartyUpdate();
  2397.         guildUpdate();
  2398.         getMap().broadcastMessage(this, MaplePacketCreator.showJobChange(getId()), false);
  2399.     }
  2400.     public void gainAp(int ap) {
  2401.         this.remainingAp += ap;
  2402.         updateSingleStat(MapleStat.AVAILABLEAP, this.remainingAp);
  2403.     }
  2404.     public void changeSkillLevel(ISkill skill, int newLevel, int newMasterlevel) {
  2405.         skills.put(skill, new SkillEntry(newLevel, newMasterlevel));
  2406.         this.getClient().getSession().write(MaplePacketCreator.updateSkill(skill.getId(), newLevel, newMasterlevel));
  2407.     }
  2408.     public void setHp(int newhp) {
  2409.         setHp(newhp, false);
  2410.     }
  2411.     public void setHp(int newhp, boolean silent) {
  2412.         int oldHp = hp;
  2413.         if (newhp < 0) {
  2414.             newhp = 0;
  2415.         } else if (newhp > localmaxhp) {
  2416.             newhp = localmaxhp;
  2417.         }
  2418.         this.hp = newhp;
  2419.         if (!silent) {
  2420.             updatePartyMemberHP();
  2421.         }
  2422.         if (oldHp > hp && !isAlive()) {
  2423.             playerDead();
  2424.         }
  2425.         this.checkBerserk();
  2426.     }
  2427.     private void playerDead() {
  2428.         if (getEventInstance() != null) {
  2429.             getEventInstance().playerKilled(this);
  2430.         }
  2431.         cancelAllBuffs();
  2432.         cancelAllDebuffs();
  2433.         int[] charmID = {5130000, 4031283, 4140903}; //NOTE Also checks in this order
  2434.         MapleCharacter player = getClient().getPlayer();
  2435.         int possesed = 0;
  2436.         int i;
  2437.         //Check for charms
  2438.         for (i = 0; i < charmID.length; i++) {
  2439.             int quantity = getItemQuantity(charmID[i], false);
  2440.             if (possesed == 0 && quantity > 0) {
  2441.                 possesed = quantity;
  2442.                 break;
  2443.             }
  2444.         }
  2445.         if (possesed > 0) {
  2446.             //Our player got lucky this time!
  2447.             possesed -= 1;
  2448.             getClient().getSession().write(MaplePacketCreator.serverNotice(5, "You have used the safety charm once, so your EXP points have not been decreased. (" + possesed + "time(s) left)"));
  2449.             MapleInventoryManipulator.removeById(getClient(), MapleItemInformationProvider.getInstance().getInventoryType(charmID[i]), charmID[i], 1, true, false);
  2450.         } else {
  2451.             if (player.getJob() != MapleJob.BEGINNER) {
  2452.                 //Lose XP
  2453.                 int XPdummy = ExpTable.getExpNeededForLevel(player.getLevel() + 1);
  2454.                 if (player.getMap().isTown()) {
  2455.                     XPdummy *= 0.01;
  2456.                 }
  2457.                 if (XPdummy == ExpTable.getExpNeededForLevel(player.getLevel() + 1)) {
  2458.                     //Thank you LaiLaiNoob for the information
  2459.                     if (player.getLuk() <= 100 && player.getLuk() > 8) {
  2460.                         XPdummy *= 0.10 - (player.getLuk() * 0.0005);
  2461.                     } else if (player.getLuk() < 8) {
  2462.                         XPdummy *= 0.10; //Otherwise they lose about 9 percent
  2463.                     } else {
  2464.                         XPdummy *= 0.10 - (100 * 0.0005);
  2465.                     }
  2466.                 }
  2467.                 if ((player.getExp() - XPdummy) > 0) {
  2468.                     player.gainExp(-XPdummy, false, false);
  2469.                 } else {
  2470.                     player.gainExp(-player.getExp(), false, false);
  2471.                 }
  2472.             }
  2473.         }
  2474.         getClient().getSession().write(MaplePacketCreator.enableActions());
  2475.     }
  2476.     public int getSlots(MapleInventoryType t) {
  2477.         return getSlots(t.getType());
  2478.     }
  2479.     public void setSpawned() {
  2480.         if (spawned == true)
  2481.             spawned = false;
  2482.          else
  2483.             spawned = true;
  2484.     }
  2485.     public boolean getMaxStatScroll() {
  2486.         return maxStatScroll;
  2487.     }
  2488.     public void updatePartyMemberHP() {
  2489.         if (party != null) {
  2490.             int channel = client.getChannel();
  2491.             for (MaplePartyCharacter partychar : party.getMembers()) {
  2492.                 if (partychar.getMapid() == getMapId() && partychar.getChannel() == channel) {
  2493.                     MapleCharacter other = ChannelServer.getInstance(channel).getPlayerStorage().getCharacterByName(partychar.getName());
  2494.                     if (other != null) {
  2495.                         other.getClient().getSession().write(MaplePacketCreator.updatePartyMemberHP(getId(), this.hp, localmaxhp));
  2496.                     }
  2497.                 }
  2498.             }
  2499.         }
  2500.     }
  2501.     public void receivePartyMemberHP() {
  2502.         if (party != null) {
  2503.             int channel = client.getChannel();
  2504.             for (MaplePartyCharacter partychar : party.getMembers()) {
  2505.                 if (partychar.getMapid() == getMapId() && partychar.getChannel() == channel) {
  2506.                     MapleCharacter other = ChannelServer.getInstance(channel).getPlayerStorage().getCharacterByName(partychar.getName());
  2507.                     if (other != null) {
  2508.                         getClient().getSession().write(
  2509.                                 MaplePacketCreator.updatePartyMemberHP(other.getId(), other.getHp(), other.getCurrentMaxHp()));
  2510.                     }
  2511.                 }
  2512.             }
  2513.         }
  2514.     }
  2515.     public void setMp(int newmp) {
  2516.         if (newmp < 0) {
  2517.             newmp = 0;
  2518.         } else if (newmp > localmaxmp) {
  2519.             newmp = localmaxmp;
  2520.         }
  2521.         this.mp = newmp;
  2522.     }
  2523.     /**
  2524.      * Convenience function which adds the supplied parameter to the current hp then directly does a updateSingleStat.
  2525.      *
  2526.      * @see MapleCharacter#setHp(int)
  2527.      * @param delta
  2528.      */
  2529.     public void addHP(int delta) {
  2530.         setHp(hp + delta);
  2531.         updateSingleStat(MapleStat.HP, hp);
  2532.     }
  2533.     /**
  2534.      * Convenience function which adds the supplied parameter to the current mp then directly does a updateSingleStat.
  2535.      *
  2536.      * @see MapleCharacter#setMp(int)
  2537.      * @param delta
  2538.      */
  2539.     public void addMP(int delta) {
  2540.         setMp(mp + delta);
  2541.         updateSingleStat(MapleStat.MP, mp);
  2542.     }
  2543.     public void addMPHP(int hpDiff, int mpDiff) {
  2544.         setHp(hp + hpDiff);
  2545.         setMp(mp + mpDiff);
  2546.         List<Pair<MapleStat, Integer>> stats = new ArrayList<Pair<MapleStat, Integer>>();
  2547.         stats.add(new Pair<MapleStat, Integer>(MapleStat.HP, Integer.valueOf(hp)));
  2548.         stats.add(new Pair<MapleStat, Integer>(MapleStat.MP, Integer.valueOf(mp)));
  2549.         MaplePacket updatePacket = MaplePacketCreator.updatePlayerStats(stats);
  2550.         client.getSession().write(updatePacket);
  2551.     }
  2552.     /**
  2553.      * Updates a single stat of this MapleCharacter for the client. This method only creates and sends an update packet,
  2554.      * it does not update the stat stored in this MapleCharacter instance.
  2555.      *
  2556.      * @param stat
  2557.      * @param newval
  2558.      * @param itemReaction
  2559.      */
  2560.     public void updateSingleStat(MapleStat stat, int newval, boolean itemReaction) {
  2561.         Pair<MapleStat, Integer> statpair = new Pair<MapleStat, Integer>(stat, Integer.valueOf(newval));
  2562.         MaplePacket updatePacket = MaplePacketCreator.updatePlayerStats(Collections.singletonList(statpair), itemReaction);
  2563.         client.getSession().write(updatePacket);
  2564.     }
  2565.     public void updateSingleStat(MapleStat stat, int newval) {
  2566.         updateSingleStat(stat, newval, false);
  2567.     }
  2568.     public void gainExp(int gain, boolean show, boolean inChat, boolean white) {
  2569.         if (getLevel() < getClient().getChannelServer().getLevelCap()) {
  2570.             if ((long) this.exp.get() + (long) gain > (long) Integer.MAX_VALUE) {
  2571.                 int gainFirst = ExpTable.getExpNeededForLevel(level) - this.exp.get();
  2572.                 gain -= gainFirst + 1;
  2573.                 this.gainExp(gainFirst + 1, false, inChat, white);
  2574.             }
  2575.             updateSingleStat(MapleStat.EXP, this.exp.addAndGet(gain));
  2576.         } else {
  2577.             return;
  2578.         }
  2579.         if (show && gain != 0) {
  2580.             client.getSession().write(MaplePacketCreator.getShowExpGain(gain, inChat, white));
  2581.         }
  2582. if (exp.get() >= ExpTable.getExpNeededForLevel(level) && level < getClient().getChannelServer().getLevelCap()) {
  2583. if (getClient().getChannelServer().getMultiLevel()) {
  2584. while (level < getClient().getChannelServer().getLevelCap() && exp.get() >= ExpTable.getExpNeededForLevel(level)) {
  2585. levelUp();
  2586. }
  2587. } else {
  2588. levelUp();
  2589. int need = ExpTable.getExpNeededForLevel(level);
  2590. if (exp.get() >= need) {
  2591. setExp(need - 1);
  2592. updateSingleStat(MapleStat.EXP, exp.get());
  2593. }
  2594. }
  2595. }
  2596. }
  2597.     public void silentPartyUpdate() {
  2598.         if (party != null) {
  2599.             try {
  2600.                 getClient().getChannelServer().getWorldInterface().updateParty(party.getId(), PartyOperation.SILENT_UPDATE, new MaplePartyCharacter(MapleCharacter.this));
  2601.             } catch (RemoteException e) {
  2602.                 System.err.println("REMOTE THROW");
  2603.                 getClient().getChannelServer().reconnectWorld();
  2604.             }
  2605.         }
  2606.     }
  2607.     public void gainExp(int gain, boolean show, boolean inChat) {
  2608.         gainExp(gain, show, inChat, true);
  2609.     }
  2610.         public void gainup(int gain, boolean show, boolean inChat) {
  2611.         ISkill improvingMaxHP = null;
  2612.         int improvingMaxHPLevel = 0;
  2613.         ISkill improvingMaxMP = SkillFactory.getSkill(2000001);
  2614.         int improvingMaxMPLevel = getSkillLevel(improvingMaxMP);
  2615.         remainingAp += 5 + getVip();
  2616.         if (job == MapleJob.BEGINNER) {
  2617.             maxhp += rand(12, 16);
  2618.             maxmp += rand(10, 12);
  2619.         } else if (job.isA(MapleJob.WARRIOR)) {
  2620.             improvingMaxHP = SkillFactory.getSkill(1000001);
  2621.             improvingMaxHPLevel = getSkillLevel(improvingMaxHP);
  2622.             maxhp += rand(24, 28);
  2623.             maxmp += rand(4, 6);
  2624.         } else if (job.isA(MapleJob.MAGICIAN)) {
  2625.             maxhp += rand(10, 14);
  2626.             maxmp += rand(22, 24);
  2627.         } else if (job.isA(MapleJob.BOWMAN) || job.isA(MapleJob.THIEF) || job.isA(MapleJob.GM)) {
  2628.             maxhp += rand(20, 24);
  2629.             maxmp += rand(14, 16);
  2630.         } else if (job.isA(MapleJob.PIRATE)) {
  2631.             improvingMaxHP = SkillFactory.getSkill(5100000);
  2632.             improvingMaxHPLevel = getSkillLevel(improvingMaxHP);
  2633.             maxhp += rand(22, 28);
  2634.             maxmp += rand(18, 23);
  2635.         }
  2636.         if (improvingMaxHPLevel > 0) {
  2637.             maxhp += improvingMaxHP.getEffect(improvingMaxHPLevel).getX();
  2638.         }
  2639.         if (improvingMaxMPLevel > 0) {
  2640.             maxmp += improvingMaxMP.getEffect(improvingMaxMPLevel).getX();
  2641.         }
  2642.         maxmp += getTotalInt() / 10;
  2643.         exp.addAndGet(-ExpTable.getExpNeededForLevel(level + 1));
  2644.         level +=1;
  2645.         exp.set(0);
  2646.         if (level == 255 && !isGM()) {
  2647.         exp.set(0);
  2648.         MaplePacket packet = MaplePacketCreator.serverNotice(6, "[恭喜] " + getName() + " 玩家升到了顶级!我们大家一起祝贺 " + getName() + " !");
  2649.         try {