void ProtocolGame::login(const std::string& name, uint32_t accountId, OperatingSystem_t operatingSystem)
{
// OTCv8 features and extended opcodes
if (otclientV8 || operatingSystem >= CLIENTOS_OTCLIENT_LINUX) {
if (otclientV8)
sendFeatures();
}
//dispatcher thread
Player* foundPlayer = g_game.getPlayerByName(name);
if (!foundPlayer || g_config.getBoolean(ConfigManager::ALLOW_CLONES)) {
player = new Player(getThis());
player->setName(name);
player->incrementReferenceCounter();
player->setID();
if (!IOLoginData::preloadPlayer(player, name)) {
disconnectClient("Your character could not be loaded.");
return;
}
if (IOBan::isPlayerNamelocked(player->getGUID())) {
disconnectClient("Your character has been namelocked.");
return;
}
if (g_game.getGameState() == GAME_STATE_CLOSING && !player->hasFlag(PlayerFlag_CanAlwaysLogin)) {
disconnectClient("The game is just going down.\nPlease try again later.");
return;
}
if (g_game.getGameState() == GAME_STATE_CLOSED && !player->hasFlag(PlayerFlag_CanAlwaysLogin)) {
disconnectClient("Server is currently closed.\nPlease try again later.");
return;
}
//warning no config lua option change in this add codes below instead.
if (!player->isPremium()) {
disconnectClient("You need to be premium account to play on this world.");
return;
}
if (g_config.getBoolean(ConfigManager::ONE_PLAYER_ON_ACCOUNT) && player->getAccountType() < ACCOUNT_TYPE_GAMEMASTER && g_game.getPlayerByAccount(player->getAccount())) {
disconnectClient("You may only login with one character\nof your account at the same time.");
return;
}
if (!player->hasFlag(PlayerFlag_CannotBeBanned)) {
BanInfo banInfo;
if (IOBan::isAccountBanned(accountId, banInfo)) {
if (banInfo.reason.empty()) {
banInfo.reason = "(none)";
}
if (banInfo.expiresAt > 0) {
disconnectClient(fmt::format("Your account has been banned until {:s} by {:s}.\n\nReason specified:\n{:s}", formatDateShort(banInfo.expiresAt), banInfo.bannedBy, banInfo.reason));
} else {
disconnectClient(fmt::format("Your account has been permanently banned by {:s}.\n\nReason specified:\n{:s}", banInfo.bannedBy, banInfo.reason));
}
return;
}
}
if (std::size_t currentSlot = clientLogin(*player)) {
uint8_t retryTime = getWaitTime(currentSlot);
auto output = OutputMessagePool::getOutputMessage();
output->addByte(0x16);
output->addString(fmt::format("Too many players online.\nYou are at place {:d} on the waiting list.", currentSlot));
output->addByte(retryTime);
send(output);
disconnect();
return;
}
if (!IOLoginData::loadPlayerById(player, player->getGUID())) {
disconnectClient("Your character could not be loaded.");
return;
}
player->setOperatingSystem(operatingSystem);
if (!g_game.placeCreature(player, player->getLoginPosition())) {
if (!g_game.placeCreature(player, player->getTemplePosition(), false, true)) {
disconnectClient("Temple position is wrong. Contact the administrator.");
return;
}
}
if (operatingSystem >= CLIENTOS_OTCLIENT_LINUX) {
player->registerCreatureEvent("ExtendedOpcode");
}
player->lastIP = player->getIP();
player->lastLoginSaved = std::max<time_t>(time(nullptr), player->lastLoginSaved + 1);
acceptPackets = true;
} else {
if (eventConnect != 0 || !g_config.getBoolean(ConfigManager::REPLACE_KICK_ON_LOGIN)) {
//Already trying to connect
disconnectClient("You are already logged in.");
return;
}
if (foundPlayer->client) {
foundPlayer->disconnect();
foundPlayer->isConnecting = true;
eventConnect = g_scheduler.addEvent(createSchedulerTask(1000, std::bind(&ProtocolGame::connect, getThis(), foundPlayer->getID(), operatingSystem)));
} else {
connect(foundPlayer->getID(), operatingSystem);
}
}
OutputMessagePool::getInstance().addProtocolToAutosend(shared_from_this());
}