/*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jfrozen.gameserver.network.clientpackets;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import com.l2jfrozen.Config;
import com.l2jfrozen.gameserver.GameServer;
import com.l2jfrozen.gameserver.datatables.NobleSkillTable;
import com.l2jfrozen.gameserver.datatables.SkillTable;
import com.l2jfrozen.gameserver.datatables.sql.CharNameTable;
import com.l2jfrozen.gameserver.datatables.sql.CharTemplateTable;
import com.l2jfrozen.gameserver.datatables.sql.ItemTable;
import com.l2jfrozen.gameserver.datatables.sql.SkillTreeTable;
import com.l2jfrozen.gameserver.datatables.xml.ExperienceData;
import com.l2jfrozen.gameserver.idfactory.IdFactory;
import com.l2jfrozen.gameserver.managers.QuestManager;
import com.l2jfrozen.gameserver.model.L2Object;
import com.l2jfrozen.gameserver.model.L2ShortCut;
import com.l2jfrozen.gameserver.model.L2Skill;
import com.l2jfrozen.gameserver.model.L2SkillLearn;
import com.l2jfrozen.gameserver.model.L2World;
import com.l2jfrozen.gameserver.model.actor.instance.L2ItemInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2PcInstance;
import com.l2jfrozen.gameserver.model.quest.Quest;
import com.l2jfrozen.gameserver.model.quest.QuestState;
import com.l2jfrozen.gameserver.network.L2GameClient;
import com.l2jfrozen.gameserver.network.serverpackets.CharCreateFail;
import com.l2jfrozen.gameserver.network.serverpackets.CharCreateOk;
import com.l2jfrozen.gameserver.network.serverpackets.CharSelectInfo;
import com.l2jfrozen.gameserver.templates.L2Item;
import com.l2jfrozen.gameserver.templates.L2PcTemplate;
import com.l2jfrozen.gameserver.util.Util;
@SuppressWarnings("unused")
public final class CharacterCreate extends L2GameClientPacket
{
private static Logger _log = Logger.getLogger(CharacterCreate.class.getName());
private static final Object CREATION_LOCK = new Object();
private String _name;
private byte _sex, _hairStyle, _hairColor, _face;
private int _race, _classId, _int, _str, _con, _men, _dex, _wit;
@Override
protected void readImpl()
{
_name = readS();
_race = readD();
_sex = (byte) readD();
_classId = readD();
_int = readD();
_str = readD();
_con = readD();
_men = readD();
_dex = readD();
_wit = readD();
_hairStyle = (byte) readD();
_hairColor = (byte) readD();
_face = (byte) readD();
}
@Override
protected void runImpl()
{
if (_name.length() < 3 || _name.length() > 16 || !Util.isAlphaNumeric(_name) || !isValidName(_name))
{
if (Config.DEBUG)
_log.fine("DEBUG "+getType()+": charname: " + _name + " is invalid. creation failed.");
sendPacket(new CharCreateFail(CharCreateFail.REASON_16_ENG_CHARS));
return;
}
if(Config.FORBIDDEN_NAMES.length > 3)
{
for(String st : Config.FORBIDDEN_NAMES)
{
if(_name.toLowerCase().contains(st.toLowerCase()))
{
sendPacket(new CharCreateFail(CharCreateFail.REASON_NAME_ALREADY_EXISTS));
return;
}
}
}
if (Config.DEBUG)
_log.fine("DEBUG "+getType()+": charname: " + _name + " classId: " + _classId);
L2PcInstance newChar = null;
L2PcTemplate template = null;
// Since checks for duplicate names are done using SQL, lock must be held until data is written to DB as well.
synchronized (CharNameTable.getInstance())
{
if (CharNameTable.getInstance().accountCharNumber(getClient().getAccountName()) >= Config.MAX_CHARACTERS_NUMBER_PER_ACCOUNT && Config.MAX_CHARACTERS_NUMBER_PER_ACCOUNT != 0)
{
if (Config.DEBUG)
_log.fine("DEBUG "+getType()+": Max number of characters reached. Creation failed.");
sendPacket(new CharCreateFail(CharCreateFail.REASON_TOO_MANY_CHARACTERS));
return;
}
else if (CharNameTable.getInstance().doesCharNameExist(_name))
{
if(Config.DEBUG)
_log.fine("DEBUG "+getType()+": charname: " + _name + " already exists. creation failed.");
sendPacket(new CharCreateFail(CharCreateFail.REASON_NAME_ALREADY_EXISTS));
return;
}else if (CharNameTable.getInstance().ipCharNumber(getClient().getConnection().getInetAddress().getHostName()) >= Config.MAX_CHARACTERS_NUMBER_PER_IP && Config.MAX_CHARACTERS_NUMBER_PER_IP != 0)
{
if (Config.DEBUG)
_log.fine("DEBUG "+getType()+": Max number of characters reached for IP. Creation failed.");
sendPacket(new CharCreateFail(CharCreateFail.REASON_TOO_MANY_CHARACTERS));
return;
}
template = CharTemplateTable.getInstance().getTemplate(_classId);
if (Config.DEBUG)
_log.fine("DEBUG "+getType()+": charname: " + _name + " classId: " + _classId + " template: " + template);
if (template == null || template.classBaseLevel > 1)
{
sendPacket(new CharCreateFail(CharCreateFail.REASON_CREATION_FAILED));
return;
}
int objectId = IdFactory.getInstance().getNextId();
newChar = L2PcInstance.create(objectId, template, getClient().getAccountName(), _name, _hairStyle, _hairColor, _face, _sex != 0);
newChar.setCurrentHp(newChar.getMaxHp());//L2Off like
//newChar.setCurrentCp(template.baseCpMax);
newChar.setCurrentCp(0); //L2Off like
newChar.setCurrentMp(newChar.getMaxMp());//L2Off like
//newChar.setMaxLoad(template.baseLoad);
// send acknowledgement
sendPacket(new CharCreateOk()); // Success
initNewChar(getClient(), newChar);
}
}
private boolean isValidName(String text)
{
boolean result = true;
String test = text;
Pattern pattern;
try
{
pattern = Pattern.compile(Config.CNAME_TEMPLATE);
}
catch (PatternSyntaxException e) // case of illegal pattern
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();
_log.warning("ERROR "+getType()+": Character name pattern of config is wrong!");
pattern = Pattern.compile(".*");
}
Matcher regexp = pattern.matcher(test);
if (!regexp.matches())
result = false;
return result;
}
private void initNewChar(L2GameClient client, L2PcInstance newChar)
{
if (Config.DEBUG)
_log.fine("DEBUG "+getType()+": Character init start");
L2World.getInstance().storeObject(newChar);
L2PcTemplate template = newChar.getTemplate();
// Starting Items
if (Config.STARTING_ADENA > 0)
newChar.addAdena("Init", Config.STARTING_ADENA, null, false);
if (Config.STARTING_AA > 0)
newChar.addAncientAdena("Init", Config.STARTING_AA, null, false);
if (Config.CUSTOM_STARTER_ITEMS_ENABLED)
{
for (int[] reward : Config.STARTING_CUSTOM_ITEMS)
{
if(ItemTable.getInstance().createDummyItem(reward[0]).isStackable())
newChar.getInventory().addItem("Starter Items", reward[0], reward[1], newChar, null);
else
for (int i = 0; i < reward[1]; ++i)
newChar.getInventory().addItem("Starter Items", reward[0], 1, newChar, null);
}
}
if (Config.SPAWN_CHAR)
newChar.setXYZInvisible(Config.SPAWN_X, Config.SPAWN_Y, Config.SPAWN_Z);
else
newChar.setXYZInvisible(template.spawnX, template.spawnY, template.spawnZ);
if (Config.ALLOW_CREATE_LVL)
newChar.getStat().addExp(ExperienceData.getInstance().getExpForLevel(Config.CHAR_CREATE_LVL));
if (Config.CHAR_TITLE)
newChar.setTitle(Config.ADD_CHAR_TITLE);
else
newChar.setTitle("");
if (Config.PVP_PK_TITLE)
newChar.setTitle(Config.PVP_TITLE_PREFIX + "0" + Config.PK_TITLE_PREFIX + "0 ");
// Shortcuts
newChar.registerShortCut(new L2ShortCut(0, 0, 3, 2, -1, 1)); // Attack
newChar.registerShortCut(new L2ShortCut(2, 2, 3, 3, -1, 1)); // Trade
newChar.registerShortCut(new L2ShortCut(3, 2, 3, 7, -1, 1)); // Party
ItemTable itemTable = ItemTable.getInstance();
L2Item[] items = template.getItems();
for (L2Item item2 : items)
{
L2ItemInstance item = newChar.getInventory().addItem("Init", item2.getItemId(), 1, newChar, null);
if (item.getItemId() == 728)
newChar.registerShortCut(new L2ShortCut(9, 1, 1, item.getObjectId(), -1, 1)); // mana pot shortcut
if (item.getItemId() == 1539)
newChar.registerShortCut(new L2ShortCut(8, 1, 1, item.getObjectId(), -1, 1)); // healing pot shortcut
if (item.getItemId() == 5591)
newChar.registerShortCut(new L2ShortCut(7, 1, 1, item.getObjectId(), -1, 1)); // healing pot shortcut
if (item.getItemId() == 9990)
newChar.registerShortCut(new L2ShortCut(0, 1, 1, item.getObjectId(), -1, 1)); // healing pot shortcut
}
L2SkillLearn[] startSkills = SkillTreeTable.getInstance().getAvailableSkills(newChar, newChar.getClassId());
for(L2SkillLearn startSkill : startSkills)
{
newChar.addSkill(SkillTable.getInstance().getInfo(startSkill.getId(), startSkill.getLevel()), true);
if(Config.DEBUG)
_log.fine("DEBUG "+getType()+": Adding starter skill:" + startSkill.getId() + " / " + startSkill.getLevel());
}
startTutorialQuest(newChar);
newChar.store();
newChar.deleteMe(); // Release the world of this character and it's inventory
// Before the char selection, check shutdown status
if (GameServer.getSelectorThread().isShutdown())
{
client.closeNow();
return;
}
// Send char list
CharSelectInfo cl = new CharSelectInfo(client.getAccountName(), client.getSessionId().playOkID1);
client.getConnection().sendPacket(cl);
client.setCharSelection(cl.getCharInfo());
if(Config.DEBUG)
_log.fine("DEBUG "+getType()+": Character init end");
}
public void startTutorialQuest(L2PcInstance player)
{
QuestState qs = player.getQuestState("255_Tutorial");
Quest q = null;
if(qs == null && !Config.ALT_DEV_NO_QUESTS){
q = QuestManager.getInstance().getQuest("255_Tutorial");
}
if(q != null)
q.newQuestState(player);
}
@Override
public String getType()
{
return "[C] 0B CharacterCreate";
}
}