• 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+ Nostalrius Multiworld system

Vantoria

www.ClassicOT.us
Joined
Jun 6, 2014
Messages
181
Reaction score
14
Location
USA
hi guys i was trying to adapt this Multiworld system by aurelion5670 · Pull Request #929 · opentibiabr/otservbr-global (https://github.com/opentibiabr/otservbr-global/pull/929/files) multiworld system in nostalrius engine i think the code did adapt sucessfully because it compile good i have setup everything correctly as i know but something is giving me error in console
Lua:
Aug 19 00:27:59 tester tfs[152622]: [Error - mysql_real_query] Query: TRUNCATE TABLE `players_online` WHERE `world_id` = 3306
Aug 19 00:27:59 tester tfs[152622]: Message: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'WHERE `world_id` = 3306' at line 1
Aug 19 00:27:59 tester tfs[152622]: [Error - mysql_real_query] Query: SELECT `id`, `world_id`, `highest_bidder`, `last_bid`, (SELECT `balance` FROM `players` WHERE `players`.`id` = `highest_bidder`) AS `balance` FROM `houses` WHERE `owner` = 0 AND `world_id` = 3306 AND `bid_end` != 0 AND `bid_end` < 1597796879
Aug 19 00:27:59 tester tfs[152622]: Message: Unknown column 'world_id' in 'field list'
Aug 19 00:27:59 tester tfs[152622]: [Error - mysql_store_result] Query: SELECT `id`, `world_id`, `highest_bidder`, `last_bid`, (SELECT `balance` FROM `players` WHERE `players`.`id` = `highest_bidder`) AS `balance` FROM `houses` WHERE `owner` = 0 AND `world_id` = 3306 AND `bid_end` != 0 AND `bid_end` < 1597796879
Aug 19 00:27:59 tester tfs[152622]: Message: Commands out of sync; you can't run this command now
this is my new edited startup.lua
Lua:
function onStartup()
    math.randomseed(os.mtime())
    
    db.asyncQuery('TRUNCATE TABLE `players_online` WHERE `world_id` = '..configManager.getNumber(configKeys.WORLD_ID)..'')
    db.asyncQuery("DELETE FROM `guild_wars` WHERE `status` = 0")
    db.asyncQuery("DELETE FROM `players` WHERE `deletion` != 0 AND `deletion` < " .. os.time())
    db.asyncQuery("DELETE FROM `ip_bans` WHERE `expires_at` != 0 AND `expires_at` <= " .. os.time())

    -- Move expired bans to ban history
    local resultId = db.storeQuery("SELECT * FROM `account_bans` WHERE `expires_at` != 0 AND `expires_at` <= " .. os.time())
    if resultId ~= false then
        repeat
            local accountId = result.getDataInt(resultId, "account_id")
            db.asyncQuery("INSERT INTO `account_ban_history` (`account_id`, `reason`, `banned_at`, `expired_at`, `banned_by`) VALUES (" .. accountId .. ", " .. db.escapeString(result.getDataString(resultId, "reason")) .. ", " .. result.getDataLong(resultId, "banned_at") .. ", " .. result.getDataLong(resultId, "expires_at") .. ", " .. result.getDataInt(resultId, "banned_by") .. ")")
            db.asyncQuery("DELETE FROM `account_bans` WHERE `account_id` = " .. accountId)
        until not result.next(resultId)
        result.free(resultId)
    end

    -- Check house auctions
    local resultId = db.storeQuery('SELECT `id`, `world_id`, `highest_bidder`, `last_bid`, (SELECT `balance` FROM `players` WHERE `players`.`id` = `highest_bidder`) AS `balance` FROM `houses` WHERE `owner` = 0 AND `world_id` = '..configManager.getNumber(configKeys.WORLD_ID)..' AND `bid_end` != 0 AND `bid_end` < ' .. os.time())
    if resultId ~= false then
        repeat
            local house = House(result.getDataInt(resultId, "id"))
            if house ~= nil then
                local highestBidder = result.getDataInt(resultId, "highest_bidder")
                local balance = result.getDataLong(resultId, "balance")
                local lastBid = result.getDataInt(resultId, "last_bid")
                if balance >= lastBid then
                    db.query("UPDATE `players` SET `balance` = " .. (balance - lastBid) .. " WHERE `id` = " .. highestBidder)
                    house:setOwnerGuid(highestBidder)
                end
                db.asyncQuery('UPDATE `houses` SET `last_bid` = 0, `bid_end` = 0, `highest_bidder` = 0, `bid` = 0 WHERE `world_id` = '..configManager.getNumber(configKeys.WORLD_ID)..' and `id` = ' .. house:getId())
            end
        until not result.next(resultId)
        result.free(resultId)
    end
    
    -- Remove murders that are more than 60 days old
    local resultId = db.storeQuery("SELECT * FROM `player_murders` WHERE `date` <= " .. os.time() - 60 * 24 * 60 * 60)
    if resultId ~= false then
        repeat
            local playerId = result.getDataInt(resultId, "player_id")
            local id = result.getDataLong(resultId, "id")
            
            db.asyncQuery("DELETE FROM `player_murders` WHERE `player_id` = " .. playerId .. " AND `id` = " .. id)
        until not result.next(resultId)
        result.free(resultId)
    end
