1. Соблюдайте Правила форума и проявляйте уважение к другим участникам беседы.

OpenSource Waaagh!tv hostbot libiray

Тема в разделе 'Кодинг/Собственные решения', создана пользователем Kirill-782, 6 янв 2018.

  1. Kirill-782 Гуру

    Сообщения:
    109
    Спасибы:
    5
    Сборка бота GHost:
    Ghost ++17.1
    Дата начала использования бота:
    00.00.0000
    Данный код встраивает рекордер WTV в бота. Поддерживается задержка стрима.

    Для работоспособности требуется слот под фейкплеера (бот сам сделает слот за обсервера, откроет или выкинет компьютера с него)

    Есть 2 известные проблемы:
    -В прямом эфире у игроков иногда бывают на некоторых картах другие цвета.
    -Некоторые карты не поддерживают наблюдателей, даже если там не 12 слотов используется.

    Не совместим с дополнениям, которые отправляют от FakePlayer какие-либо Action пакеты (например продвинутый HCL о котором писал ранее)


    Ну что, погнали

    Качаем из комита файлы wtv.cpp и wtv.h и добавляем их в проект (приаттачил, если вруг поменяю в репозитории)

    ghost.cpp

    Добавляем к includes

    #include "wtv.h"

    В конструктор ( CGHost :: CGHost( CConfig *CFG ) )
    Добавляем
    m_WTV = NULL;

    Ищем
    Код:
        m_AdminGamePassword = CFG->GetString( "admingame_password", string( ) );
        m_AdminGameMap = CFG->GetString( "admingame_map", string( ) );
        m_LANWar3Version = CFG->GetInt( "lan_war3version", 24 );
        m_ReplayWar3Version = CFG->GetInt( "replay_war3version", 24 );
        m_ReplayBuildNumber = CFG->GetInt( "replay_buildnumber", 6059 );
    Добавляем
    Код:
        m_WTVServer = CFG->GetString( "wtv_server", "vkapps.ru" );
        m_WTVPort = CFG->GetInt( "wtv_port", 10384 );
        m_WTVLogin = CFG->GetString( "wtv_login", "testuser" );
        m_WTVPassword = CFG->GetString( "wtv_password", "testpass" );
        m_WTVActionMask = CFG->GetInt( "wtv_actionmask", 0 );
    Ищем
    SetConfigs( CFG );
    Вставляем

    Код:
        if ( ( m_WTVActionMask & 1 ) == 1 )
        {
            m_WTV = new CWTV( this, m_WTVServer, m_WTVPort, m_WTVLogin, m_WTVPassword, m_WTVActionMask );
        }
    Перед
    Код:
        // before we call select we need to determine how long to block for
        // previously we just blocked for a maximum of the passed usecBlock microseconds
        // however, in an effort to make game updates happen closer to the desired latency setting we now use a dynamic block interval
        // note: we still use the passed usecBlock as a hard maximum
    Вставляем
    Код:
        if ( m_WTV != NULL )
        {
            NumFDs += m_WTV->SetFD( &fd, &send_fd, &nfds );
        }
    После
    Код:
        // update battle.net connections
     
        for( vector<CBNET *> :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ )
        {
            if( (*i)->Update( &fd, &send_fd ) )
                BNETExit = true;
        }
    Вставляем
    Код:
        if ( m_WTV != NULL )
        {
            m_WTV->Update( &fd, &send_fd );
        }
    Ищем
    Код:
        m_SyncLimit = CFG->GetInt( "bot_synclimit", 50 );
          m_VoteKickAllowed = CFG->GetInt( "bot_votekickallowed", 1 ) == 0 ? false : true;
          m_VoteKickPercentage = CFG->GetInt( "bot_votekickpercentage", 100 );
    Вставляем
    Код:
        m_SyncLimit = CFG->GetInt( "bot_synclimit", 50 );
          m_VoteKickAllowed = CFG->GetInt( "bot_votekickallowed", 1 ) == 0 ? false : true;
          m_VoteKickPercentage = CFG->GetInt( "bot_votekickpercentage", 100 );
    В Makefile (если вдруг на линуксе надумаете бота пускать)
    В конец вставляем
    wtv.o: ghost.h util.h wtv.h socket.h map.h config.h gameprotocol.h game_base.h game.h gameplayer.h gameslot.h

    В OBJS дописываем wtv.o

    В ghost.o: добавляем wtv.h

    Дальше мне дико лень писать поэтому дам ссыль на комит (https://github.com/kirill-782/ghostwtvlib/commit/7eff783f5e809fcb2b5af9500b43835c320c3d0e)

    В конфиг вставляем
    wtv_server = vkapps.ru
    wtv_port = 10384
    wtv_actionmask = 7 (складывается из суммы 1 - включить WTV, 2 - разрешить менять команду у слота и выкидывать из него компьютера 4 - разрешить менять конфиг карты, добавляя судей и обсов)
    wtv_login = testuser
    wtv_password = testpass
    wtv_delay = 30

    Использует фейкплеера, так что нужно поменять у него название.

    На днях сделаю вайп WTV сервера и буду выдавать каждому боту логины и пароли. Так же скину ссыль на клиент WTV (хотя можно сейчас качнуть с верархива)

    Вложения:

    • wtv.zip
      Размер файла:
      5,9 КБ
      Просмотров:
      8
    Suicider, [OJIEHb] и Max5 нравится это.
  2. Max5 Старожила

    Сообщения:
    360
    Спасибы:
    66
    Сборка бота GHost:
    GhostOne 1.7.266
    Дата начала использования бота:
    14.05.2013
    Прикольно, раньше я бы сразу кинулся тестить, а сейчас думаю мои игроки не оценят, их вообще мало чем можно заинтересовать, если это не халява. Ради интереса посмотрел бы чью нибудь игру.
  3. Kirill-782 Гуру

    Сообщения:
    109
    Спасибы:
    5
    Сборка бота GHost:
    Ghost ++17.1
    Дата начала использования бота:
    00.00.0000
    Да я тоже по фану писал либу. Можно ли как нибудь бота на 16 ubuntu скомпилить с последним GCC. Какие нужны бусты? И что надо менять в коде?
  4. Kirill-782 Гуру

    Сообщения:
    109
    Спасибы:
    5
    Сборка бота GHost:
    Ghost ++17.1
    Дата начала использования бота:
    00.00.0000
    Поставить бы сервер на какую нибудь мощную машину с кучей RAM
  5. Max5 Старожила

    Сообщения:
    360
    Спасибы:
    66
    Сборка бота GHost:
    GhostOne 1.7.266
    Дата начала использования бота:
    14.05.2013
    где такую машину найти то, на мое vds 1гиг, а весит на ней дофига и больше.

    я даже не уверен что знаю что такое GCC, компилирую командой make и фиг знает что за компилятор используется. У меня ubuntu 12.04, бусты ставил из репозитория.
  6. Kirill-782 Гуру

    Сообщения:
    109
    Спасибы:
    5
    Сборка бота GHost:
    Ghost ++17.1
    Дата начала использования бота:
    00.00.0000
    16 уже не компилит
  7. Max5 Старожила

    Сообщения:
    360
    Спасибы:
    66
    Сборка бота GHost:
    GhostOne 1.7.266
    Дата начала использования бота:
    14.05.2013
    а под виндой какие бусты и компилятор юзаешь?
  8. Max5 Старожила

    Сообщения:
    360
    Спасибы:
    66
    Сборка бота GHost:
    GhostOne 1.7.266
    Дата начала использования бота:
    14.05.2013
    в общем репозиторий, на который ссылаются в первом посте удалён, но штука то прикольная, поэтому я заполню пробелы и добавлю немного от себя.
    Начнём с архива wtv.zip, там файл wtv.cpp, в нем надо найти кусок


    Код:
    BYTEARRAY CWTV :: DetalGameData ( CMap *Map, vector<CGameSlot> slots, vector<CGamePlayer *> players, unsigned char FakePlayerPid, string Name, uint32_t RandomSeed )
    {
        BYTEARRAY Data;
        unsigned char Zeros[]                = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        unsigned char PlayerJoinCounter[]    = { 2, 0, 0, 0 };
        //t_GameCreatedData
        UTIL_AppendByteArray( Data, Map->GetMapPath( ) );
        UTIL_AppendByteArray( Data, Map->GetMapSize( ) );
        UTIL_AppendByteArray( Data, Map->GetMapInfo( ) );
        UTIL_AppendByteArray( Data, (uint32_t) 1, false );
        UTIL_AppendByteArray( Data, Map->GetMapCRC( ) );
        UTIL_AppendByteArray( Data, (uint32_t) 1, false ); // Unknown 1
        UTIL_AppendByteArray( Data, (uint32_t) 1, false ); // Unknown 2
        UTIL_AppendByteArray( Data, RandomSeed, false );
        Data.push_back( Map->GetMapLayoutStyle( ) );
        Data.push_back( Map->GetMapNumPlayers( ) );
        //UNUSED
        Data.push_back( 2 );
        Data.push_back( 0 );                                                   
        UTIL_AppendByteArray( Data, (uint16_t)6112, false );                               
        UTIL_AppendByteArray( Data, Zeros, 12 );               
        //
        [B]Data.push_back( (unsigned char)slots.size( ) );[/B]
    
    где
    Код:
    Data.push_back( (unsigned char)slots.size( ) );
    заменить на
    Код:
    Data.push_back( (unsigned char)12);
    иначе это не будет работать на картах, где меньше 12 слотов.

    Ещё момент, у каждой карты определённое количество слотов, это количество можно попытаться переопределить в конфиге, но это ничего не даст, вернее это сломает вам игру, но фейк просто необходим т.к. стрим ведётся от его лица. Выходит если все слоты заняты игроками, а слотов меньше 12 и очень хочется добавить ещё один для фейка, бросьте эту затею, не работает.

    И теперь недостающие части.
    В ghost.cpp
    после
    Код:
    m_WTVActionMask = CFG->GetInt( "wtv_actionmask", 0 );
    ещё добавляем
    Код:
    m_WTVDelay = CFG->GetInt( "wtv_delay", 0 );
    Это тот параметр отвечает за время(в секундах) на которое стрим будет отставать от реального времени, нужен, видимо, чтобы зрители не могли влиять на игру, подсказывая одним действиях других.

    В ghost.h, допустим перед struct GProxyReconnector
    добавить
    Код:
    class CWTV;
    после
    Код:
    CTCPServer *m_ReconnectSocket;
    вставить
    Код:
    CWTV *m_WTV;
    после
    Код:
    vector<GProxyReconnector *> m_PendingReconnects;
    вставляем
    Код:
        string m_WTVServer;                        // config value
        uint16_t m_WTVPort;                        // config value
        string m_WTVLogin;                        // config value
        string m_WTVPassword;                    // config value
        uint32_t m_WTVDelay;                    // config value
        uint32_t m_WTVActionMask;                // config value

    Куда-нибудь(к примеру, перед public: ) в game_base.h добавить
    Код:
    CWTVGame *m_WTVGame;
    uint32_t m_WTVGameDelay;
    в том же файле перед
    Код:
    class CBaseGame
    {
    добавить
    Код:
    class CWTVGame;
    В game_base.cpp добавить рядом с другими include
    Код:
    #include "wtv.h"
    далее в
    Код:
    CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, string nGameName, string nOwnerName, string nCreatorName, string nCreatorServer )
    {
    добавить
    Код:
    m_WTVGame = NULL;
    m_WTVGameDelay = m_GHost->m_WTVDelay;
    после
    Код:
    CBaseGame :: ~CBaseGame( )
    {
    вставить
    Код:
    if( m_GHost->m_WTV )
    {
    m_GHost->m_WTV->PastePackage( m_WTVGame, m_Protocol->SEND_W3GS_PLAYERLEAVE_OTHERS( m_FakePlayerPID, PLAYERLEAVE_GPROXY ), 5000 );
    m_GHost->m_WTV->GameEnd( m_WTVGame );
    }
    где то в условии
    Код:
    if( m_LoadInGame && GetTime( ) - m_LastLagScreenResetTime >= 30 )
    есть
    Код:
    if( m_Replay )
                    {
                        if( UsingGProxy )
                        {
                            for( unsigned char i = 0; i < m_GProxyEmptyActions; i++ )
                                m_Replay->AddTimeSlot( 0, queue<CIncomingAction *>( ) );
                        }
     
                        m_Replay->AddTimeSlot( 0, queue<CIncomingAction *>( ) );
                    }
    перед ним добавить
    Код:
        if( m_GHost->m_WTV )
                    {
                        if( UsingGProxy )
                        {
                            for( unsigned char i = 0; i < m_GProxyEmptyActions; i++ )
                                m_GHost->m_WTV->PastePackage( m_WTVGame, m_Protocol->SEND_W3GS_INCOMING_ACTION( queue<CIncomingAction *>( ), 0 ) );
                        }
     
                        m_GHost->m_WTV->PastePackage( m_WTVGame, m_Protocol->SEND_W3GS_INCOMING_ACTION( queue<CIncomingAction *>( ), 0 ) );
                    }
    после
    Код:
    SendAll( m_Protocol->SEND_W3GS_START_LAG( m_Players ) );
    добавить
    Код:
    if( m_GHost->m_WTV )
    m_GHost->m_WTV->GameStartLagging( m_WTVGame );
    после
    Код:
        for( vector<CGamePlayer *> :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ )
                {
                    if( (*i)->GetLagging( ) )
                        Lagging = true;
                }
     
                m_Lagging = Lagging;
    добавить
    Код:
    if( m_GHost->m_WTV && !m_Lagging )
    m_GHost->m_WTV->GameStopLagging( m_WTVGame );
    в методы
    Код:
    void CBaseGame :: Send( BYTEARRAY PIDs, BYTEARRAY data )
    {
    и
    Код:
    void CBaseGame :: SendAll( BYTEARRAY data )
    добавить
    Код:
    if( m_GHost->m_WTV && m_GameLoaded )
            m_GHost->m_WTV->PastePackage( m_WTVGame, data );
    после
    Код:
    for( vector<CGamePlayer *> :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ )
            {
                if( (*i)->GetFinishedLoading( ) )
                {
                    if( !player->GetFinishedLoading( ) )
                        Send( *i, m_Protocol->SEND_W3GS_STOP_LAG( player ) );
     
                    Send( *i, m_Protocol->SEND_W3GS_PLAYERLEAVE_OTHERS( player->GetPID( ), player->GetLeftCode( ) ) );
                }
                else
                    (*i)->AddLoadInGameData( m_Protocol->SEND_W3GS_PLAYERLEAVE_OTHERS( player->GetPID( ), player->GetLeftCode( ) ) );
            }
    добавить
    Код:
    if( m_GHost->m_WTV )
    {
    m_GHost->m_WTV->PastePackage( m_WTVGame, m_Protocol->SEND_W3GS_PLAYERLEAVE_OTHERS( player->GetPID( ), player->GetLeftCode( ) ) );
    }
    после
    Код:
    void CBaseGame :: EventGameStarted( )
    {
        CONSOLE_Print( "[GAME: " + m_GameName + "] started loading with " + UTIL_ToString( GetNumHumanPlayers( ) ) + " players" );
    
    добавить
    Код:
    DeleteVirtualHost( );
     
        unsigned int ObserverSID = 255;
     
        if( m_GHost->m_WTV && !m_SaveGame )
        {
            DeleteFakePlayer( );
            // found observer slot for fakeplayer.
            CloseAllSlots( );
     
            // attempt find observer slot
            for( unsigned int i = 0; i < m_Slots.size( ); i++ )
            {
                if( m_Slots[i].GetTeam( ) == 12 && m_Slots[i].GetSlotStatus( ) == SLOTSTATUS_CLOSED )
                {
                    ObserverSID = i;
                    break;
                }
            }
     
            if( ( m_GHost->m_WTVActionMask & 2 ) == 2 )
            {
     
                // attempt find any slot, and set slot in observer team
                if( ObserverSID == 255 )
                {
                    for( unsigned int i = 0; i < m_Slots.size( ); i++ )
                    {
                        if( m_Slots[i].GetSlotStatus( ) == SLOTSTATUS_CLOSED )
                        {
                            m_Slots[i].SetTeam( 12 );
                            ObserverSID = i;
                            break;
                        }
                    }
                }
                if( ObserverSID == 255 )
                {
                    for( unsigned int i = 0; i < m_Slots.size( ); i++ )
                    {
                        if( m_Slots[i].GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && m_Slots[i].GetComputer( ) == 1 )
                        {
                            m_Slots[i].SetTeam( 12 );
                            CloseSlot( i, true );
                            ObserverSID = i;
                            break;
                        }
                    }
                }
            }
        }
    что то я не уверен, что именно тут нужен DeleteVirtualHost( ); т.к. по коду он идёт ниже. Можно убрать его чуть ниже или не вставлять из этого куска, вроде не должен не на что влиять и я хз почему он у меня именно тут.

    Далее после
    Код:
    if( m_SlotInfoChanged )
    SendAllSlotInfo( );
    добавить
    Код:
        if( ObserverSID != 255 )
        {
            OpenSlot( ObserverSID, true );
            CreateFakePlayer( );
            m_WTVGame = m_GHost->m_WTV->CreateGame( m_WTVGameDelay, m_Map, m_Slots, m_Players, m_FakePlayerPID, m_VirtualHostName, m_RandomSeed, m_GameName );
        }
    перед
    Код:
        CGamePlayer *Shortest = NULL;
        CGamePlayer *Longest = NULL;
    Код:
    if( m_GHost->m_WTV )
    m_GHost->m_WTV->GameStart( m_WTVGame );
    В game.cpp, куда хотите можно добавить команду для управления задержкой стрима
    Код:
    if( Command == "delay" && !m_GameLoading && !m_GameLoaded && !m_SaveGame )
                {
                 
                    if( Payload.empty( ) )
                        SendAllChat( "Current Waaagh!TV delay: " + UTIL_ToString( m_WTVGameDelay ) );
                    else
                    {
     
                        uint32_t Delay;
                        stringstream SS;
                        SS << Payload;
                        SS >> Delay;
     
                        if( SS.fail( ) )
                            CONSOLE_Print( "[GAME: " + m_GameName + "] bad input #1 to delay command" );
                        else
                        {
                            m_WTVGameDelay = Delay;
                        }
                    }
                }

    Вроде ничего не забыл, как минимум, самое важное написал.
  9. Max5 Старожила

    Сообщения:
    360
    Спасибы:
    66
    Сборка бота GHost:
    GhostOne 1.7.266
    Дата начала использования бота:
    14.05.2013
    Клиент Waaagh гуглится легко, нет смысла выкладывать, а сервер лежит тут https://github.com/Volcore/waaaghtv, но требуются некоторые изменения, которые , опять же, уважаемый Kirill-782 уже внёс https://github.com/kirill-782/waaaghtv достаточно скачать, по инструкции собрать и запустить.

    Отмечу что карты нынче стали сложными и к каждой нужен свой подход, где то фейка можно посадить на свободный слот, где то только на слот компьютера, а иногда необходим мап хак, чтобы открыть всю карту и в полной мере наблюдать стрим.