示例#1
0
void CharServerHandler::processCharLogin(Net::MessageIn &msg)
{
    msg.skip(2, "packet len");
    const int slots = msg.readInt8("MAX_CHARS");
    msg.readInt8("sd->char_slots");
    msg.readInt8("MAX_CHARS");
    loginData.characterSlots = static_cast<uint16_t>(slots);

    msg.skip(20, "unused 0");

    delete_all(mCharacters);
    mCharacters.clear();

    // Derive number of characters from message length
    const int count = (msg.getLength() - 27)
        / (106 + 4 + 2 + 16 + 4 + 4 + 4 + 4);

    for (int i = 0; i < count; ++i)
    {
        Net::Character *const character = new Net::Character;
        readPlayerData(msg, character);
        mCharacters.push_back(character);
        if (character->dummy)
        {
            logger->log("CharServer: Player: %s (%d)",
                character->dummy->getName().c_str(), character->slot);
        }
    }

    client->setState(STATE_CHAR_SELECT);
}
示例#2
0
void CharServerHandler::processCharLogin(Net::MessageIn &msg)
{
    msg.skip(2);  // Length word
    int slots = msg.readInt16();
    if (slots > 0 && slots < 30)
        loginData.characterSlots = static_cast<short unsigned int>(slots);

    bool version = msg.readInt8() == 1 && serverVersion > 0;
    msg.skip(17); // 0 Unused

    delete_all(mCharacters);
    mCharacters.clear();

    // Derive number of characters from message length
    int count = (msg.getLength() - 24);
    if (version)
        count /= 120;
    else
        count /= 106;

    for (int i = 0; i < count; ++i)
    {
        Net::Character *character = new Net::Character;
        readPlayerData(msg, character, version);
        mCharacters.push_back(character);
        if (character && character->dummy)
        {
            logger->log("CharServer: Player: %s (%d)",
                character->dummy->getName().c_str(), character->slot);
        }
    }

    Client::setState(STATE_CHAR_SELECT);
}
示例#3
0
void PartyHandler::processPartyMove(Net::MessageIn &msg)
{
    int id = msg.readInt32();    // id
    PartyMember *m = nullptr;
    if (Ea::taParty)
        m = Ea::taParty->getMember(id);
    if (m)
    {
        msg.skip(4);        // 0
        m->setX(msg.readInt16());    // x
        m->setY(msg.readInt16());    // y
        m->setOnline(msg.readInt8());     // online (if 0)
        msg.readString(24); // party
        msg.readString(24); // nick
        m->setMap(msg.readString(16)); // map
    }
    else
    {
        msg.skip(4);        // 0
        msg.readInt16();    // x
        msg.readInt16();    // y
        msg.readInt8();     // online (if 0)
        msg.readString(24); // party
        msg.readString(24); // nick
        msg.readString(16); // map
    }
}
void CharServerHandler::processCharLogin(Net::MessageIn &msg)
{
    msg.skip(2);  // Length word
    const int slots = msg.readInt16();
    if (slots > 0 && slots < 30)
        loginData.characterSlots = static_cast<uint16_t>(slots);

    msg.skip(18);  // 0 Unused

    delete_all(mCharacters);
    mCharacters.clear();

    // Derive number of characters from message length
    const int count = (msg.getLength() - 24) / 106;

    for (int i = 0; i < count; ++i)
    {
        Net::Character *const character = new Net::Character;
        readPlayerData(msg, character, false);
        mCharacters.push_back(character);
        if (character->dummy)
        {
            logger->log("CharServer: Player: %s (%d)",
                character->dummy->getName().c_str(), character->slot);
        }
    }

    client->setState(STATE_CHAR_SELECT);
}
void SkillHandler::processPlayerSkills(Net::MessageIn &msg) const
{
    msg.readInt16();  // length
    const int skillCount = (msg.getLength() - 4) / 37;
    int updateSkill = 0;

    for (int k = 0; k < skillCount; k++)
    {
        const int skillId = msg.readInt16();
        msg.readInt16();  // target type
        msg.skip(2);  // skill pool flags
        const int level = msg.readInt16();
        msg.readInt16();  // sp
        const int range = msg.readInt16();
        msg.skip(24);  // 0 unused
        const int up = msg.readInt8();
        const int oldLevel = PlayerInfo::getSkillLevel(skillId);
        if (oldLevel && oldLevel != level)
            updateSkill = skillId;
        PlayerInfo::setSkillLevel(skillId, level);
        if (skillDialog)
        {
            if (!skillDialog->updateSkill(skillId, range, up))
                skillDialog->addSkill(skillId, level, range, up);
        }
    }
    if (updateSkill && skillDialog)
        skillDialog->playUpdateEffect(updateSkill);
}
示例#6
0
void ItemHandler::handleMessage(Net::MessageIn &msg)
{
    switch (msg.getId())
    {
    case SMSG_ITEM_VISIBLE:
    case SMSG_ITEM_DROPPED:
    {
        int id = msg.readInt32();
        int itemId = msg.readInt16();
        msg.readInt8();  // identify flag
        int x = msg.readInt16();
        int y = msg.readInt16();
        msg.skip(4);     // amount,subX,subY / subX,subY,amount

        Game *game = Game::instance();
        if (!game)
            break;

        if (Map *map = game->getCurrentMap())
            actorSpriteManager->createItem(id, itemId,
                                           map->getTileCenter(x, y));
    }
    break;

    case SMSG_ITEM_REMOVE:
        if (FloorItem *item = actorSpriteManager->findItem(msg.readInt32()))
            actorSpriteManager->destroy(item);
        break;
    }
}
示例#7
0
void CharServerHandler::readPlayerData(Net::MessageIn &msg, Net::Character *character)
{
    const Token &token =
            static_cast<LoginHandler*>(Net::getLoginHandler())->getToken();

    LocalPlayer *tempPlayer = new LocalPlayer(msg.readInt32(), 0);
    tempPlayer->setGender(token.sex);

    character->data.mAttributes[EXP] = msg.readInt32();
    character->data.mAttributes[MONEY] = msg.readInt32();
    character->data.mStats[JOB].exp = msg.readInt32();

    int temp = msg.readInt32();
    character->data.mStats[JOB].base = temp;
    character->data.mStats[JOB].mod = temp;

    tempPlayer->setSprite(SPRITE_SHOE, msg.readInt16());
    tempPlayer->setSprite(SPRITE_GLOVES, msg.readInt16());
    tempPlayer->setSprite(SPRITE_CAPE, msg.readInt16());
    tempPlayer->setSprite(SPRITE_MISC1, msg.readInt16());

    msg.readInt32();                       // option
    msg.readInt32();                       // karma
    msg.readInt32();                       // manner
    msg.skip(2);                          // unknown

    character->data.mAttributes[HP] = msg.readInt16();
    character->data.mAttributes[MAX_HP] = msg.readInt16();
    character->data.mAttributes[MP] = msg.readInt16();
    character->data.mAttributes[MAX_MP] = msg.readInt16();

    msg.readInt16();                       // speed
    tempPlayer->setSubtype(msg.readInt16()); // class (used for race)
    int hairStyle = msg.readInt16();
    Uint16 weapon = msg.readInt16();
    tempPlayer->setSprite(SPRITE_WEAPON, weapon, "", true);

    character->data.mAttributes[LEVEL] = msg.readInt16();

    msg.readInt16();                       // skill point
    tempPlayer->setSprite(SPRITE_BOTTOMCLOTHES, msg.readInt16()); // head bottom
    tempPlayer->setSprite(SPRITE_SHIELD, msg.readInt16());
    tempPlayer->setSprite(SPRITE_HAT, msg.readInt16()); // head option top
    tempPlayer->setSprite(SPRITE_TOPCLOTHES, msg.readInt16()); // head option mid
    tempPlayer->setSprite(SPRITE_HAIR, hairStyle * -1,
                          hairDB.getHairColor(msg.readInt16()));
    tempPlayer->setSprite(SPRITE_MISC2, msg.readInt16());
    tempPlayer->setName(msg.readString(24));

    character->dummy = tempPlayer;

    for (int i = 0; i < 6; i++)
        character->data.mStats[i + STRENGTH].base = msg.readInt8();

    character->slot = msg.readInt8(); // character slot
    msg.readInt8();                        // unknown
}
void GuildHandler::processGuildEmblem(Net::MessageIn &msg) const
{
    const int length = msg.readInt16();

    msg.readInt32();  // Guild ID
    msg.readInt32();  // Emblem ID
    if (length < 12)
        return;
    msg.skip(length - 12);  // Emblem data (unknown format)
}
void GuildHandler::processGuildExpulsion(Net::MessageIn &msg) const
{
    msg.skip(2);    // size (can be many explusions in list)
    const std::string nick = msg.readString(24);  // Name (of expulsed?)
    msg.skip(24);        // acc
    msg.readString(44);  // Message
    if (taGuild)
        taGuild->removeMember(nick);

    if (!player_node)
        return;

    if (nick == player_node->getName())
    {
        if (taGuild)
        {
            taGuild->removeFromMembers();
            taGuild->clearMembers();
        }
        NotifyManager::notify(NotifyManager::GUILD_KICKED);
        delete guildTab;
        guildTab = nullptr;

        if (socialWindow && taGuild)
            socialWindow->removeTab(taGuild);
        if (actorManager)
            actorManager->updatePlayerColors();
    }
    else
    {
        NotifyManager::notify(NotifyManager::GUILD_USER_KICKED, nick);
        if (actorManager)
        {
            Being *const b = actorManager->findBeingByName(
                nick, Being::PLAYER);

            if (b)
                b->clearGuilds();
            if (taGuild)
                taGuild->removeMember(nick);
        }
    }
}
示例#10
0
void GuildHandler::processGuildBasicInfo(Net::MessageIn &msg)
{
    const int guildId = msg.readInt32("guild id");
    const int level = msg.readInt32("guild level");
    const int members = msg.readInt32("connect member");
    const int maxMembers = msg.readInt32("max member");
    const int avgLevel = msg.readInt32("average level");
    const int exp = msg.readInt32("exp");
    const int nextExp = msg.readInt32("next exp");
    msg.skip(12, "unused");
    const int emblem = msg.readInt32("emblem id");
    std::string name = msg.readString(24, "guild name");
    std::string master = msg.readString(24, "master name");
    std::string castle = msg.readString(16, "castles");
    msg.readInt32("unused");

    if (guildTab && showBasicInfo)
    {
        showBasicInfo = false;
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild name: %s"),
            name.c_str()), ChatMsgType::BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild master: %s"),
            master.c_str()), ChatMsgType::BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild level: %d"), level),
            ChatMsgType::BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Online members: %d"),
            members), ChatMsgType::BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Max members: %d"),
            maxMembers), ChatMsgType::BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Average level: %d"),
            avgLevel), ChatMsgType::BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild exp: %d"), exp),
            ChatMsgType::BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild next exp: %d"),
            nextExp), ChatMsgType::BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild castle: %s"),
            castle.c_str()), ChatMsgType::BY_SERVER);
    }

    Guild *const g = Guild::getGuild(static_cast<int16_t>(guildId));
    if (!g)
        return;
    g->setName(name);
    g->setEmblemId(emblem);
}
示例#11
0
void CharServerRecv::processCharLogin2(Net::MessageIn &msg)
{
    // ignored
    msg.readInt16("len");
    msg.readUInt8("char slots");
    msg.readUInt8("left slots");
    msg.readUInt8("left slots");
    msg.readUInt8("char slots");
    msg.readUInt8("char slots");
    msg.skip(20, "unused");
}
示例#12
0
void GuildRecv::processGuildEmblemData(Net::MessageIn &msg)
{
    UNIMPLEMENTEDPACKET;
    const int length = msg.readInt16("len");

    msg.readInt32("guild id");
    msg.readInt32("emblem id");
    if (length < 12)
        return;
    msg.skip(length - 12, "emblem data");
}
示例#13
0
void LoginHandler::processLoginData(Net::MessageIn &msg)
{
    // Skip the length word
    msg.skip(2);    // size

    clearWorlds();

    const int worldCount = (msg.getLength() - 47) / 32;

    mToken.session_ID1 = msg.readInt32();
    mToken.account_ID = msg.readInt32();
    mToken.session_ID2 = msg.readInt32();
    msg.skip(4);                           // old ip
    loginData.lastLogin = msg.readString(24);
    msg.skip(2);                           // 0 unused bytes

//    msg.skip(30);                           // unknown
    // reserve bits for future usage
    mToken.sex = Being::intToGender(static_cast<uint8_t>(
        msg.readUInt8() & 3U));

    for (int i = 0; i < worldCount; i++)
    {
        WorldInfo *const world = new WorldInfo;

        world->address = msg.readInt32();
        world->port = msg.readInt16();
        world->name = msg.readString(20);
        world->online_users = msg.readInt16();
        config.setValue("updatehost", mUpdateHost);
        world->updateHost = mUpdateHost;
        msg.skip(2);                        // maintenance
        msg.skip(2);                        // new

        logger->log("Network: Server: %s (%s:%d)", world->name.c_str(),
            ipToString(world->address), world->port);

        mWorlds.push_back(world);
    }
    client->setState(STATE_WORLD_SELECT);
}
示例#14
0
void PlayerHandler::processPlayerShortcuts(Net::MessageIn &msg)
{
    // +++ player shortcuts ignored. It also disabled on server side.
    // may be in future better use it?
    msg.readUInt8("unused?");
    for (int f = 0; f < 27; f ++)
    {
        msg.readUInt8("type 0: item, 1: skill");
        msg.readInt32("item or skill id");
        msg.readInt16("skill level");
    }
    msg.skip(77, "unused");
}
void GuildHandler::processGuildBasicInfo(Net::MessageIn &msg)
{
    const int guildId = msg.readInt32();      // Guild ID
    const int level = msg.readInt32();        // Guild level
    const int members = msg.readInt32();      // 'Connect member'
    const int maxMembers = msg.readInt32();   // 'Max member'
    const int avgLevel = msg.readInt32();     // Average level
    const int exp = msg.readInt32();          // Exp
    const int nextExp = msg.readInt32();      // Next exp
    msg.skip(16);                             // 0 unused
    std::string name = msg.readString(24);    // Name
    std::string master = msg.readString(24);  // Master's name
    std::string castle = msg.readString(20);  // Castles
                            // (ie: "Six Castles" or "None Taken")

    if (guildTab && showBasicInfo)
    {
        showBasicInfo = false;
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild name: %s"),
            name.c_str()), BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild master: %s"),
            master.c_str()), BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild level: %d"), level), BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Online members: %d"),
            members), BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Max members: %d"),
            maxMembers), BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Average level: %d"),
            avgLevel), BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild exp: %d"), exp), BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild next exp: %d"),
            nextExp), BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild castle: %s"),
            castle.c_str()), BY_SERVER);
    }

    Guild *const g = Guild::getGuild(static_cast<int16_t>(guildId));
    if (!g)
        return;
    g->setName(name);
}
void GuildHandler::processGuildSkillInfo(Net::MessageIn &msg) const
{
    const int length = msg.readInt16();
    const int count = (length - 6) / 37;

    msg.readInt16();  // 'Skill point'

    if (length < 6)
        return;
    for (int i = 0; i < count; i++)
    {
        msg.readInt16();  // ID
        msg.readInt16();  // 'Info' (unknown atm)
        msg.readInt16();  // 0 unused
        msg.readInt16();  // Level
        msg.readInt16();  // SP
        msg.readInt16();  // 'Range'
        msg.skip(24);     // 0 unused
        msg.readInt8();   // Can be increased
    }
}
示例#17
0
void SkillRecv::processPlayerSkills(Net::MessageIn &msg)
{
    msg.readInt16("len");
    const int skillCount = (msg.getLength() - 4) / 37;
    int updateSkill = 0;

    for (int k = 0; k < skillCount; k++)
    {
        const int skillId = msg.readInt16("skill id");
        const SkillType::SkillType inf = static_cast<SkillType::SkillType>(
            msg.readInt16("inf"));
        msg.readInt16("skill pool flags");
        const int level = msg.readInt16("skill level");
        const int sp = msg.readInt16("sp");
        const int range = msg.readInt16("range");
        msg.skip(24, "unused");
        const Modifiable up = fromBool(msg.readUInt8("up flag"), Modifiable);
        const int oldLevel = PlayerInfo::getSkillLevel(skillId);
        if (oldLevel && oldLevel != level)
            updateSkill = skillId;
        PlayerInfo::setSkillLevel(skillId, level);
        if (skillDialog)
        {
            if (!skillDialog->updateSkill(skillId, range, up, inf, sp))
            {
                skillDialog->addSkill(SkillOwner::Player,
                    skillId, "", level, range, up, inf, sp);
            }
        }
    }
    if (skillDialog)
    {
        skillDialog->update();
        if (updateSkill)
            skillDialog->playUpdateEffect(updateSkill);
    }
}
示例#18
0
void ItemHandler::handleMessage(Net::MessageIn &msg)
{
    switch (msg.getId())
    {
        case SMSG_ITEM_VISIBLE:
        case SMSG_ITEM_DROPPED:
            {
                int id = msg.readInt32();
                int itemId = msg.readInt16();
                msg.readInt8();  // identify flag
                int x = msg.readInt16();
                int y = msg.readInt16();
                msg.skip(4);     // amount,subX,subY / subX,subY,amount

                actorSpriteManager->createItem(id, itemId, x, y);
            }
            break;

        case SMSG_ITEM_REMOVE:
            if (FloorItem *item = actorSpriteManager->findItem(msg.readInt32()))
                actorSpriteManager->destroy(item);
            break;
    }
}
示例#19
0
void GuildRecv::processGuildBasicInfo(Net::MessageIn &msg)
{
    const int guildId = msg.readInt32("guild id");
    const int level = msg.readInt32("guild level");
    const int members = msg.readInt32("connect member");
    const int maxMembers = msg.readInt32("max member");
    const int avgLevel = msg.readInt32("average level");
    const int exp = msg.readInt32("exp");
    const int nextExp = msg.readInt32("next exp");
    msg.skip(12, "unused");
    const int emblem = msg.readInt32("emblem id");
    std::string name = msg.readString(24, "guild name");
    std::string castle;
    std::string master;
    if (msg.getVersion() >= 20160622)
    {
        castle = msg.readString(16, "castles");
        msg.readInt32("money, unused");
        msg.readBeingId("leader char id");
    }
    else
    {
        master = msg.readString(24, "master name");
        castle = msg.readString(16, "castles");
        msg.readInt32("money, unused");
    }

    if (guildTab != nullptr &&
        showBasicInfo)
    {
        showBasicInfo = false;
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild name: %s"),
            name.c_str()),
            ChatMsgType::BY_SERVER,
            IgnoreRecord_false,
            TryRemoveColors_true);
        if (!master.empty())
        {
            // TRANSLATORS: guild info message
            guildTab->chatLog(strprintf(_("Guild master: %s"),
                master.c_str()),
                ChatMsgType::BY_SERVER,
                IgnoreRecord_false,
                TryRemoveColors_true);
        }
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild level: %d"), level),
            ChatMsgType::BY_SERVER,
            IgnoreRecord_false,
            TryRemoveColors_true);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Online members: %d"), members),
            ChatMsgType::BY_SERVER,
            IgnoreRecord_false,
            TryRemoveColors_true);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Max members: %d"), maxMembers),
            ChatMsgType::BY_SERVER,
            IgnoreRecord_false,
            TryRemoveColors_true);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Average level: %d"), avgLevel),
            ChatMsgType::BY_SERVER,
            IgnoreRecord_false,
            TryRemoveColors_true);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild exp: %d"), exp),
            ChatMsgType::BY_SERVER,
            IgnoreRecord_false,
            TryRemoveColors_true);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild next exp: %d"), nextExp),
            ChatMsgType::BY_SERVER,
            IgnoreRecord_false,
            TryRemoveColors_true);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild castle: %s"), castle.c_str()),
            ChatMsgType::BY_SERVER,
            IgnoreRecord_false,
            TryRemoveColors_true);
    }

    Guild *const g = Guild::getGuild(CAST_S16(guildId));
    if (g == nullptr)
        return;
    g->setName(name);
    g->setEmblemId(emblem);
}
示例#20
0
void GuildRecv::processGuildMemberList(Net::MessageIn &msg)
{
    if (actorManager == nullptr)
        return;

    const int length = msg.readInt16("len");
    if (length < 4)
        return;
    int guildSize = 0;
    if (msg.getVersion() >= 20161026)
    {
        guildSize = 34;
    }
    else
    {
        guildSize = 104;
    }

    const int count = (length - 4) / guildSize;
    if (taGuild == nullptr)
    {
        logger->log1("!taGuild");
        return;
    }

    taGuild->clearMembers();

    int onlineNum = 0;
    int totalNum = 0;
    for (int i = 0; i < count; i++)
    {
        const BeingId id = msg.readBeingId("account id");
        const int charId = msg.readInt32("char id");
        msg.readInt16("hair");
        msg.readInt16("hair color");
        const int gender = msg.readInt16("gender");
        const int race = msg.readInt16("class");
        const int level = msg.readInt16("level");
        const int exp = msg.readInt32("exp");
        const int online = msg.readInt32("online");
        const int pos = msg.readInt32("position");
        std::string name;
        if (msg.getVersion() < 20161026)
        {
            msg.skip(50, "unused");
            name = msg.readString(24, "name");
        }
        else
        {
            msg.readInt32("last login");  // for now unused
            name = actorManager->findCharById(charId);
            if (name.empty())
            {
                beingHandler->requestNameByCharId(charId);
            }
        }

        GuildMember *const m = taGuild->addMember(id, charId, name);
        if (m != nullptr)
        {
            m->setOnline(online != 0);
            m->setID(id);
            m->setCharId(charId);
            m->setGender(Being::intToGender(CAST_U8(gender)));
            m->setLevel(level);
            m->setExp(exp);
            m->setPos(pos);
            m->setRace(race);
            Being *const being = actorManager->findBeingByName(
                name, ActorType::Player);
            if (being != nullptr)
            {
                being->setGuildName(taGuild->getName());
                if (being->getLevel() != level)
                {
                    being->setLevel(level);
                    being->updateName();
                }
            }
            if (online != 0)
                onlineNum ++;
            totalNum ++;
        }
    }
    taGuild->sort();
    actorManager->updatePlayerGuild();
    actorManager->updatePlayerColors();
    if (socialWindow != nullptr)
        socialWindow->updateGuildCounter(onlineNum, totalNum);
}
示例#21
0
void TradeHandler::handleMessage(Net::MessageIn &msg)
{
    switch (msg.getId())
    {
    case SMSG_TRADE_REQUEST:
    {
        // If a trade window or request window is already open, send a
        // trade cancel to any other trade request.
        //
        // Note that it would be nice if the server would prevent this
        // situation, and that the requesting player would get a
        // special message about the player being occupied.
        std::string tradePartnerNameTemp = msg.readString(24);

        if (player_relations.hasPermission(tradePartnerName,
                                           PlayerRelation::TRADE))
        {
            if (PlayerInfo::isTrading() || confirmDlg)
            {
                Net::getTradeHandler()->respond(false);
                break;
            }

            tradePartnerName = tradePartnerNameTemp;
            PlayerInfo::setTrading(true);
            confirmDlg = new ConfirmDialog(_("Request for Trade"),
                                           strprintf(_("%s wants to trade with you, do you "
                                                   "accept?"), tradePartnerName.c_str()));
            confirmDlg->addActionListener(&listener);
        }
        else
        {
            Net::getTradeHandler()->respond(false);
            break;
        }
    }
    break;

    case SMSG_TRADE_RESPONSE:
        switch (msg.readInt8())
        {
        case 0: // Too far away
            SERVER_NOTICE(_("Trading isn't possible. Trade "
                            "partner is too far away."))
            break;
        case 1: // Character doesn't exist
            SERVER_NOTICE(_("Trading isn't possible. Character "
                            "doesn't exist."))
            break;
        case 2: // Invite request check failed...
            SERVER_NOTICE(_("Trade cancelled due to an unknown "
                            "reason."))
            break;
        case 3: // Trade accepted
            tradeWindow->reset();
            tradeWindow->setCaption(strprintf(_("Trade: You and %s"),
                                              tradePartnerName.c_str()));
            tradeWindow->setVisible(true);
            break;
        case 4: // Trade cancelled
            if (player_relations.hasPermission(tradePartnerName,
                                               PlayerRelation::SPEECH_LOG))
                SERVER_NOTICE(strprintf(_("Trade with %s cancelled."),
                                        tradePartnerName.c_str()))
                // otherwise ignore silently

                tradeWindow->setVisible(false);
            PlayerInfo::setTrading(false);
            break;
        default: // Shouldn't happen as well, but to be sure
            SERVER_NOTICE(_("Unhandled trade cancel packet."))
            break;
        }
        break;

    case SMSG_TRADE_ITEM_ADD:
    {
        int amount = msg.readInt32();
        int type = msg.readInt16();
        msg.readInt8();  // identified flag
        msg.readInt8();  // attribute
        msg.readInt8();  // refine
        msg.skip(8);     // card (4 shorts)

        // TODO: handle also identified, etc
        if (type == 0)
            tradeWindow->setMoney(amount);
        else
            tradeWindow->addItem(type, false, amount);
    }
    break;

    case SMSG_TRADE_ITEM_ADD_RESPONSE:
        // Trade: New Item add response (was 0x00ea, now 01b1)
    {
        const int index = msg.readInt16() - INVENTORY_OFFSET;
        Item *item = PlayerInfo::getInventory()->getItem(index);
        if (!item)
        {
            tradeWindow->receivedOk(true);
            return;
        }
        int quantity = msg.readInt16();

        switch (msg.readInt8())
        {
        case 0:
            // Successfully added item
            if (item->isEquippable() && item->isEquipped())
            {
                item->doEvent(Event::DoUnequip);
            }
            tradeWindow->addItem(item->getId(), true, quantity);

            item->increaseQuantity(-quantity);
            break;
        case 1:
            // Add item failed - player overweighted
            SERVER_NOTICE(_("Failed adding item. Trade "
                            "partner is over weighted."))
            break;
        case 2:
            // Add item failed - player has no free slot
            SERVER_NOTICE(_("Failed adding item. Trade "
                            "partner has no free slot."))
            break;
        default:
            SERVER_NOTICE(_("Failed adding item for "
                            "unknown reason."))
            break;
        }
    }
    break;

    case SMSG_TRADE_OK:
        // 0 means ok from myself, 1 means ok from other;
        tradeWindow->receivedOk(msg.readInt8() == 0);
        break;

    case SMSG_TRADE_CANCEL:
        SERVER_NOTICE(_("Trade canceled."))
        tradeWindow->setVisible(false);
        tradeWindow->reset();
        PlayerInfo::setTrading(false);
        break;

    case SMSG_TRADE_COMPLETE:
        SERVER_NOTICE(_("Trade completed."))
        tradeWindow->setVisible(false);
        tradeWindow->reset();
        PlayerInfo::setTrading(false);
        break;
    }
}
示例#22
0
void LoginHandler::handleMessage(Net::MessageIn &msg)
{
    int code, worldCount;

    switch (msg.getId())
    {
        case SMSG_CHAR_PASSWORD_RESPONSE:
        {
            // 0: acc not found, 1: success, 2: password mismatch, 3: pass too short
            int errMsg = msg.readInt8();
            // Successful pass change
            if (errMsg == 1)
            {
                Client::setState(STATE_CHANGEPASSWORD_SUCCESS);
            }
            // pass change failed
            else
            {
                switch (errMsg)
                {
                    case 0:
                        errorMessage = _("Account was not found. Please re-login.");
                        break;
                    case 2:
                        errorMessage = _("Old password incorrect.");
                        break;
                    case 3:
                        errorMessage = _("New password too short.");
                        break;
                    default:
                        errorMessage = _("Unknown error.");
                        break;
                }
                Client::setState(STATE_ACCOUNTCHANGE_ERROR);
            }
        }
            break;

        case SMSG_UPDATE_HOST:
             int len;

             len = msg.readInt16() - 4;
             mUpdateHost = msg.readString(len);
             loginData.updateHost = mUpdateHost;

             logger->log("Received update host \"%s\" from login server.",
                     mUpdateHost.c_str());
             break;

        case SMSG_LOGIN_DATA:
            // Skip the length word
            msg.skip(2);

            clearWorlds();

            worldCount = (msg.getLength() - 47) / 32;

            mToken.session_ID1 = msg.readInt32();
            mToken.account_ID = msg.readInt32();
            mToken.session_ID2 = msg.readInt32();
            msg.skip(30);                           // unknown
            mToken.sex = msg.readInt8() ? GENDER_MALE : GENDER_FEMALE;

            for (int i = 0; i < worldCount; i++)
            {
                WorldInfo *world = new WorldInfo;

                world->address = msg.readInt32();
                world->port = msg.readInt16();
                world->name = msg.readString(20);
                world->online_users = msg.readInt32();
                world->updateHost = mUpdateHost;
                msg.skip(2);                        // unknown

                logger->log("Network: Server: %s (%s:%d)",
                        world->name.c_str(),
                        ipToString(world->address),
                        world->port);

                mWorlds.push_back(world);
            }
            Client::setState(STATE_WORLD_SELECT);
            break;

        case SMSG_LOGIN_ERROR:
            code = msg.readInt8();
            logger->log("Login::error code: %i", code);

            switch (code)
            {
                case 0:
                    errorMessage = _("Unregistered ID.");
                    break;
                case 1:
                    errorMessage = _("Wrong password.");
                    break;
                case 2:
                    errorMessage = _("Account expired.");
                    break;
                case 3:
                    errorMessage = _("Rejected from server.");
                    break;
                case 4:
                    errorMessage = _("You have been permanently banned from "
                                     "the game. Please contact the GM team.");
                    break;
                case 5:
                    errorMessage = _("Client too old.");
                    break;
                case 6:
                    errorMessage = strprintf(_("You have been temporarily "
                                               "banned from the game until "
                                               "%s.\nPlease contact the GM "
                                               "team via the forums."),
                                               msg.readString(20).c_str());
                    break;
                case 7:
                    errorMessage = _("Server overpopulated.");
                    break;
                case 9:
                    errorMessage = _("This user name is already taken.");
                    break;
                case 99:
                    errorMessage = _("Username permanently erased.");
                    break;
                default:
                    errorMessage = _("Unknown error.");
                    break;
            }
            Client::setState(STATE_ERROR);
            break;

        case SMSG_SERVER_VERSION_RESPONSE:
            {
                // TODO: verify these!

                msg.readInt8(); // -1
                msg.readInt8(); // T
                msg.readInt8(); // M
                msg.readInt8(); // W

                unsigned int options = msg.readInt32();

                mRegistrationEnabled = (options & 1);

                // Leave this last
                mVersionResponse = true;
            }
            break;
    }
}
示例#23
0
void CharServerHandler::handleMessage(Net::MessageIn &msg)
{
    switch (msg.getId())
    {
            case SMSG_CHAR_LOGIN:
            {
                msg.skip(2);  // Length word
                msg.skip(20); // Unused

                // Derive number of characters from message length
                const int count = (msg.getLength() - 24) / 106;

                for (int i = 0; i < count; ++i)
                {
                    Net::Character *character = new Net::Character;
                    readPlayerData(msg, character);
                    mCharacters.push_back(character);
                    logger->log("CharServer: Player: %s (%d)",
                                character->dummy->getName().c_str(), character->slot);
                }

                Client::setState(STATE_CHAR_SELECT);
            }
            break;

        case SMSG_CHAR_LOGIN_ERROR:
            switch (msg.readInt8())
            {
                case 0:
                    errorMessage = _("Access denied. Most likely, there are "
                                     "too many players on this server.");
                    break;
                case 1:
                    errorMessage = _("Cannot use this ID.");
                    break;
                default:
                    errorMessage = _("Unknown char-server failure.");
                    break;
            }
            Client::setState(STATE_ERROR);
            break;

        case SMSG_CHAR_CREATE_SUCCEEDED:
            {
                Net::Character *character = new Net::Character;
                readPlayerData(msg, character);
                mCharacters.push_back(character);

                updateCharSelectDialog();

                // Close the character create dialog
                if (mCharCreateDialog)
                {
                    mCharCreateDialog->scheduleDelete();
                    mCharCreateDialog = 0;
                }
            }
            break;

        case SMSG_CHAR_CREATE_FAILED:
            new OkDialog(_("Error"), _("Failed to create character. Most "
                                       "likely the name is already taken."));
            if (mCharCreateDialog)
                mCharCreateDialog->unlock();
            break;

        case SMSG_CHAR_DELETE_SUCCEEDED:
            delete mSelectedCharacter;
            mCharacters.remove(mSelectedCharacter);
            mSelectedCharacter = 0;
            updateCharSelectDialog();
            unlockCharSelectDialog();
            new OkDialog(_("Info"), _("Character deleted."));
            break;

        case SMSG_CHAR_DELETE_FAILED:
            unlockCharSelectDialog();
            new OkDialog(_("Error"), _("Failed to delete character."));
            break;

        case SMSG_CHAR_MAP_INFO:
        {
            msg.skip(4); // CharID, must be the same as player_node->charID
            GameHandler *gh = static_cast<GameHandler*>(Net::getGameHandler());
            gh->setMap(msg.readString(16));
            mapServer.hostname = ipToString(msg.readInt32());
            mapServer.port = msg.readInt16();

            // Prevent the selected local player from being deleted
            player_node = mSelectedCharacter->dummy;
            PlayerInfo::setBackend(mSelectedCharacter->data);

            mSelectedCharacter->dummy = 0;

            delete_all(mCharacters);
            mCharacters.clear();
            updateCharSelectDialog();

            mNetwork->disconnect();
            Client::setState(STATE_CONNECT_GAME);
        }
        break;

        case SMSG_CHANGE_MAP_SERVER:
        {
            GameHandler *gh = static_cast<GameHandler*>(Net::getGameHandler());
            gh->setMap(msg.readString(16));
            int x = msg.readInt16();
            int y = msg.readInt16();
            mapServer.hostname = ipToString(msg.readInt32());
            mapServer.port = msg.readInt16();

            mNetwork->disconnect();
            Client::setState(STATE_CHANGE_MAP);
            player_node->setTileCoords(x, y);
            player_node->setMap(0);
        }
        break;
    }
}
示例#24
0
void CharServerHandler::readPlayerData(Net::MessageIn &msg,
                                       Net::Character *const character,
                                       const bool withColors) const
{
    if (!character)
        return;

    const Token &token =
        static_cast<LoginHandler*>(loginHandler)->getToken();

    LocalPlayer *const tempPlayer = new LocalPlayer(
        msg.readBeingId("account id"), BeingTypeId_zero);
    tempPlayer->setGender(token.sex);

    PlayerInfoBackend &data = character->data;
    data.mAttributes[Attributes::EXP] = msg.readInt32("exp");
    data.mAttributes[Attributes::MONEY] = msg.readInt32("money");
    Stat &jobStat = data.mStats[Attributes::JOB];
    jobStat.exp = msg.readInt32("job");

    const int temp = msg.readInt32("job level");
    jobStat.base = temp;
    jobStat.mod = temp;

    const int shoes = msg.readInt16("shoes");
    const int gloves = msg.readInt16("gloves");
    const int cape = msg.readInt16("cape");
    const int misc1 = msg.readInt16("misc1");

    msg.readInt32("option");
    tempPlayer->setKarma(msg.readInt32("karma"));
    tempPlayer->setManner(msg.readInt32("manner"));
    msg.readInt16("character points left");

    data.mAttributes[Attributes::HP] = msg.readInt16("hp");
    data.mAttributes[Attributes::MAX_HP] = msg.readInt16("max hp");
    data.mAttributes[Attributes::MP] = msg.readInt16("mp");
    data.mAttributes[Attributes::MAX_MP] = msg.readInt16("max mp");

    msg.readInt16("speed");
    const uint16_t race = msg.readInt16("class");
    const uint8_t hairStyle = msg.readUInt8("hair style");
    const uint16_t look = msg.readUInt8("look");
    tempPlayer->setSubtype(fromInt(race, BeingTypeId), look);
    const uint16_t weapon = msg.readInt16("weapon");
    tempPlayer->setSprite(SPRITE_BODY, weapon, "", 1, true);

    data.mAttributes[Attributes::LEVEL] = msg.readInt16("level");

    msg.readInt16("skill point");
    const int bottomClothes = msg.readInt16("bottom clothes");
    const int shield = msg.readInt16("shield");

    const int hat = msg.readInt16("hat");
    const int topClothes = msg.readInt16("top clothes");

    const uint8_t hairColor = msg.readUInt8("hair color");
    msg.readUInt8("unused");
    tempPlayer->setSprite(SPRITE_HAIR_COLOR, hairStyle * -1,
        ItemDB::get(-hairStyle).getDyeColorsString(hairColor));
    tempPlayer->setHairColor(static_cast<unsigned char>(hairColor));

    const int misc2 = msg.readInt16("misc2");
    tempPlayer->setName(msg.readString(24, "name"));

    character->dummy = tempPlayer;

    character->data.mStats[Attributes::STR].base = msg.readUInt8("str");
    character->data.mStats[Attributes::AGI].base = msg.readUInt8("agi");
    character->data.mStats[Attributes::VIT].base = msg.readUInt8("vit");
    character->data.mStats[Attributes::INT].base = msg.readUInt8("int");
    character->data.mStats[Attributes::DEX].base = msg.readUInt8("dex");
    character->data.mStats[Attributes::LUK].base = msg.readUInt8("luk");

    if (withColors)
    {
        tempPlayer->setSprite(SPRITE_HAIR, shoes, "",
            msg.readUInt8("shoes color"));
        tempPlayer->setSprite(SPRITE_SHOES, gloves, "",
            msg.readUInt8("gloves color"));
        tempPlayer->setSprite(SPRITE_SHIELD, cape, "",
            msg.readUInt8("cape color"));
        tempPlayer->setSprite(SPRITE_HEAD_TOP, misc1, "",
            msg.readUInt8("misc1 color"));
        tempPlayer->setSprite(SPRITE_WEAPON, bottomClothes,
            "", msg.readUInt8("bottom clothes color"));
        tempPlayer->setSprite(SPRITE_FLOOR, shield, "",
            msg.readUInt8("shield color"));
        tempPlayer->setSprite(SPRITE_CLOTHES_COLOR, hat, "",
            msg.readUInt8("head option top color"));
        tempPlayer->setSprite(SPRITE_HEAD_BOTTOM, topClothes, "",
            msg.readUInt8("top clothes color"));
        tempPlayer->setSprite(SPRITE_HEAD_MID, misc2, "",
            msg.readUInt8("misc2 color"));
        msg.skip(5, "unused");
    }
    else
    {
        tempPlayer->setSprite(SPRITE_HAIR, shoes);
        tempPlayer->setSprite(SPRITE_SHOES, gloves);
        tempPlayer->setSprite(SPRITE_SHIELD, cape);
        tempPlayer->setSprite(SPRITE_HEAD_TOP, misc1);
        tempPlayer->setSprite(SPRITE_WEAPON, bottomClothes);
        tempPlayer->setSprite(SPRITE_FLOOR, shield);
        tempPlayer->setSprite(SPRITE_CLOTHES_COLOR, hat);  // head option top
        tempPlayer->setSprite(SPRITE_HEAD_BOTTOM, topClothes);
        tempPlayer->setSprite(SPRITE_HEAD_MID, misc2);
    }
    character->slot = msg.readUInt8("slot");
    msg.readUInt8("unused");
}
示例#25
0
void GuildHandler::processGuildMemberList(Net::MessageIn &msg)
{
    const int length = msg.readInt16("len");
    if (length < 4)
        return;
    const int count = (length - 4) / 104;
    if (!taGuild)
    {
        logger->log1("!taGuild");
        return;
    }

    taGuild->clearMembers();

    int onlineNum = 0;
    int totalNum = 0;
    for (int i = 0; i < count; i++)
    {
        const BeingId id = msg.readBeingId("account id");
        const int charId = msg.readInt32("char id");
        msg.readInt16("hair");
        msg.readInt16("hair color");
        const int gender = msg.readInt16("gender");
        const int race = msg.readInt16("class");
        const int level = msg.readInt16("level");
        const int exp = msg.readInt32("exp");
        const int online = msg.readInt32("online");
        const int pos = msg.readInt32("position");
        msg.skip(50, "unused");
        std::string name = msg.readString(24, "name");

        GuildMember *const m = taGuild->addMember(id, charId, name);
        if (m)
        {
            m->setOnline(online);
            m->setID(id);
            m->setCharId(charId);
            m->setGender(Being::intToGender(static_cast<uint8_t>(gender)));
            m->setLevel(level);
            m->setExp(exp);
            m->setPos(pos);
            m->setRace(race);
            if (actorManager)
            {
                Being *const being = actorManager->findBeingByName(
                    name, ActorType::Player);
                if (being)
                {
                    being->setGuildName(taGuild->getName());
                    if (being->getLevel() != level)
                    {
                        being->setLevel(level);
                        being->updateName();
                    }
                }
            }
            if (online)
                onlineNum ++;
            totalNum ++;
        }
    }
    taGuild->sort();
    if (actorManager)
    {
        actorManager->updatePlayerGuild();
        actorManager->updatePlayerColors();
    }
    if (socialWindow)
        socialWindow->updateGuildCounter(onlineNum, totalNum);
}
void GuildHandler::processGuildMemberList(Net::MessageIn &msg) const
{
    const int length = msg.readInt16();
    if (length < 4)
        return;
    const int count = (length - 4) / 104;
    if (!taGuild)
    {
        logger->log1("!taGuild");
        return;
    }

    taGuild->clearMembers();

    int onlineNum = 0;
    int totalNum = 0;
    for (int i = 0; i < count; i++)
    {
        const int id = msg.readInt32();      // Account ID
        const int charId = msg.readInt32();  // Char ID
        msg.readInt16();                     // Hair
        msg.readInt16();                     // Hair color
        const int gender = msg.readInt16();  // Gender
        const int race = msg.readInt16();    // Class
        const int level = msg.readInt16();   // Level
        const int exp = msg.readInt32();     // Exp
        const int online = msg.readInt32();  // Online
        const int pos = msg.readInt32();     // Position
        msg.skip(50);                        // 0 unused
        std::string name = msg.readString(24);  // Name

        GuildMember *const m = taGuild->addMember(id, charId, name);
        if (m)
        {
            m->setOnline(online);
            m->setID(id);
            m->setCharId(charId);
            m->setGender(Being::intToGender(static_cast<uint8_t>(gender)));
            m->setLevel(level);
            m->setExp(exp);
            m->setPos(pos);
            m->setRace(race);
            if (actorManager)
            {
                Being *const being = actorManager->findBeingByName(
                    name, Being::PLAYER);
                if (being)
                {
                    being->setGuildName(taGuild->getName());
                    if (being->getLevel() != level)
                    {
                        being->setLevel(level);
                        being->updateName();
                    }
                }
            }
            if (online)
                onlineNum ++;
            totalNum ++;
        }
    }
    taGuild->sort();
    if (actorManager)
    {
        actorManager->updatePlayerGuild();
        actorManager->updatePlayerColors();
    }
    if (socialWindow)
        socialWindow->updateGuildCounter(onlineNum, totalNum);
}
示例#27
0
void SpecialHandler::handleMessage(Net::MessageIn &msg)
{
    int skillCount;
    int skillId;

    switch (msg.getId())
    {
        case SMSG_PLAYER_SKILLS:
            msg.readInt16();  // length
            skillCount = (msg.getLength() - 4) / 37;

            for (int k = 0; k < skillCount; k++)
            {
                skillId = msg.readInt16();
                msg.readInt16();  // target type
                msg.skip(2);  // unused
                int level = msg.readInt16();
                msg.readInt16(); // sp
                msg.readInt16(); // range
                msg.skip(24); // unused
                int up = msg.readInt8();

                PlayerInfo::setStatBase(skillId, level);
                if (skillDialog)
                    skillDialog->setModifiable(skillId, up);
            }
            break;

        case SMSG_PLAYER_SKILL_UP:
            {
                skillId = msg.readInt16();
                int level = msg.readInt16();
                msg.readInt16(); // sp
                msg.readInt16(); // range
                int up = msg.readInt8();

                PlayerInfo::setStatBase(skillId, level);
                skillDialog->setModifiable(skillId, up);
            }
            break;

        case SMSG_SKILL_FAILED:
            // Action failed (ex. sit because you have not reached the
            // right level)
            skillId   = msg.readInt16();
            short bskill  = msg.readInt16();
            msg.readInt16(); // unknown
            char success = msg.readInt8();
            char reason  = msg.readInt8();
            if (success != SKILL_FAILED && bskill == BSKILL_EMOTE)
            {
                logger->log("Action: %d/%d", bskill, success);
            }

            std::string msg;
            if (success == SKILL_FAILED && skillId == SKILL_BASIC)
            {
                switch (bskill)
                {
                    case BSKILL_TRADE:
                        msg = _("Trade failed!");
                        break;
                    case BSKILL_EMOTE:
                        msg = _("Emote failed!");
                        break;
                    case BSKILL_SIT:
                        msg = _("Sit failed!");
                        break;
                    case BSKILL_CREATECHAT:
                        msg = _("Chat creating failed!");
                        break;
                    case BSKILL_JOINPARTY:
                        msg = _("Could not join party!");
                        break;
                    case BSKILL_SHOUT:
                        msg = _("Cannot shout!");
                        break;
                }

                msg += " ";

                switch (reason)
                {
                    case RFAIL_SKILLDEP:
                        msg += _("You have not yet reached a high enough lvl!");
                        break;
                    case RFAIL_INSUFHP:
                        msg += _("Insufficient HP!");
                        break;
                    case RFAIL_INSUFSP:
                        msg += _("Insufficient SP!");
                        break;
                    case RFAIL_NOMEMO:
                        msg += _("You have no memos!");
                        break;
                    case RFAIL_SKILLDELAY:
                        msg += _("You cannot do that right now!");
                        break;
                    case RFAIL_ZENY:
                        msg += _("Seems you need more money... ;-)");
                        break;
                    case RFAIL_WEAPON:
                        msg += _("You cannot use this skill with that kind of weapon!");
                        break;
                    case RFAIL_REDGEM:
                        msg += _("You need another red gem!");
                        break;
                    case RFAIL_BLUEGEM:
                        msg += _("You need another blue gem!");
                        break;
                    case RFAIL_OVERWEIGHT:
                        msg += _("You're carrying to much to do this!");
                        break;
                    default:
                        msg += _("Huh? What's that?");
                        break;
                }
            }
            else
            {
                switch (skillId)
                {
                    case SKILL_WARP :
                        msg = _("Warp failed...");
                        break;
                    case SKILL_STEAL :
                        msg = _("Could not steal anything...");
                        break;
                    case SKILL_ENVENOM :
                        msg = _("Poison had no effect...");
                        break;
                }
            }

            SERVER_NOTICE(msg)
            break;
    }
}
示例#28
0
void CharServerHandler::readPlayerData(Net::MessageIn &msg,
                                       Net::Character *character,
                                       bool withColors)
{
    if (!character)
        return;

    const Token &token =
        static_cast<LoginHandler*>(Net::getLoginHandler())->getToken();

    LocalPlayer *tempPlayer = new LocalPlayer(msg.readInt32(), 0);
    tempPlayer->setGender(token.sex);

    PlayerInfoBackend &data = character->data;
    data.mAttributes[EXP] = msg.readInt32();
    data.mAttributes[MONEY] = msg.readInt32();
    data.mStats[JOB].exp = msg.readInt32();

    int temp = msg.readInt32();
    data.mStats[JOB].base = temp;
    data.mStats[JOB].mod = temp;

    int shoes = msg.readInt16();
    int gloves = msg.readInt16();
    int cape = msg.readInt16();
    int misc1 = msg.readInt16();

    msg.readInt32();                       // option
    msg.readInt32();                       // karma
    msg.readInt32();                       // manner
    msg.readInt16();                       // character points left

    data.mAttributes[HP] = msg.readInt16();
    data.mAttributes[MAX_HP] = msg.readInt16();
    data.mAttributes[MP] = msg.readInt16();
    data.mAttributes[MAX_MP] = msg.readInt16();

    msg.readInt16();                       // speed
    tempPlayer->setSubtype(msg.readInt16()); // class (used for race)
    int hairStyle = msg.readInt16();
    uint16_t weapon = msg.readInt16();  // server not used it. may be need use?
    tempPlayer->setSprite(SPRITE_WEAPON, weapon, "", 1, true);

    data.mAttributes[LEVEL] = msg.readInt16();

    msg.readInt16();                       // skill point
    int bottomClothes = msg.readInt16();
    int shield = msg.readInt16();

    int hat = msg.readInt16(); // head option top
    int topClothes = msg.readInt16();

    tempPlayer->setSprite(SPRITE_HAIR, hairStyle * -1,
        ItemDB::get(-hairStyle).getDyeColorsString(msg.readInt16()));

    int misc2 = msg.readInt16();
    tempPlayer->setName(msg.readString(24));

    character->dummy = tempPlayer;

    for (int i = 0; i < 6; i++)
        character->data.mStats[i + STR].base = msg.readInt8();

    if (withColors)
    {
        tempPlayer->setSprite(SPRITE_SHOE, shoes, "", msg.readInt8());
        tempPlayer->setSprite(SPRITE_GLOVES, gloves, "", msg.readInt8());
        tempPlayer->setSprite(SPRITE_CAPE, cape, "", msg.readInt8());
        tempPlayer->setSprite(SPRITE_MISC1, misc1, "", msg.readInt8());
        tempPlayer->setSprite(SPRITE_BOTTOMCLOTHES, bottomClothes,
            "", msg.readInt8());
        //to avoid show error (error.xml) need remove this sprite
        if (!config.getBoolValue("hideShield"))
            tempPlayer->setSprite(SPRITE_SHIELD, shield, "", msg.readInt8());
        else
            msg.readInt8();

        tempPlayer->setSprite(SPRITE_HAT, hat, "",
            msg.readInt8()); // head option top
        tempPlayer->setSprite(SPRITE_TOPCLOTHES, topClothes, "",
            msg.readInt8());
        tempPlayer->setSprite(SPRITE_MISC2, misc2, "", msg.readInt8());
        msg.skip(5);
        character->slot = msg.readInt8(); // character slot
    }
    else
    {
        tempPlayer->setSprite(SPRITE_SHOE, shoes);
        tempPlayer->setSprite(SPRITE_GLOVES, gloves);
        tempPlayer->setSprite(SPRITE_CAPE, cape);
        tempPlayer->setSprite(SPRITE_MISC1, misc1);
        tempPlayer->setSprite(SPRITE_BOTTOMCLOTHES, bottomClothes);
        //to avoid show error (error.xml) need remove this sprite
        if (!config.getBoolValue("hideShield"))
            tempPlayer->setSprite(SPRITE_SHIELD, shield);

        tempPlayer->setSprite(SPRITE_HAT, hat); // head option top
        tempPlayer->setSprite(SPRITE_TOPCLOTHES, topClothes);
        tempPlayer->setSprite(SPRITE_MISC2, misc2);
        character->slot = msg.readInt8(); // character slot
    }

    msg.readInt8();                        // unknown
}