CharacterCreate.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  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.clientpackets;
  20. import java.util.List;
  21. import java.util.logging.Level;
  22. import java.util.logging.LogRecord;
  23. import java.util.logging.Logger;
  24. import java.util.regex.Matcher;
  25. import java.util.regex.Pattern;
  26. import java.util.regex.PatternSyntaxException;
  27. import com.l2jserver.Config;
  28. import com.l2jserver.gameserver.data.sql.impl.CharNameTable;
  29. import com.l2jserver.gameserver.data.xml.impl.InitialEquipmentData;
  30. import com.l2jserver.gameserver.data.xml.impl.InitialShortcutData;
  31. import com.l2jserver.gameserver.data.xml.impl.PlayerTemplateData;
  32. import com.l2jserver.gameserver.data.xml.impl.SkillTreesData;
  33. import com.l2jserver.gameserver.datatables.SkillData;
  34. import com.l2jserver.gameserver.instancemanager.QuestManager;
  35. import com.l2jserver.gameserver.model.L2SkillLearn;
  36. import com.l2jserver.gameserver.model.L2World;
  37. import com.l2jserver.gameserver.model.Location;
  38. import com.l2jserver.gameserver.model.actor.appearance.PcAppearance;
  39. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  40. import com.l2jserver.gameserver.model.actor.stat.PcStat;
  41. import com.l2jserver.gameserver.model.actor.templates.L2PcTemplate;
  42. import com.l2jserver.gameserver.model.base.ClassId;
  43. import com.l2jserver.gameserver.model.events.Containers;
  44. import com.l2jserver.gameserver.model.events.EventDispatcher;
  45. import com.l2jserver.gameserver.model.events.impl.character.player.OnPlayerCreate;
  46. import com.l2jserver.gameserver.model.items.PcItemTemplate;
  47. import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
  48. import com.l2jserver.gameserver.model.quest.Quest;
  49. import com.l2jserver.gameserver.model.quest.QuestState;
  50. import com.l2jserver.gameserver.model.quest.State;
  51. import com.l2jserver.gameserver.network.L2GameClient;
  52. import com.l2jserver.gameserver.network.serverpackets.CharCreateFail;
  53. import com.l2jserver.gameserver.network.serverpackets.CharCreateOk;
  54. import com.l2jserver.gameserver.network.serverpackets.CharSelectionInfo;
  55. import com.l2jserver.gameserver.util.Util;
  56. @SuppressWarnings("unused")
  57. public final class CharacterCreate extends L2GameClientPacket
  58. {
  59. private static final String _C__0C_CHARACTERCREATE = "[C] 0C CharacterCreate";
  60. protected static final Logger _logAccounting = Logger.getLogger("accounting");
  61. // cSdddddddddddd
  62. private String _name;
  63. private int _race;
  64. private byte _sex;
  65. private int _classId;
  66. private int _int;
  67. private int _str;
  68. private int _con;
  69. private int _men;
  70. private int _dex;
  71. private int _wit;
  72. private byte _hairStyle;
  73. private byte _hairColor;
  74. private byte _face;
  75. @Override
  76. protected void readImpl()
  77. {
  78. _name = readS();
  79. _race = readD();
  80. _sex = (byte) readD();
  81. _classId = readD();
  82. _int = readD();
  83. _str = readD();
  84. _con = readD();
  85. _men = readD();
  86. _dex = readD();
  87. _wit = readD();
  88. _hairStyle = (byte) readD();
  89. _hairColor = (byte) readD();
  90. _face = (byte) readD();
  91. }
  92. @Override
  93. protected void runImpl()
  94. {
  95. // Last Verified: May 30, 2009 - Gracia Final - Players are able to create characters with names consisting of as little as 1,2,3 letter/number combinations.
  96. if ((_name.length() < 1) || (_name.length() > 16))
  97. {
  98. if (Config.DEBUG)
  99. {
  100. _log.fine("Character Creation Failure: Character name " + _name + " is invalid. Message generated: Your title cannot exceed 16 characters in length. Please try again.");
  101. }
  102. sendPacket(new CharCreateFail(CharCreateFail.REASON_16_ENG_CHARS));
  103. return;
  104. }
  105. if (Config.FORBIDDEN_NAMES.length > 1)
  106. {
  107. for (String st : Config.FORBIDDEN_NAMES)
  108. {
  109. if (_name.toLowerCase().contains(st.toLowerCase()))
  110. {
  111. sendPacket(new CharCreateFail(CharCreateFail.REASON_INCORRECT_NAME));
  112. return;
  113. }
  114. }
  115. }
  116. // Last Verified: May 30, 2009 - Gracia Final
  117. if (!Util.isAlphaNumeric(_name) || !isValidName(_name))
  118. {
  119. if (Config.DEBUG)
  120. {
  121. _log.fine("Character Creation Failure: Character name " + _name + " is invalid. Message generated: Incorrect name. Please try again.");
  122. }
  123. sendPacket(new CharCreateFail(CharCreateFail.REASON_INCORRECT_NAME));
  124. return;
  125. }
  126. if ((_face > 2) || (_face < 0))
  127. {
  128. _log.warning("Character Creation Failure: Character face " + _face + " is invalid. Possible client hack. " + getClient());
  129. sendPacket(new CharCreateFail(CharCreateFail.REASON_CREATION_FAILED));
  130. return;
  131. }
  132. if ((_hairStyle < 0) || ((_sex == 0) && (_hairStyle > 4)) || ((_sex != 0) && (_hairStyle > 6)))
  133. {
  134. _log.warning("Character Creation Failure: Character hair style " + _hairStyle + " is invalid. Possible client hack. " + getClient());
  135. sendPacket(new CharCreateFail(CharCreateFail.REASON_CREATION_FAILED));
  136. return;
  137. }
  138. if ((_hairColor > 3) || (_hairColor < 0))
  139. {
  140. _log.warning("Character Creation Failure: Character hair color " + _hairColor + " is invalid. Possible client hack. " + getClient());
  141. sendPacket(new CharCreateFail(CharCreateFail.REASON_CREATION_FAILED));
  142. return;
  143. }
  144. L2PcInstance newChar = null;
  145. L2PcTemplate template = null;
  146. /*
  147. * DrHouse: Since checks for duplicate names are done using SQL, lock must be held until data is written to DB as well.
  148. */
  149. synchronized (CharNameTable.getInstance())
  150. {
  151. if ((CharNameTable.getInstance().getAccountCharacterCount(getClient().getAccountName()) >= Config.MAX_CHARACTERS_NUMBER_PER_ACCOUNT) && (Config.MAX_CHARACTERS_NUMBER_PER_ACCOUNT != 0))
  152. {
  153. if (Config.DEBUG)
  154. {
  155. _log.fine("Max number of characters reached. Creation failed.");
  156. }
  157. sendPacket(new CharCreateFail(CharCreateFail.REASON_TOO_MANY_CHARACTERS));
  158. return;
  159. }
  160. else if (CharNameTable.getInstance().doesCharNameExist(_name))
  161. {
  162. if (Config.DEBUG)
  163. {
  164. _log.fine("Character Creation Failure: Message generated: You cannot create another character. Please delete the existing character and try again.");
  165. }
  166. sendPacket(new CharCreateFail(CharCreateFail.REASON_NAME_ALREADY_EXISTS));
  167. return;
  168. }
  169. template = PlayerTemplateData.getInstance().getTemplate(_classId);
  170. if ((template == null) || (ClassId.getClassId(_classId).level() > 0))
  171. {
  172. if (Config.DEBUG)
  173. {
  174. _log.fine("Character Creation Failure: " + _name + " classId: " + _classId + " Template: " + template + " Message generated: Your character creation has failed.");
  175. }
  176. sendPacket(new CharCreateFail(CharCreateFail.REASON_CREATION_FAILED));
  177. return;
  178. }
  179. final PcAppearance app = new PcAppearance(_face, _hairColor, _hairStyle, _sex != 0);
  180. newChar = L2PcInstance.create(template, getClient().getAccountName(), _name, app);
  181. }
  182. // HP and MP are at maximum and CP is zero by default.
  183. newChar.setCurrentHp(newChar.getMaxHp());
  184. newChar.setCurrentMp(newChar.getMaxMp());
  185. // newChar.setMaxLoad(template.getBaseLoad());
  186. sendPacket(new CharCreateOk());
  187. initNewChar(getClient(), newChar);
  188. LogRecord record = new LogRecord(Level.INFO, "Created new character");
  189. record.setParameters(new Object[]
  190. {
  191. newChar,
  192. getClient()
  193. });
  194. _logAccounting.log(record);
  195. }
  196. private boolean isValidName(String text)
  197. {
  198. boolean result = true;
  199. String test = text;
  200. Pattern pattern;
  201. // UnAfraid: TODO: Move that into Config
  202. try
  203. {
  204. pattern = Pattern.compile(Config.CNAME_TEMPLATE);
  205. }
  206. catch (PatternSyntaxException e) // case of illegal pattern
  207. {
  208. _log.warning("ERROR : Character name pattern of config is wrong!");
  209. pattern = Pattern.compile(".*");
  210. }
  211. Matcher regexp = pattern.matcher(test);
  212. if (!regexp.matches())
  213. {
  214. result = false;
  215. }
  216. return result;
  217. }
  218. private void initNewChar(L2GameClient client, L2PcInstance newChar)
  219. {
  220. if (Config.DEBUG)
  221. {
  222. _log.fine("Character init start");
  223. }
  224. L2World.getInstance().storeObject(newChar);
  225. if (Config.STARTING_ADENA > 0)
  226. {
  227. newChar.addAdena("Init", Config.STARTING_ADENA, null, false);
  228. }
  229. final L2PcTemplate template = newChar.getTemplate();
  230. Location createLoc = template.getCreationPoint();
  231. newChar.setXYZInvisible(createLoc.getX(), createLoc.getY(), createLoc.getZ());
  232. newChar.setTitle("");
  233. if (Config.ENABLE_VITALITY)
  234. {
  235. newChar.setVitalityPoints(Math.min(Config.STARTING_VITALITY_POINTS, PcStat.MAX_VITALITY_POINTS), true);
  236. }
  237. if (Config.STARTING_LEVEL > 1)
  238. {
  239. newChar.getStat().addLevel((byte) (Config.STARTING_LEVEL - 1));
  240. }
  241. if (Config.STARTING_SP > 0)
  242. {
  243. newChar.getStat().addSp(Config.STARTING_SP);
  244. }
  245. final List<PcItemTemplate> initialItems = InitialEquipmentData.getInstance().getEquipmentList(newChar.getClassId());
  246. if (initialItems != null)
  247. {
  248. for (PcItemTemplate ie : initialItems)
  249. {
  250. final L2ItemInstance item = newChar.getInventory().addItem("Init", ie.getId(), ie.getCount(), newChar, null);
  251. if (item == null)
  252. {
  253. _log.warning("Could not create item during char creation: itemId " + ie.getId() + ", amount " + ie.getCount() + ".");
  254. continue;
  255. }
  256. if (item.isEquipable() && ie.isEquipped())
  257. {
  258. newChar.getInventory().equipItem(item);
  259. }
  260. }
  261. }
  262. for (L2SkillLearn skill : SkillTreesData.getInstance().getAvailableSkills(newChar, newChar.getClassId(), false, true))
  263. {
  264. if (Config.DEBUG)
  265. {
  266. _log.fine("Adding starter skill:" + skill.getSkillId() + " / " + skill.getSkillLevel());
  267. }
  268. newChar.addSkill(SkillData.getInstance().getSkill(skill.getSkillId(), skill.getSkillLevel()), true);
  269. }
  270. // Register all shortcuts for actions, skills and items for this new character.
  271. InitialShortcutData.getInstance().registerAllShortcuts(newChar);
  272. if (!Config.DISABLE_TUTORIAL)
  273. {
  274. startTutorialQuest(newChar);
  275. }
  276. EventDispatcher.getInstance().notifyEvent(new OnPlayerCreate(newChar, newChar.getObjectId(), newChar.getName(), client), Containers.Players());
  277. newChar.setOnlineStatus(true, false);
  278. newChar.deleteMe();
  279. final CharSelectionInfo cl = new CharSelectionInfo(client.getAccountName(), client.getSessionId().playOkID1);
  280. client.setCharSelection(cl.getCharInfo());
  281. if (Config.DEBUG)
  282. {
  283. _log.fine("Character init end");
  284. }
  285. }
  286. /**
  287. * TODO: Unhardcode it using the new listeners.
  288. * @param player
  289. */
  290. public void startTutorialQuest(L2PcInstance player)
  291. {
  292. final QuestState qs = player.getQuestState("255_Tutorial");
  293. Quest q = null;
  294. if (qs == null)
  295. {
  296. q = QuestManager.getInstance().getQuest("255_Tutorial");
  297. }
  298. if (q != null)
  299. {
  300. q.newQuestState(player).setState(State.STARTED);
  301. }
  302. }
  303. @Override
  304. public String getType()
  305. {
  306. return _C__0C_CHARACTERCREATE;
  307. }
  308. }