• 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!

Compiling C++ doubt (1.3)

sasuke.maria

New Member
Joined
Nov 19, 2016
Messages
17
Reaction score
0
Hihi!
I come here for ask something, if you can help me with this, please post.

Well look the img:
N2wYSgS.png


I tryng put this "viewers" below but no sucesso ;s
someone can help-me with this?

code of this part:
Code:
void ProtocolLogin::getCastingStreamsList(const std::string& password, uint16_t version)
{
    //dispatcher thread
    auto output = OutputMessagePool::getOutputMessage();
    addWorldInfo(output, "", password, version, true);

    const auto& casts = ProtocolGame::getLiveCasts();
    output->addByte(casts.size());
    std::ostringstream entry;
    for (const auto& cast : casts) {
        output->addByte(0);
        entry << cast.first->getName() << " [" << cast.second->getSpectatorCount() << " viewers]";
        output->addString(entry.str());
        entry.str(std::string());
    }
    output->addByte(0);
    output->addByte(g_config.getBoolean(ConfigManager::FREE_PREMIUM));
    output->add<uint32_t>(g_config.getBoolean(ConfigManager::FREE_PREMIUM) ? 0 : (time(nullptr)));

    send(std::move(output));

    disconnect();
}
 
Without knowing exactly what ProtocolGame::getLiveCasts() return, it will be impossible to figgure out what's wrong here.

But don't forget to change your protocolgame.cpp or whereever the spectator would connect to.

Code:
std::string characterName = msg.getString();
size_t pos = characterName.find('[');
characterName = characterName.substr(0, pos - 1);
 
Without knowing exactly what ProtocolGame::getLiveCasts() return, it will be impossible to figgure out what's wrong here.

But don't forget to change your protocolgame.cpp or whereever the spectator would connect to.

Code:
std::string characterName = msg.getString();
size_t pos = characterName.find('[');
characterName = characterName.substr(0, pos - 1);