end

and this one the old startup.lua
Lua:
function onStartup()
    math.randomseed(os.mtime())
    
    db.query("TRUNCATE TABLE `players_online`")
    db.asyncQuery("DELETE FROM `guild_wars` WHERE `status` = 0")
    db.asyncQuery("DELETE FROM `players` WHERE `deletion` != 0 AND `deletion` < " .. os.time())
    db.asyncQuery("DELETE FROM `ip_bans` WHERE `expires_at` != 0 AND `expires_at` <= " .. os.time())

    -- Move expired bans to ban history
    local resultId = db.storeQuery("SELECT * FROM `account_bans` WHERE `expires_at` != 0 AND `expires_at` <= " .. os.time())
    if resultId ~= false then
        repeat
            local accountId = result.getDataInt(resultId, "account_id")
            db.asyncQuery("INSERT INTO `account_ban_history` (`account_id`, `reason`, `banned_at`, `expired_at`, `banned_by`) VALUES (" .. accountId .. ", " .. db.escapeString(result.getDataString(resultId, "reason")) .. ", " .. result.getDataLong(resultId, "banned_at") .. ", " .. result.getDataLong(resultId, "expires_at") .. ", " .. result.getDataInt(resultId, "banned_by") .. ")")
            db.asyncQuery("DELETE FROM `account_bans` WHERE `account_id` = " .. accountId)
        until not result.next(resultId)
        result.free(resultId)
    end

    -- Check house auctions
    local resultId = db.storeQuery("SELECT `id`, `highest_bidder`, `last_bid`, (SELECT `balance` FROM `players` WHERE `players`.`id` = `highest_bidder`) AS `balance` FROM `houses` WHERE `owner` = 0 AND `bid_end` != 0 AND `bid_end` < " .. os.time())
    if resultId ~= false then
        repeat
            local house = House(result.getDataInt(resultId, "id"))
            if house ~= nil then
                local highestBidder = result.getDataInt(resultId, "highest_bidder")
                local balance = result.getDataLong(resultId, "balance")
                local lastBid = result.getDataInt(resultId, "last_bid")
                if balance >= lastBid then
                    db.query("UPDATE `players` SET `balance` = " .. (balance - lastBid) .. " WHERE `id` = " .. highestBidder)
                    house:setOwnerGuid(highestBidder)
                end
                db.asyncQuery("UPDATE `houses` SET `last_bid` = 0, `bid_end` = 0, `highest_bidder` = 0, `bid` = 0 WHERE `id` = " .. house:getId())
            end
        until not result.next(resultId)
        result.free(resultId)
    end
    
    -- Remove murders that are more than 60 days old
    local resultId = db.storeQuery("SELECT * FROM `player_murders` WHERE `date` <= " .. os.time() - 60 * 24 * 60 * 60)
    if resultId ~= false then
        repeat
            local playerId = result.getDataInt(resultId, "player_id")
            local id = result.getDataLong(resultId, "id")
            
            db.asyncQuery("DELETE FROM `player_murders` WHERE `player_id` = " .. playerId .. " AND `id` = " .. id)
        until not result.next(resultId)
        result.free(resultId)
    end
