/**
* License
* THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS
* CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE").
* THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW.
* ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR
* COPYRIGHT LAW IS PROHIBITED.
*
* BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND
* AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE
* MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED
* HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
*
*/
package l1j.server.server.clientpackets;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.logging.Level;
import java.util.logging.Logger;
import l1j.server.Config;
import l1j.server.server.Account;
import l1j.server.server.BadNamesList;
import l1j.server.server.ClientThread;
import l1j.server.server.IdFactory;
import l1j.server.server.datatables.CharacterTable;
import l1j.server.server.datatables.SkillsTable;
import l1j.server.server.model.Beginner;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.serverpackets.S_AddSkill;
import l1j.server.server.serverpackets.S_CharCreateStatus;
import l1j.server.server.serverpackets.S_NewCharPacket;
import l1j.server.server.templates.L1Skills;
import l1j.server.server.utils.CalcInitHpMp;
// Referenced classes of package l1j.server.server.clientpackets:
// ClientBasePacket
/**
* 處理收到由客戶端傳來建立角色的封包
*/
public class C_CreateChar extends ClientBasePacket {
private static Logger _log = Logger.getLogger(C_CreateChar.class.getName());
private static final String C_CREATE_CHAR = "[C] C_CreateChar";
private static final int[] ORIGINAL_STR = new int[]
{ 13, 16, 11, 8, 12, 13, 11 };
private static final int[] ORIGINAL_DEX = new int[]
{ 10, 12, 12, 7, 15, 11, 10 };
private static final int[] ORIGINAL_CON = new int[]
{ 10, 14, 12, 12, 8, 14, 12 };
private static final int[] ORIGINAL_WIS = new int[]
{ 11, 9, 12, 12, 10, 12, 12 };
private static final int[] ORIGINAL_CHA = new int[]
{ 13, 12, 9, 8, 9, 8, 8 };
private static final int[] ORIGINAL_INT = new int[]
{ 10, 8, 12, 12, 11, 11, 12 };
private static final int[] ORIGINAL_AMOUNT = new int[]
{ 8, 4, 7, 16, 10, 6, 10 };
private static final String CLIENT_LANGUAGE_CODE = Config.CLIENT_LANGUAGE_CODE;
public C_CreateChar(byte[] abyte0, ClientThread client) throws Exception {
super(abyte0);
L1PcInstance pc = new L1PcInstance();
String name = readS();
Account account = Account.load(client.getAccountName());
int characterSlot = account.getCharacterSlot();
int maxAmount = Config.DEFAULT_CHARACTER_SLOT + characterSlot;
name = name.replaceAll("\\s", "");
name = name.replaceAll(" ", "");
if (name.length() == 0) {
S_CharCreateStatus s_charcreatestatus = new S_CharCreateStatus(S_CharCreateStatus.REASON_INVALID_NAME);
client.sendPacket(s_charcreatestatus);
return;
}
if (isInvalidName(name)) {
S_CharCreateStatus s_charcreatestatus = new S_CharCreateStatus(S_CharCreateStatus.REASON_INVALID_NAME);
client.sendPacket(s_charcreatestatus);
return;
}
if (CharacterTable.doesCharNameExist(name)) {
_log.fine("charname: " + pc.getName() + " already exists. creation failed.");
S_CharCreateStatus s_charcreatestatus1 = new S_CharCreateStatus(S_CharCreateStatus.REASON_ALREADY_EXSISTS);
client.sendPacket(s_charcreatestatus1);
return;
}
if (client.getAccount().countCharacters() >= maxAmount) {
_log.fine("account: " + client.getAccountName() + " 超過角色上限數目: " + maxAmount + "。");
S_CharCreateStatus s_charcreatestatus1 = new S_CharCreateStatus(S_CharCreateStatus.REASON_WRONG_AMOUNT);
client.sendPacket(s_charcreatestatus1);
return;
}
pc.setName(name);
pc.setType(readC());
pc.set_sex(readC());
pc.addBaseStr((byte) readC());
pc.addBaseDex((byte) readC());
pc.addBaseCon((byte) readC());
pc.addBaseWis((byte) readC());
pc.addBaseCha((byte) readC());
pc.addBaseInt((byte) readC());
boolean isStatusError = false;
int originalStr = ORIGINAL_STR[pc.getType()];
int originalDex = ORIGINAL_DEX[pc.getType()];
int originalCon = ORIGINAL_CON[pc.getType()];
int originalWis = ORIGINAL_WIS[pc.getType()];
int originalCha = ORIGINAL_CHA[pc.getType()];
int originalInt = ORIGINAL_INT[pc.getType()];
int originalAmount = ORIGINAL_AMOUNT[pc.getType()];
if (((pc.getBaseStr() < originalStr) || (pc.getBaseDex() < originalDex) || (pc.getBaseCon() < originalCon) || (pc.getBaseWis() < originalWis)
|| (pc.getBaseCha() < originalCha) || (pc.getBaseInt() < originalInt))
|| ((pc.getBaseStr() > originalStr + originalAmount) || (pc.getBaseDex() > originalDex + originalAmount)
|| (pc.getBaseCon() > originalCon + originalAmount) || (pc.getBaseWis() > originalWis + originalAmount)
|| (pc.getBaseCha() > originalCha + originalAmount) || (pc.getBaseInt() > originalInt + originalAmount))) {
isStatusError = true;
}
int statusAmount = pc.getDex() + pc.getCha() + pc.getCon() + pc.getInt() + pc.getStr() + pc.getWis();
if ((statusAmount != 75) || isStatusError) {
_log.finest("Character have wrong value");
S_CharCreateStatus s_charcreatestatus3 = new S_CharCreateStatus(S_CharCreateStatus.REASON_WRONG_AMOUNT);
client.sendPacket(s_charcreatestatus3);
return;
}
_log.fine("charname: " + pc.getName() + " classId: " + pc.getClassId());
S_CharCreateStatus s_charcreatestatus2 = new S_CharCreateStatus(S_CharCreateStatus.REASON_OK);
client.sendPacket(s_charcreatestatus2);
initNewChar(client, pc);
}
private static final int[] MALE_LIST = new int[]
{ 0, 61, 138, 734, 2786, 6658, 6671 };
private static final int[] FEMALE_LIST = new int[]
{ 1, 48, 37, 1186, 2796, 6661, 6650 };
/*
* private static final int[] LOCX_LIST = new int[] { 32734, 32734, 32734,
* 32734, 32734, 32734, 32734 }; private static final int[] LOCY_LIST = new
* int[] { 32798, 32798, 32798, 32798, 32798, 32798, 32798 }; private static
* final short[] MAPID_LIST = new short[] { 8013, 8013, 8013, 8013, 8013,
* 8013, 8013 };
*/
/*private static final int[] LOCX_LIST = new int[]
{ 32780, 32714, 32714, 32780, 32714, 32714, 32714 };
private static final int[] LOCY_LIST = new int[]
{ 32781, 32877, 32877, 32781, 32877, 32877, 32877 };
private static final short[] MAPID_LIST = new short[]
{ 68, 69, 69, 68, 69, 69, 69 };*/
//台版 3.3C
private static final int[] LOCX_LIST = new int[]
{ 32691, 32691, 32691, 32691, 32691, 32691, 32691 };
private static final int[] LOCY_LIST = new int[]
{ 32864, 32864, 32864, 32864, 32864, 32864, 32864 };
private static final short[] MAPID_LIST = new short[]
{ 2005, 2005, 2005, 2005, 2005, 2005, 2005 };
private static void initNewChar(ClientThread client, L1PcInstance pc) throws IOException, Exception {
pc.setId(IdFactory.getInstance().nextId());
pc.setBirthday();
if (pc.get_sex() == 0) {
pc.setClassId(MALE_LIST[pc.getType()]);
}
else {
pc.setClassId(FEMALE_LIST[pc.getType()]);
}
pc.setX(LOCX_LIST[pc.getType()]);
pc.setY(LOCY_LIST[pc.getType()]);
pc.setMap(MAPID_LIST[pc.getType()]);
pc.setHeading(0);
pc.setLawful(0);
int initHp = CalcInitHpMp.calcInitHp(pc);
int initMp = CalcInitHpMp.calcInitMp(pc);
pc.addBaseMaxHp((short) initHp);
pc.setCurrentHp((short) initHp);
pc.addBaseMaxMp((short) initMp);
pc.setCurrentMp((short) initMp);
pc.resetBaseAc();
pc.setTitle("");
pc.setClanid(0);
pc.setClanRank(0);
pc.set_food(40);
pc.setAccessLevel((short) 0);
pc.setGm(false);
pc.setMonitor(false);
pc.setGmInvis(false);
pc.setExp(0);
pc.setHighLevel(0);
pc.setStatus(0);
pc.setClanname("");
pc.setBonusStats(0);
pc.setElixirStats(0);
pc.resetBaseMr();
pc.setElfAttr(0);
pc.set_PKcount(0);
pc.setPkCountForElf(0);
pc.setExpRes(0);
pc.setPartnerId(0);
pc.setOnlineStatus(0);
pc.setHomeTownId(0);
pc.setContribution(0);
pc.setBanned(false);
pc.setKarma(0);
if (pc.isWizard()) { // WIZ
pc.sendPackets(new S_AddSkill(3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
int object_id = pc.getId();
L1Skills l1skills = SkillsTable.getInstance().getTemplate(4); // EB
String skill_name = l1skills.getName();
int skill_id = l1skills.getSkillId();
SkillsTable.getInstance().spellMastery(object_id, skill_id, skill_name, 0, 0); // 儲存魔法資料到資料庫中
}
Beginner.getInstance().GiveItem(pc);
pc.setAccountName(client.getAccountName());
CharacterTable.getInstance().storeNewCharacter(pc);
S_NewCharPacket s_newcharpacket = new S_NewCharPacket(pc);
client.sendPacket(s_newcharpacket);
CharacterTable.getInstance();
CharacterTable.saveCharStatus(pc);
pc.refresh();
}
private static boolean isAlphaNumeric(String s) {
boolean flag = true;
char ac[] = s.toCharArray();
int i = 0;
do {
if (i >= ac.length) {
break;
}
if (!Character.isLetterOrDigit(ac[i])) {
flag = false;
break;
}
i++;
}
while (true);
return flag;
}
private static boolean isInvalidName(String name) {
int numOfNameBytes = 0;
// TODO:Check the badNameList is working well ?
if (BadNamesList.getInstance().isBadName(name)) {
return true;
}
try {
numOfNameBytes = name.getBytes(CLIENT_LANGUAGE_CODE).length;
}
catch (UnsupportedEncodingException e) {
_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
return false;
}
if (isAlphaNumeric(name)) {
return false;
}
// XXX - 規則還沒確定
// 雙字節字符或5個字符以上或整個超過 12個字節就視為一個無效的名稱
if ((5 < (numOfNameBytes - name.length())) || (12 < numOfNameBytes)) {
return false;
}
if (BadNamesList.getInstance().isBadName(name)) {
return false;
}
return true;
}
@Override
public String getType() {
return C_CREATE_CHAR;
}
}