CharSelectionInfo.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /*
  2. * Copyright (C) 2004-2015 L2J Server
  3. *
  4. * This file is part of L2J Server.
  5. *
  6. * L2J Server is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * L2J Server 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 GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package com.l2jserver.gameserver.network.serverpackets;
  20. import java.sql.Connection;
  21. import java.sql.PreparedStatement;
  22. import java.sql.ResultSet;
  23. import java.util.ArrayList;
  24. import java.util.List;
  25. import java.util.logging.Level;
  26. import java.util.logging.Logger;
  27. import com.l2jserver.Config;
  28. import com.l2jserver.L2DatabaseFactory;
  29. import com.l2jserver.gameserver.data.sql.impl.ClanTable;
  30. import com.l2jserver.gameserver.data.xml.impl.ExperienceData;
  31. import com.l2jserver.gameserver.model.CharSelectInfoPackage;
  32. import com.l2jserver.gameserver.model.L2Clan;
  33. import com.l2jserver.gameserver.model.itemcontainer.Inventory;
  34. import com.l2jserver.gameserver.network.L2GameClient;
  35. public class CharSelectionInfo extends L2GameServerPacket
  36. {
  37. private static Logger _log = Logger.getLogger(CharSelectionInfo.class.getName());
  38. private final String _loginName;
  39. private final int _sessionId;
  40. private int _activeId;
  41. private final List<CharSelectInfoPackage> _characterPackages;
  42. /**
  43. * Constructor for CharSelectionInfo.
  44. * @param loginName
  45. * @param sessionId
  46. */
  47. public CharSelectionInfo(String loginName, int sessionId)
  48. {
  49. _sessionId = sessionId;
  50. _loginName = loginName;
  51. _characterPackages = loadCharacterSelectInfo(_loginName);
  52. _activeId = -1;
  53. }
  54. public CharSelectionInfo(String loginName, int sessionId, int activeId)
  55. {
  56. _sessionId = sessionId;
  57. _loginName = loginName;
  58. _characterPackages = loadCharacterSelectInfo(_loginName);
  59. _activeId = activeId;
  60. }
  61. public List<CharSelectInfoPackage> getCharInfo()
  62. {
  63. return _characterPackages;
  64. }
  65. @Override
  66. protected final void writeImpl()
  67. {
  68. writeC(0x09);
  69. int size = (_characterPackages.size());
  70. writeD(size);
  71. // Can prevent players from creating new characters (if 0); (if 1, the client will ask if chars may be created (0x13) Response: (0x0D) )
  72. writeD(Config.MAX_CHARACTERS_NUMBER_PER_ACCOUNT);
  73. writeC(0x00);
  74. long lastAccess = 0L;
  75. if (_activeId == -1)
  76. {
  77. for (int i = 0; i < size; i++)
  78. {
  79. final CharSelectInfoPackage charInfoPackage = _characterPackages.get(i);
  80. if (lastAccess < charInfoPackage.getLastAccess())
  81. {
  82. lastAccess = charInfoPackage.getLastAccess();
  83. _activeId = i;
  84. }
  85. }
  86. }
  87. for (int i = 0; i < size; i++)
  88. {
  89. final CharSelectInfoPackage charInfoPackage = _characterPackages.get(i);
  90. writeS(charInfoPackage.getName());
  91. writeD(charInfoPackage.getObjectId());
  92. writeS(_loginName);
  93. writeD(_sessionId);
  94. writeD(charInfoPackage.getClanId());
  95. writeD(0x00); // ??
  96. writeD(charInfoPackage.getSex());
  97. writeD(charInfoPackage.getRace());
  98. if (charInfoPackage.getClassId() == charInfoPackage.getBaseClassId())
  99. {
  100. writeD(charInfoPackage.getClassId());
  101. }
  102. else
  103. {
  104. writeD(charInfoPackage.getBaseClassId());
  105. }
  106. writeD(0x01); // active ??
  107. writeD(charInfoPackage.getX());
  108. writeD(charInfoPackage.getY());
  109. writeD(charInfoPackage.getZ());
  110. writeF(charInfoPackage.getCurrentHp());
  111. writeF(charInfoPackage.getCurrentMp());
  112. writeD(charInfoPackage.getSp());
  113. writeQ(charInfoPackage.getExp());
  114. writeF((float) (charInfoPackage.getExp() - ExperienceData.getInstance().getExpForLevel(charInfoPackage.getLevel())) / (ExperienceData.getInstance().getExpForLevel(charInfoPackage.getLevel() + 1) - ExperienceData.getInstance().getExpForLevel(charInfoPackage.getLevel()))); // High Five
  115. // exp %
  116. writeD(charInfoPackage.getLevel());
  117. writeD(charInfoPackage.getKarma());
  118. writeD(charInfoPackage.getPkKills());
  119. writeD(charInfoPackage.getPvPKills());
  120. writeD(0x00);
  121. writeD(0x00);
  122. writeD(0x00);
  123. writeD(0x00);
  124. writeD(0x00);
  125. writeD(0x00);
  126. writeD(0x00);
  127. for (int slot : getPaperdollOrder())
  128. {
  129. writeD(charInfoPackage.getPaperdollItemId(slot));
  130. }
  131. writeD(charInfoPackage.getHairStyle());
  132. writeD(charInfoPackage.getHairColor());
  133. writeD(charInfoPackage.getFace());
  134. writeF(charInfoPackage.getMaxHp()); // hp max
  135. writeF(charInfoPackage.getMaxMp()); // mp max
  136. long deleteTime = charInfoPackage.getDeleteTimer();
  137. int deletedays = 0;
  138. if (deleteTime > 0)
  139. {
  140. deletedays = (int) ((deleteTime - System.currentTimeMillis()) / 1000);
  141. }
  142. writeD(deletedays); // days left before
  143. // delete .. if != 0
  144. // then char is inactive
  145. writeD(charInfoPackage.getClassId());
  146. writeD(i == _activeId ? 0x01 : 0x00); // c3 auto-select char
  147. writeC(charInfoPackage.getEnchantEffect() > 127 ? 127 : charInfoPackage.getEnchantEffect());
  148. writeH(0x00);
  149. writeH(0x00);
  150. // writeD(charInfoPackage.getAugmentationId());
  151. // writeD(charInfoPackage.getTransformId()); // Used to display Transformations
  152. writeD(0x00); // Currently on retail when you are on character select you don't see your transformation.
  153. // Freya by Vistall:
  154. writeD(0x00); // npdid - 16024 Tame Tiny Baby Kookaburra A9E89C
  155. writeD(0x00); // level
  156. writeD(0x00); // ?
  157. writeD(0x00); // food? - 1200
  158. writeF(0x00); // max Hp
  159. writeF(0x00); // cur Hp
  160. // High Five by Vistall:
  161. writeD(charInfoPackage.getVitalityPoints()); // H5 Vitality
  162. }
  163. }
  164. private static List<CharSelectInfoPackage> loadCharacterSelectInfo(String loginName)
  165. {
  166. final List<CharSelectInfoPackage> characterList = new ArrayList<>();
  167. try (Connection con = L2DatabaseFactory.getInstance().getConnection();
  168. PreparedStatement statement = con.prepareStatement("SELECT * FROM characters WHERE account_name=? ORDER BY createDate"))
  169. {
  170. statement.setString(1, loginName);
  171. try (ResultSet charList = statement.executeQuery())
  172. {
  173. while (charList.next())// fills the package
  174. {
  175. CharSelectInfoPackage charInfopackage = restoreChar(charList);
  176. if (charInfopackage != null)
  177. {
  178. characterList.add(charInfopackage);
  179. }
  180. }
  181. }
  182. }
  183. catch (Exception e)
  184. {
  185. _log.log(Level.WARNING, "Could not restore char info: " + e.getMessage(), e);
  186. }
  187. return characterList;
  188. }
  189. private static void loadCharacterSubclassInfo(CharSelectInfoPackage charInfopackage, int ObjectId, int activeClassId)
  190. {
  191. try (Connection con = L2DatabaseFactory.getInstance().getConnection();
  192. PreparedStatement statement = con.prepareStatement("SELECT exp, sp, level FROM character_subclasses WHERE charId=? && class_id=? ORDER BY charId"))
  193. {
  194. statement.setInt(1, ObjectId);
  195. statement.setInt(2, activeClassId);
  196. try (ResultSet charList = statement.executeQuery())
  197. {
  198. if (charList.next())
  199. {
  200. charInfopackage.setExp(charList.getLong("exp"));
  201. charInfopackage.setSp(charList.getInt("sp"));
  202. charInfopackage.setLevel(charList.getInt("level"));
  203. }
  204. }
  205. }
  206. catch (Exception e)
  207. {
  208. _log.log(Level.WARNING, "Could not restore char subclass info: " + e.getMessage(), e);
  209. }
  210. }
  211. private static CharSelectInfoPackage restoreChar(ResultSet chardata) throws Exception
  212. {
  213. int objectId = chardata.getInt("charId");
  214. String name = chardata.getString("char_name");
  215. // See if the char must be deleted
  216. long deletetime = chardata.getLong("deletetime");
  217. if (deletetime > 0)
  218. {
  219. if (System.currentTimeMillis() > deletetime)
  220. {
  221. L2Clan clan = ClanTable.getInstance().getClan(chardata.getInt("clanid"));
  222. if (clan != null)
  223. {
  224. clan.removeClanMember(objectId, 0);
  225. }
  226. L2GameClient.deleteCharByObjId(objectId);
  227. return null;
  228. }
  229. }
  230. CharSelectInfoPackage charInfopackage = new CharSelectInfoPackage(objectId, name);
  231. charInfopackage.setAccessLevel(chardata.getInt("accesslevel"));
  232. charInfopackage.setLevel(chardata.getInt("level"));
  233. charInfopackage.setMaxHp(chardata.getInt("maxhp"));
  234. charInfopackage.setCurrentHp(chardata.getDouble("curhp"));
  235. charInfopackage.setMaxMp(chardata.getInt("maxmp"));
  236. charInfopackage.setCurrentMp(chardata.getDouble("curmp"));
  237. charInfopackage.setKarma(chardata.getInt("karma"));
  238. charInfopackage.setPkKills(chardata.getInt("pkkills"));
  239. charInfopackage.setPvPKills(chardata.getInt("pvpkills"));
  240. charInfopackage.setFace(chardata.getInt("face"));
  241. charInfopackage.setHairStyle(chardata.getInt("hairstyle"));
  242. charInfopackage.setHairColor(chardata.getInt("haircolor"));
  243. charInfopackage.setSex(chardata.getInt("sex"));
  244. charInfopackage.setExp(chardata.getLong("exp"));
  245. charInfopackage.setSp(chardata.getInt("sp"));
  246. charInfopackage.setVitalityPoints(chardata.getInt("vitality_points"));
  247. charInfopackage.setClanId(chardata.getInt("clanid"));
  248. charInfopackage.setRace(chardata.getInt("race"));
  249. final int baseClassId = chardata.getInt("base_class");
  250. final int activeClassId = chardata.getInt("classid");
  251. charInfopackage.setX(chardata.getInt("x"));
  252. charInfopackage.setY(chardata.getInt("y"));
  253. charInfopackage.setZ(chardata.getInt("z"));
  254. if (Config.L2JMOD_MULTILANG_ENABLE)
  255. {
  256. String lang = chardata.getString("language");
  257. if (!Config.L2JMOD_MULTILANG_ALLOWED.contains(lang))
  258. {
  259. lang = Config.L2JMOD_MULTILANG_DEFAULT;
  260. }
  261. charInfopackage.setHtmlPrefix("data/lang/" + lang + "/");
  262. }
  263. // if is in subclass, load subclass exp, sp, lvl info
  264. if (baseClassId != activeClassId)
  265. {
  266. loadCharacterSubclassInfo(charInfopackage, objectId, activeClassId);
  267. }
  268. charInfopackage.setClassId(activeClassId);
  269. // Get the augmentation id for equipped weapon
  270. int weaponObjId = charInfopackage.getPaperdollObjectId(Inventory.PAPERDOLL_RHAND);
  271. if (weaponObjId < 1)
  272. {
  273. weaponObjId = charInfopackage.getPaperdollObjectId(Inventory.PAPERDOLL_RHAND);
  274. }
  275. if (weaponObjId > 0)
  276. {
  277. try (Connection con = L2DatabaseFactory.getInstance().getConnection();
  278. PreparedStatement statement = con.prepareStatement("SELECT augAttributes FROM item_attributes WHERE itemId=?"))
  279. {
  280. statement.setInt(1, weaponObjId);
  281. try (ResultSet result = statement.executeQuery())
  282. {
  283. if (result.next())
  284. {
  285. int augment = result.getInt("augAttributes");
  286. charInfopackage.setAugmentationId(augment == -1 ? 0 : augment);
  287. }
  288. }
  289. }
  290. catch (Exception e)
  291. {
  292. _log.log(Level.WARNING, "Could not restore augmentation info: " + e.getMessage(), e);
  293. }
  294. }
  295. // Check if the base class is set to zero and also doesn't match with the current active class, otherwise send the base class ID. This prevents chars created before base class was introduced from being displayed incorrectly.
  296. if ((baseClassId == 0) && (activeClassId > 0))
  297. {
  298. charInfopackage.setBaseClassId(activeClassId);
  299. }
  300. else
  301. {
  302. charInfopackage.setBaseClassId(baseClassId);
  303. }
  304. charInfopackage.setDeleteTimer(deletetime);
  305. charInfopackage.setLastAccess(chardata.getLong("lastAccess"));
  306. return charInfopackage;
  307. }
  308. }