end
also i can't see characterlist with otcv8 when i see console it give me this error
Code:
ERROR: protected lua call failed: C++ call failed: InputMessage eof reached
stack traceback:
    [builtin#146]: at 0x011ef230
    [C]: in function 'getString'
    /modules/gamelib/protocollogin.lua:247: in function 'parseCharacterList'
    /modules/gamelib/protocollogin.lua:178: in function </modules/gamelib/protocollogin.lua:159>
 
Solution
it is not defined but if i do it then i cant compile
Lua:
#define MULTIWORLD_SYSTEM
in definitions.h
it give me this error with no sucess on compilation
Code:
/home/otsmanager/forgottenserver/src/protocollogin.cpp: In member function ‘void ProtocolLogin::getCharacterList(uint32_t, const string&)’:
/home/otsmanager/forgottenserver/src/protocollogin.cpp:100:77: error: request for member ‘c_str’ in ‘g_gameworld.GameWorldConfig::getWorldIp(((int)((uint16_t)worldId)))’, which is of non-class type ‘const char*’
  100 |      output->add<uint32_t>(inet_addr(g_gameworld.getWorldIp(worldId).c_str()));
      |                                                                      ^~~~~
C++:
/**
* Tibia GIMUD Server - a free and open-source...
OP
OP
Vantoria

Vantoria

www.ClassicOT.us
Joined
Jun 6, 2014
Messages
181
Reaction score
14
Location
USA
C++:
/**
* Tibia GIMUD Server - a free and open-source MMORPG server emulator
* Copyright (C) 2017  Alejandro Mujica <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "otpch.h"

#include "protocollogin.h"

#include "outputmessage.h"
#include "tasks.h"

#include "configmanager.h"
#include "iologindata.h"
#include "ban.h"
#include "game.h"
#ifdef MULTIWORLD_SYSTEM
    #include "gameworldconfig.h"
#endif

extern ConfigManager g_config;
extern Game g_game;
#ifdef MULTIWORLD_SYSTEM
    extern GameWorldConfig g_gameworld;
#endif

void ProtocolLogin::sendUpdateRequest()
{
    auto output = OutputMessagePool::getOutputMessage();

    output->addByte(0x1E);
    send(output);

    disconnect();
}

void ProtocolLogin::disconnectClient(const std::string& message)
{
    auto output = OutputMessagePool::getOutputMessage();

    output->addByte(0x0A);
    output->addString(message);
    send(output);

    disconnect();
}

void ProtocolLogin::getCharacterList(uint32_t accountNumber, const std::string& password)
{
    Account account;
    if (!IOLoginData::loginserverAuthentication(accountNumber, 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());
    }
 
    output->addByte(0x64);
  
    uint8_t size = std::min<size_t>(std::numeric_limits<uint8_t>::max(), account.characters.size());
    output->addByte(size);

    #ifdef MULTIWORLD_SYSTEM
        //Add char list
        printf("multiworld is defined");

        for (uint8_t i = 0; i < size; i++) {
            output->addString(account.characters[i].name);

            const uint16_t worldId = account.characters[i].worldid;

            output->addString(g_gameworld.getWorldName(worldId));
            output->add<uint32_t>(inet_addr(g_gameworld.getWorldIp(worldId)));
            output->add<uint16_t>(g_gameworld.getWorldPort(worldId));
        }
    #else
        printf("multiworld is NOT defined");

        //Add char list
        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>(inet_addr(g_config.getString(ConfigManager::IP).c_str()));
            output->add<uint16_t>(g_config.getNumber(ConfigManager::GAME_PORT));
        }
    #endif
  
    //Add premium days
    if (g_config.getBoolean(ConfigManager::FREE_PREMIUM)) {
        output->add<uint16_t>(0xFFFF);
    } else {
        output->add<uint16_t>(account.premiumDays);
    }

    send(output);

    disconnect();
}

void ProtocolLogin::onRecvFirstMessage(NetworkMessage& msg)
{
    if (g_game.getGameState() == GAME_STATE_SHUTDOWN) {
        disconnect();
        return;
    }

    msg.skipBytes(2); // client OS

    /*uint16_t version =*/ msg.get<uint16_t>();
    msg.skipBytes(12);

    /*
     * Skipped bytes:
     * 4 bytes: protocolVersion
     * 12 bytes: dat, spr, pic signatures (4 bytes each)
     */

    if (!Protocol::RSA_decrypt(msg)) {
        disconnect();
        return;
    }

    uint32_t key[4];
    key[0] = msg.get<uint32_t>();
    key[1] = msg.get<uint32_t>();
    key[2] = msg.get<uint32_t>();
    key[3] = msg.get<uint32_t>();
    enableXTEAEncryption();
    setXTEAKey(key);

    /*if (version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX) {
        //sendUpdateRequest();
        disconnectClient("Use Tibia 7.72 to login!");
        return;
    }*/

    if (g_game.getGameState() == GAME_STATE_STARTUP) {
        disconnectClient("Gameworld is starting up. Please wait.");
        return;
    }

    if (g_game.getGameState() == GAME_STATE_MAINTAIN) {
        disconnectClient("Gameworld is under maintenance.\nPlease re-connect in a while.");
        return;
    }

    BanInfo banInfo;
    auto connection = getConnection();
    if (!connection) {
        return;
    }

    if (IOBan::isIpBanned(connection->getIP(), banInfo)) {
        if (banInfo.reason.empty()) {
            banInfo.reason = "(none)";
        }

        std::ostringstream ss;
        ss << "Your IP has been banned until " << formatDateShort(banInfo.expiresAt) << " by " << banInfo.bannedBy << ".\n\nReason specified:\n" << banInfo.reason;
        disconnectClient(ss.str());
        return;
    }

    uint32_t accountNumber = msg.get<uint32_t>();
    if (!accountNumber) {
        disconnectClient("Invalid account number.");
        return;
    }

    std::string password = msg.getString();
    if (password.empty()) {
        disconnectClient("Invalid password.");
        return;
    }

    auto thisPtr = std::static_pointer_cast<ProtocolLogin>(shared_from_this());
    g_dispatcher.addTask(createTask(std::bind(&ProtocolLogin::getCharacterList, thisPtr, accountNumber, password)));
}
sorry for tag you again mate but with the latest fix u posted here i got this error when select character to log ingame
Lua:
Connection failed. (ERROR 1214)
 

Diarreamental

Well-Known Member
Joined
Jul 6, 2015
Messages
364
Reaction score
68
what u mean? @Ezzz repository doesnt have multi world system what i can compare there? :)
yours multi world editions on nostalrius code with his one.... Later make a pull request( does not matter if he accept it or not)
so everyone can see easily which files and lines has been changed.
it's pretty easy wont take you more than 5 minits
 

Alpha

Relentless
Joined
Apr 3, 2011
Messages
669
Solutions
36
Reaction score
482
Location
South Korea
sorry for tag you again mate but with the latest fix u posted here i got this error when select character to log ingame
Lua:
Connection failed. (ERROR 1214)
That most likely indicates a wrong IP/Port being sent to the client, add me on Discord (Acnologia#0001) instead and I'll take a look at it through TeamViewer instead of sending code back and forth all the time.
 
Top