• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

TFS 1.X+ Help with protocollogin piece of code tfs 1.2

Manigold

Active Member
Joined
Nov 2, 2017
Messages
197
Solutions
8
Reaction score
47
I am trying to convert some old code from a multiworld system to tfs 1.2, but I am stuck at the last part. I tried all day but every attempt resulted in the client crashing.
It is only the protocollogin.cpp part that is very different from the one I am using(mine don't have addWorldInfo function). I hope someone can help me.
And here are the codes if anyone is interested in taking a look.(just missing the protocollogin changes).
This is my getCharacterlist function:
C++:
void ProtocolLogin::getCharacterList(uint32_t accountName, const std::string& password)
{
    uint32_t serverIp = serverIPs[0].first;
    for (uint32_t i = 0; i < serverIPs.size(); i++) {
        if (getConnection()) {
            if ((serverIPs[i].first & serverIPs[i].second) == (getConnection()->getIP() & serverIPs[i].second)) {
                serverIp = serverIPs[i].first;
                break;
            }
        }
    }

    Account account;
    if (!IOLoginData::loginserverAuthentication(accountName, password, account)) {
        disconnectClient("Account number or password is not correct.");
        return;
    }

    auto output = OutputMessagePool::getOutputMessage();
    //Update premium days
    Game::updatePremium(account);

    const std::string& motd = g_config.getString(ConfigManager::MOTD);
    if (!motd.empty()) {
        //Add MOTD
        output->addByte(0x14);

        std::ostringstream ss;
        ss << g_game.getMotdNum() << "\n" << motd;
        output->addString(ss.str());
    }

    //Add char list
    output->addByte(0x64);

    uint8_t size = std::min<size_t>(std::numeric_limits<uint8_t>::max(), account.characters.size());
    output->addByte(size);
    for (uint8_t i = 0; i < size; i++) {
        output->addString(account.characters[i]);
        output->addString(g_config.getString(ConfigManager::SERVER_NAME));
        output->add<uint32_t>(serverIp);
        output->add<uint16_t>(g_config.getNumber(ConfigManager::GAME_PORT));
    }

    //Add premium days
    if (g_config.getBoolean(ConfigManager::FREE_PREMIUM)) {
        output->add<uint16_t>(0xFFFF); //client displays free premium
    } else {
        output->add<uint16_t>(account.premiumDays);
    }

    send(output);

    disconnect();
}

and this is the one i'm struggling to convert:
C++:
void ProtocolLogin::addWorldInfo(OutputMessage_ptr& output, const std::string& accountName, const std::string& password, uint16_t version, bool isLiveCastLogin /*=false*/)
{
    const std::string& motd = g_config.getString(ConfigManager::MOTD);
    if (!motd.empty()) {
        //Add MOTD
        output->addByte(0x14);
        std::ostringstream ss;
        ss << g_game.getMotdNum() << "\n" << motd;
        output->addString(ss.str());
    }
    //Add session key
    output->addByte(0x28);
    output->addString(accountName + "\n" + password);
    //Add char list
    output->addByte(0x64);

    World world;
    if (!IOLoginData::loadWorlds(world)) {
        disconnectClient("Game worlds are not working, please contact the server admin.", version);
        return;
    }

    uint8_t size = std::min<size_t>(std::numeric_limits<uint8_t>::max(), world.id.size());
    output->addByte(size); // number of worlds
    for (uint8_t i = 0; i < size; i++) {
        output->addByte(world.id[i]); // world id
        output->addString(world.name[i]);
        output->addString(world.ip[i]);
        if (isLiveCastLogin) {   //<-- This part is uselles for me, can be removed
            output->add<uint16_t>(world.port[i] + 1000);
        } else {
            output->add<uint16_t>(world.port[i]);
        }
        output->addByte(world.previewer[i]);
    }
}

void ProtocolLogin::getCharacterList(const std::string& accountName, const std::string& password, const std::string& token, uint16_t version)
{
    //dispatcher thread
    Account account;
    if (!IOLoginData::loginserverAuthentication(accountName, password, account)) {
        disconnectClient("Account name or password is not correct.", version);
        return;
    }
    
    auto output = OutputMessagePool::getOutputMessage();
    if (!account.key.empty()) {
         int32_t ticks = static_cast<int32_t>(time(nullptr) / AUTHENTICATOR_PERIOD);
         if (token.empty() || !(token == generateToken(account.key, ticks) || token == generateToken(account.key, ticks - 1) || token == generateToken(account.key, ticks + 1))) {
             output->addByte(0x0D);
             output->addByte(0);
             send(output);
             disconnect();
             return;
         }
         output->addByte(0x0C);
         output->addByte(0);
     }
 
    //Update premium days
    Game::updatePremium(account);
    
    addWorldInfo(output, accountName, password, version);
    uint8_t size = std::min<size_t>(std::numeric_limits<uint8_t>::max(), account.characters.size());
    output->addByte(size);
    for (uint8_t i = 0; i < size; i++) {
        output->addByte(account.world[i]);
        output->addString(account.characters[i]);
    }

    //Add premium days
    output->addByte(0);//0 = normal (free/premium), 1 = frozen, 2 = suspended
    output->addByte(g_config.getBoolean(ConfigManager::FREE_PREMIUM) || account.premiumDays > 0);
    output->add<uint32_t>(g_config.getBoolean(ConfigManager::FREE_PREMIUM) ? 0 : (time(nullptr) + (account.premiumDays * 24 * 60 * 60)));

    send(output);

    disconnect();
}
 
Back
Top