package com.aionemu.gameserver.network.aion.serverpackets;
import java.util.List;
import com.aionemu.gameserver.configs.main.SecurityConfig;
import com.aionemu.gameserver.dao.MailDAO;
import com.aionemu.gameserver.dao.PlayerSettingsDAO;
import com.aionemu.gameserver.model.account.CharacterBanInfo;
import com.aionemu.gameserver.model.account.PlayerAccountData;
import com.aionemu.gameserver.model.gameobjects.Item;
import com.aionemu.gameserver.model.gameobjects.player.PlayerAppearance;
import com.aionemu.gameserver.model.gameobjects.player.PlayerCommonData;
import com.aionemu.gameserver.model.items.ItemSlot;
import com.aionemu.gameserver.network.aion.AionConnection;
import com.aionemu.gameserver.network.aion.AionServerPacket;
import com.aionemu.gameserver.services.BrokerService;
import com.aionemu.gameserver.services.player.MultiClientingService;
/**
* @author AEJTester, Nemesiss, Niato, Neon
*/
public abstract class AbstractPlayerInfoPacket extends AionServerPacket {
/**
* The maximum number of characters the client can display. The client expects a fixed size text buffer in various packets.
*/
public static final int CHARNAME_MAX_LENGTH = 25;
protected void writePlayerInfo(PlayerAccountData accPlData, AionConnection con) {
PlayerCommonData pcd = accPlData.getPlayerCommonData();
int playerId = pcd.getPlayerObjId();
PlayerAppearance playerAppearance = accPlData.getAppearance();
CharacterBanInfo cbi = getCharBanInfo(accPlData, con);
writeD(playerId);
writeS(pcd.getName(), CHARNAME_MAX_LENGTH);
writeD(pcd.getGender().getGenderId());
writeD(pcd.getRace().getRaceId());
writeD(pcd.getPlayerClass().getClassId());
writeD(playerAppearance.getVoice());
writeD(playerAppearance.getSkinRGB());
writeD(playerAppearance.getHairRGB());
writeD(playerAppearance.getEyeRGB());
writeD(playerAppearance.getLipRGB());
writeC(playerAppearance.getFace());
writeC(playerAppearance.getHair());
writeC(playerAppearance.getDeco());
writeC(playerAppearance.getTattoo());
writeC(playerAppearance.getFaceContour());
writeC(playerAppearance.getExpression());
writeC(5);// always 5 o0
writeC(playerAppearance.getJawLine());
writeC(playerAppearance.getForehead());
writeC(playerAppearance.getEyeHeight());
writeC(playerAppearance.getEyeSpace());
writeC(playerAppearance.getEyeWidth());
writeC(playerAppearance.getEyeSize());
writeC(playerAppearance.getEyeShape());
writeC(playerAppearance.getEyeAngle());
writeC(playerAppearance.getBrowHeight());
writeC(playerAppearance.getBrowAngle());
writeC(playerAppearance.getBrowShape());
writeC(playerAppearance.getNose());
writeC(playerAppearance.getNoseBridge());
writeC(playerAppearance.getNoseWidth());
writeC(playerAppearance.getNoseTip());
writeC(playerAppearance.getCheek());
writeC(playerAppearance.getLipHeight());
writeC(playerAppearance.getMouthSize());
writeC(playerAppearance.getLipSize());
writeC(playerAppearance.getSmile());
writeC(playerAppearance.getLipShape());
writeC(playerAppearance.getJawHeigh());
writeC(playerAppearance.getChinJut());
writeC(playerAppearance.getEarShape());
writeC(playerAppearance.getHeadSize());
// 1.5.x 0x00, shoulderSize, armLength, legLength (BYTE) after HeadSize
writeC(playerAppearance.getNeck());
writeC(playerAppearance.getNeckLength());
writeC(playerAppearance.getShoulderSize());
writeC(playerAppearance.getTorso());
writeC(playerAppearance.getChest());
writeC(playerAppearance.getWaist());
writeC(playerAppearance.getHips());
writeC(playerAppearance.getArmThickness());
writeC(playerAppearance.getHandSize());
writeC(playerAppearance.getLegThickness());
writeC(playerAppearance.getFootSize());
writeC(playerAppearance.getFacialRate());
writeC(0x00); // 0x00
writeC(playerAppearance.getArmLength());
writeC(playerAppearance.getLegLength());
writeC(playerAppearance.getShoulders());
writeC(playerAppearance.getFaceShape());
writeC(0x00); // always 0 may be acessLevel
writeC(0x00); // sometimes 0xC7 (199) for all chars, else 0
writeC(0x00); // sometimes 0x04 (4) for all chars, else 0
writeF(playerAppearance.getHeight());
writeD(pcd.getTemplateId());
writeD(pcd.getMapId()); // mapid for preloading map
writeF(pcd.getX());
writeF(pcd.getY());
writeF(pcd.getZ());
writeD(pcd.getHeading());
writeH(pcd.getLevel());
writeH(0); // unk 2.5
writeD(pcd.getTitleId());
writeD(accPlData.isLegionMember() ? accPlData.getLegion().getLegionId() : 0);
writeS(accPlData.isLegionMember() ? accPlData.getLegion().getName() : null, 40);
writeH(accPlData.isLegionMember() ? 1 : 0);
writeD(pcd.getLastOnlineEpochSeconds());
for (int i = 0; i < 16; i++) { // 16 items is always expected by the client...
PlayerAccountData.VisibleItem item = i < accPlData.getVisibleItems().size() ? accPlData.getVisibleItems().get(i) : null;
writeC(item == null ? 0 : item.slotType()); // 0 = not visible, 1 = default (right-hand) slot, 2 = secondary (left-hand) slot
writeD(item == null ? 0 : item.itemId());
writeD(item == null ? 0 : item.godStoneId());
writeDyeInfo(item == null ? null : item.color());
}
writeD(0);
writeD(0);
writeD(0); // 4.5
writeD(0); // 4.5
writeD(0); // 4.5
writeD(0); // 4.5
writeB(new byte[68]); // 4.7
writeD(accPlData.getDeletionTimeInSeconds());
writeH(PlayerSettingsDAO.loadSettings(playerId).getDisplay()); // display helmet 0 show, 5 dont show , possible bit operation
writeH(0);
writeD(0); // total mail count
writeD(MailDAO.haveUnread(playerId) ? 1 : 0); // unread mail count
writeD(0); // express mail count
writeD(0); // blackcloud mail count
writeQ(BrokerService.getInstance().getEarnedKinahFromSoldItems(pcd)); // collected money from broker
writeD(0);
writeD(0);
writeD(0);
writeD(0);
writeD(0);
writeD(cbi == null ? 0 : (int) cbi.getStart()); // startPunishDate
writeD(cbi == null ? 0 : (int) cbi.getEnd()); // endPunishDate
writeS(cbi == null ? "" : cbi.getReason());
}
@SuppressWarnings("lossy-conversions")
protected void writeEquippedItems(List<Item> items) {
int mask = 0;
for (Item item : items) {
mask |= item.getEquipmentSlot();
// remove sub hand mask bits (sub hand is present on TwoHandeds by default and would produce display bugs)
if (ItemSlot.isTwoHandedWeapon(item.getEquipmentSlot()))
mask &= ~ItemSlot.SUB_HAND.getSlotIdMask();
}
writeD(mask);
for (Item item : items) {
writeD(item.getItemSkinTemplate().getTemplateId());
writeD(item.getGodStoneId());
writeDyeInfo(item.getItemColor());
writeH(item.getItemEnchantParam());
writeH(0); // 4.7
}
}
private CharacterBanInfo getCharBanInfo(PlayerAccountData playerAccountData, AionConnection con) {
CharacterBanInfo cbi = playerAccountData.getCharBanInfo();
long nowSeconds = System.currentTimeMillis() / 1000;
if (cbi != null && nowSeconds >= cbi.getEnd())
cbi = null;
if (cbi == null && SecurityConfig.MULTI_CLIENTING_RESTRICTION_MODE == SecurityConfig.MultiClientingRestrictionMode.SAME_FACTION) {
int cdMinutes = SecurityConfig.MULTI_CLIENTING_FACTION_SWITCH_COOLDOWN_MINUTES;
if (cdMinutes > 0 && MultiClientingService.checkForFactionSwitchCooldownTime(playerAccountData.getPlayerCommonData().getRace(), con) != null) {
int durationSeconds = 61; // client will send CM_CHARACTER_LIST after this duration to update the ban info (<61s corrupts the ban info)
cbi = new CharacterBanInfo(nowSeconds, durationSeconds, "\n\n\n\uE026 " + cdMinutes + " minute cooldown between switching factions\n\n\n\n\n\n\n");
}
}
return cbi;
}
}