Sorry, i think spectator connect here:
Code:
/**
* The Forgotten Server - a free and open-source MMORPG server emulator
 * Copyright (C) 2016  Mark Samman <[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 "protocolgame.h"
#include "protocolspectator.h"

#include "outputmessage.h"
#include "ctype.h"
#include "tile.h"
#include "player.h"
#include "chat.h"

#include "configmanager.h"

#include "game.h"

#include "connection.h"
#include "scheduler.h"
#include "ban.h"

extern Game g_game;
extern ConfigManager g_config;
extern Chat* g_chat;

ProtocolSpectator::ProtocolSpectator(Connection_ptr connection) :
    ProtocolGameBase(connection),
    client(nullptr)
{

}

void ProtocolSpectator::disconnectSpectator(const std::string& message) const
{
    auto output = OutputMessagePool::getOutputMessage();
    output->addByte(0x14);
    output->addString(message);
    send(std::move(output));
    disconnect();
}

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

    operatingSystem = (OperatingSystem_t)msg.get<uint16_t>();
    version = msg.get<uint16_t>();

    msg.skipBytes(7); // U32 clientVersion, U8 clientType

    if (!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 (operatingSystem >= CLIENTOS_OTCLIENT_LINUX) {
        NetworkMessage opcodeMessage;
        opcodeMessage.addByte(0x32);
        opcodeMessage.addByte(0x00);
        opcodeMessage.add<uint16_t>(0x00);
        writeToOutputBuffer(opcodeMessage);
    }

    msg.skipBytes(1); // gamemaster flag
    std::string password = msg.getString();
    std::string characterName = msg.getString();

    uint32_t timeStamp = msg.get<uint32_t>();
    uint8_t randNumber = msg.getByte();
    if (challengeTimestamp != timeStamp || challengeRandom != randNumber) {
        disconnect();
        return;
    }

    if (version < g_config.getNumber(ConfigManager::VERSION_MIN) || version > g_config.getNumber(ConfigManager::VERSION_MAX)) {
        disconnectSpectator(g_config.getString(ConfigManager::VERSION_STR));
        return;
    }

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

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

    BanInfo banInfo;
    if (IOBan::isIpBanned(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;
        disconnectSpectator(ss.str());
        return;
    }
    password.erase(password.begin()); //Erase whitespace from the front of the password string
    std::size_t pos = characterName.find("[");
    if (pos != std::string::npos) {
        pos -= 1;
    }
    g_dispatcher.addTask(createTask(std::bind(&ProtocolSpectator::login, std::static_pointer_cast<ProtocolSpectator>(shared_from_this()), characterName.substr(0, pos), password)));
}

void ProtocolSpectator::sendEmptyTileOnPlayerPos(const Tile* tile, const Position& playerPos)
{
    NetworkMessage msg;

    msg.addByte(0x69);
    msg.addPosition(playerPos);

    msg.add<uint16_t>(0x00);
    msg.addItem(tile->getGround());

    msg.addByte(0x00);
    msg.addByte(0xFF);
    writeToOutputBuffer(msg);
}

void ProtocolSpectator::addDummyCreature(NetworkMessage& msg, const uint32_t& creatureID, const Position& playerPos)
{
    // add dummy creature
    CreatureType_t creatureType = CREATURETYPE_NPC;
    if (creatureID <= 0x10000000) {
        creatureType = CREATURETYPE_PLAYER;
    } else if (creatureID <= 0x40000000) {
        creatureType = CREATURETYPE_MONSTER;
    }
    msg.addByte(0x6A);
    msg.addPosition(playerPos);
    msg.addByte(1); //stackpos
    msg.add<uint16_t>(0x61); // is not known
    msg.add<uint32_t>(0); // remove no creature
    msg.add<uint32_t>(creatureID); // creature id
    msg.addByte(creatureType); // creature type
    msg.addString("Dummy");
    msg.addByte(0x00); // health percent
    msg.addByte(DIRECTION_NORTH); // direction
    AddOutfit(msg, player->getCurrentOutfit()); // outfit
    msg.addByte(0); // light level
    msg.addByte(0); // light color
    msg.add<uint16_t>(200); // speed
    msg.addByte(SKULL_NONE); // skull type
    msg.addByte(SHIELD_NONE); // party shield
    msg.addByte(GUILDEMBLEM_NONE); // guild emblem
    msg.addByte(creatureType); // creature type
    msg.addByte(SPEECHBUBBLE_NONE); // speechbubble
    msg.addByte(0xFF); // MARK_UNMARKED
    msg.add<uint16_t>(0x00); // helpers
    msg.addByte(0); // walkThrough
}

void ProtocolSpectator::syncKnownCreatureSets()
{
    const auto& casterKnownCreatures = client->getKnownCreatures();
    const auto playerPos = player->getPosition();
    const auto tile = player->getTile();

    if (!tile || !tile->getGround()) {
        disconnectSpectator("A sync error has occured.");
        return;
    }
    sendEmptyTileOnPlayerPos(tile, playerPos);

    bool known;
    uint32_t removedKnown;
    for (const auto creatureID : casterKnownCreatures) {
        if (knownCreatureSet.find(creatureID) != knownCreatureSet.end()) {
            continue;
        }

        NetworkMessage msg;
        const auto creature = g_game.getCreatureByID(creatureID);
        if (creature && !creature->isRemoved()) {
            msg.addByte(0x6A);
            msg.addPosition(playerPos);
            msg.addByte(1); //stackpos
            checkCreatureAsKnown(creature->getID(), known, removedKnown);
            AddCreature(msg, creature, known, removedKnown);
            RemoveTileThing(msg, playerPos, 1);
        } else if (operatingSystem <= CLIENTOS_FLASH) { // otclient freeze with huge amount of creature add, but do not debug if there are unknown creatures, best solution for now :(
            addDummyCreature(msg, creatureID, playerPos);
            RemoveTileThing(msg, playerPos, 1);
        }
        writeToOutputBuffer(msg);
    }

    sendUpdateTile(tile, playerPos);
}

void ProtocolSpectator::syncChatChannels()
{
    sendChannel(CHANNEL_CAST, LIVE_CAST_CHAT_NAME, nullptr, nullptr);
}

void ProtocolSpectator::syncOpenContainers()
{
    const auto& openContainers = player->getOpenContainers();
    for (const auto& it : openContainers) {
        auto openContainer = it.second;
        auto container = openContainer.container;
        sendContainer(it.first, container, container->hasParent(), openContainer.index);
    }
}

void ProtocolSpectator::login(const std::string& liveCastName, const std::string& password)
{
    //dispatcher thread
    auto foundPlayer = g_game.getPlayerByName(liveCastName);
    if (!foundPlayer || foundPlayer->isRemoved()) {
        disconnectSpectator("This cast no longer exists. Please relogin to refresh the list.");
        return;
    }

    const auto liveCasterProtocol = ProtocolGame::getLiveCast(foundPlayer);
    if (!liveCasterProtocol) {
        disconnectSpectator("This cast no longer exists. Please relogin to refresh the list.");
        return;
    }

    const auto& liveCastPassword = liveCasterProtocol->getLiveCastPassword();
    if (liveCasterProtocol->isLiveCaster()) {
        if (!liveCastPassword.empty() && password != liveCastPassword) {
            disconnectSpectator("This cast is protected and you are setting the wrong password.");
            return;
        }

        player = foundPlayer;
        player->incrementReferenceCounter();
        eventConnect = 0;
        client = liveCasterProtocol;
        acceptPackets = true;
        OutputMessagePool::getInstance().addProtocolToAutosend(shared_from_this());
        sendAddCreature(player, player->getPosition(), 0, false);
        syncKnownCreatureSets();
        syncChatChannels();
        syncOpenContainers();

        liveCasterProtocol->addSpectator(std::static_pointer_cast<ProtocolSpectator>(shared_from_this()));
    } else {
        disconnectSpectator("This cast no longer exists. Please relogin to refresh the list.");
    }
}

void ProtocolSpectator::logout()
{
    acceptPackets = false;
    if (client && player) {
        client->removeSpectator(std::static_pointer_cast<ProtocolSpectator>(shared_from_this()));
        player->sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "One viewer has been left from your cast.");
        player->decrementReferenceCounter();
        player = nullptr;
    }
    disconnect();
}

void ProtocolSpectator::parsePacket(NetworkMessage& msg)
{
    if (!acceptPackets || g_game.getGameState() == GAME_STATE_SHUTDOWN || msg.getLength() <= 0) {
        return;
    }

    uint8_t recvbyte = msg.getByte();

    if (!player) {
        if (recvbyte == 0x0F) {
            disconnect();
        }

        return;
    }

    //a dead player can not perform actions
    if (player->isRemoved() || player->getHealth() <= 0) {
        disconnect();
        return;
    }

    switch (recvbyte) {
    case 0x14: g_dispatcher.addTask(createTask(std::bind(&ProtocolSpectator::logout, getThis()))); break;
    case 0x1D: g_dispatcher.addTask(createTask(std::bind(&ProtocolSpectator::sendPingBack, getThis()))); break;
    case 0x1E: g_dispatcher.addTask(createTask(std::bind(&ProtocolSpectator::sendPing, getThis()))); break;
        //Reset viewed position/direction if the spectator tries to move in any way
    case 0x64: case 0x65: case 0x66: case 0x67: case 0x68: case 0x6A: case 0x6B: case 0x6C: case 0x6D: case 0x6F: case 0x70: case 0x71:
    case 0x72: g_dispatcher.addTask(createTask(std::bind(&ProtocolSpectator::sendCancelWalk, getThis()))); break;
    case 0x96: parseSpectatorSay(msg); break;
    default:
        break;
    }

    if (msg.isOverrun()) {
        disconnect();
    }
}

void ProtocolSpectator::parseSpectatorSay(NetworkMessage& msg)
{
    SpeakClasses type = (SpeakClasses)msg.getByte();
    uint16_t channelId = 0;

    if (type == TALKTYPE_CHANNEL_Y) {
        channelId = msg.get<uint16_t>();
    } else {
        return;
    }

    const std::string text = msg.getString();

    if (text.length() > 255 || channelId != CHANNEL_CAST || !client) {
        return;
    }

    if (text.substr(0, 5) == "/nick" && text.length() > 6) {
        std::string newName = text.substr(6);
        toupper(newName);
        if (newName == "god"){
            sendChannelMessage("", "You can't choose this name. It is inappropriate and only true administrators can use them.", TALKTYPE_CHANNEL_Y, CHANNEL_CAST);
            return;
        }
        if (client) {
            g_dispatcher.addTask(createTask(std::bind(&ProtocolGame::broadcastSpectatorMessage, client, "", (name.empty() ? "spectator" : name) + " changed nick to " + newName)));
            player->sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "The viewer " + newName + " has entered on your cast channel.");
        }
        name = newName;
        return;
    }

    if (name.empty()) {
        sendChannelMessage("", "You can not talk before choosing a nick with the /nick YOURNAME.", TALKTYPE_CHANNEL_O, CHANNEL_CAST);
        return;
    }

    if (client) {
        g_dispatcher.addTask(createTask(std::bind(&ProtocolGame::broadcastSpectatorMessage, client, name, text)));
    }
}

void ProtocolSpectator::release()
{
    //dispatcher
    if (client && player) {
        player->sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "One viewer has been left from your cast.");
        client->removeSpectator(std::static_pointer_cast<ProtocolSpectator>(shared_from_this()));
        player->decrementReferenceCounter();
        player = nullptr;
    }
    Protocol::release();
    OutputMessagePool::getInstance().removeProtocolFromAutosend(shared_from_this());
}

void ProtocolSpectator::writeToOutputBuffer(const NetworkMessage& msg, bool broadcast)
{
    OutputMessage_ptr out = getOutputBuffer(msg.getLength());
    out->append(msg);
}

void ProtocolSpectator::onLiveCastStop()
{
    //dispatcher
    if (player) {
        player->decrementReferenceCounter();
        player = nullptr;
    }
    disconnect();
}

And about getliveCasts i found just it on cpps..

const auto& casts = ProtocolGame::getLiveCasts();
 
Back
Top