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

BIT_hack

Знающий
Участник
Сообщения
170
Розыгрыши
0
Решения
2
Репутация
59
Реакции
118
Баллы
455
Я пытался понять, как взаимодействуют DLL и интерфейс. Для этого я создал интернет-радио, которое, как я считаю, никому не нужно. Однако я решил сохранить его на память. Возможно, кто-то захочет его использовать.

Исходный код для интерлюдия, который вы можете адаптировать для любой хроники выше HF. Для этого вам потребуется подключить файл interface.dll к l2.exe с помощью CFF_Explorer.

Если у вас Interlude или HF, просто переместите все файлы из архива, которые находятся в папке system, в свою системную папку игры с заменой.



Этот скрипт поможет вам разобраться в основах работы с интернет-радио. Вы можете адаптировать его под свой стиль и проект!
C++:
/******************************************
 Дата 25.10.2024 23:18

 Разработчик: BITHACK

 Copyright (c) Ваша компания

Описание скрипта:
 Интерфейс интернет-радиоплеера с базовыми
 функциями управления воспроизведением из DLL.
*******************************************/
class aaIT_RadioDLL extends UICommonAPI;

 var int count; // Переменная для хранения индекса текущей станции

// Нативные функции, реализованные в Interface.dll
native(1246) final function bool PlayStop(); // Останавливает или запускает воспроизведение
native(1249) final function string GetStreamURL(); // воспроизведение URL

// Импортируем текстуры для кнопок из папки interface/RadioIMG
    #exec Texture Import File=RadioIMG/Back.tga Name=Back Mips=Off MASKED=1
    #exec Texture Import File=RadioIMG/Next.tga Name=Next Mips=Off MASKED=1
    #exec Texture Import File=RadioIMG/Stop.tga Name=Stop Mips=Off MASKED=1
    #exec Texture Import File=RadioIMG/Play.tga Name=Play Mips=Off MASKED=1

// Импортируем текстуры для кнопок в нажатом состоянии из папки interface/RadioIMG
    #exec Texture Import File=RadioIMG/Back_down.tga Name=Back_down Mips=Off MASKED=1
    #exec Texture Import File=RadioIMG/Next_down.tga Name=Next_down Mips=Off MASKED=1
    #exec Texture Import File=RadioIMG/Stop_down.tga Name=Stop_down Mips=Off MASKED=1
    #exec Texture Import File=RadioIMG/Play_down.tga Name=Play_down Mips=Off MASKED=1

// Функция обработки нажатия на кнопку
function OnClickButton( String strID ) {

 switch( strID ){
    case "PlayStop":
  // Проверяем, запущено ли воспроизведение
 if ( PlayStop() ){
    ButtonHandle(GetHandle("aaIT_RadioDLL.PlayStop")).SetTexture( "interface.Stop", "interface.Stop_down", "Interface.Stop_down"); // Меняем текстуру кнопки на "Stop"
    }else{
    ButtonHandle(GetHandle("aaIT_RadioDLL.PlayStop")).SetTexture( "interface.Play", "interface.Play_down", "Interface.Play_down"); // Меняем текстуру кнопки на "Play"
    }
 break;
    case "PlayBack": //Назад
    count--; // Уменьшаем индекс текущей станции
 if (count == -1) {
    count = 5; // Если индекс выходит за пределы массива, устанавливаем его в 5
    }
    SteamPlay(count); // Переключаемся на предыдущую станцию
 break;
    case "PlayNext"://Вперед
    count++; // Увеличиваем индекс текущей станции
 if (count == 6) {
    count = 0; // Если индекс выходит за пределы массива, устанавливаем его в 0
    }
    SteamPlay(count); // Переключаемся на следующую станцию
 break;
    }
    }

function SteamPlay(int PlayCount){ // Функция для переключения станции
 local array<String> UrlName; //Массив с ID разрешенных банок

    Split(RadioName(PlayCount), "," ,UrlName); // Разделяем строку с адресом и названием на две части
    PlayStreamURL(UrlName[0]); // Запускаем воспроизведение по полученному адресу
    TextBoxHandle(GetHandle("aaIT_RadioDLL.RadioNameTxt")).SetText(UrlName[1]); // Устанавливаем название станции в текстовое поле
    ButtonHandle(GetHandle("aaIT_RadioDLL.PlayStop")).SetTexture( "interface.Stop", "interface.Stop_down", "");

    }

function PlayStreamURL(string URL){ // Функция для запуска воспроизведения по адресу DLL
    URL = GetStreamURL(); // Получаем адрес станции из DLL
    }

function string RadioName(int Radio){ // Функция для получения адреса и названия станции по индексу
 switch( Radio ){
    case 0:
    return "https://hfm.amgradio.ru/HypeFM , Хайп ФМ" ;
 break;
    case 1:
    return "http://paris.discovertrance.com:8006/;stream.nsv , Discover Trance" ;
 break;
    case 2:
    return "http://listen1.myradio24.com:9000/5967 , 90's Eurodance" ;
 break;
    case 3:
    return "https://radiorecord.hostingradio.ru/rr_main96.aacp , Radio Record «Record»" ;
 break;
    case 4:
    return "https://radiorecord.hostingradio.ru/rus96.aacp , Radio Record «Russian Mix»" ;
 break;
    case 5:
    return "https://radiorecord.hostingradio.ru/hype96.aacp, Radio Record «На Хайпе»" ;
 break;

    }
    }

    defaultproperties{}
 

Вложения

  • L2InterfaceRadio.zip
    697,5 КБ · Просмотры: 26
Было бы интересно посмотреть что под interface.dll, это результаты тех долгих разборов с внешней dll.
 
А вот что мы обсуждали в этой теме. Where im failing on native dll?

Только вместо этого:
C++:
// Функция, которая будет вызываться вместо оригинальной функции с номером 1247
void __stdcall functionUC(struct FFrame& Stack , void* Result)
{

// Извлечение результата
int result = *(int*)Result;

}

вот это:
C++:
// Извлечение результата
TCHAR* str = *(TCHAR**)Result;  // Получаем URL из UnrealScript
 
Небольшой обзор радио, баловался в видеоредактор)
 
Sup, i already tried use TCHAR but i was getting some Critical Errors, i was trying just to send a message to UC, have u already tried it?

here is the code but 0 idea why im having Critical Error:

C++:
void __stdcall functionUC(struct FFrame& Stack, RESULT_DECL)
{
    Stack.Code++;
    
    *(TCHAR**)Result = TEXT("Message From DLL");

    MessageBox(nullptr, L"Load functionUC ", L"hook", MB_OK);
}

Код:
native(1247) static final function string ItemExSort();

function OnClickButton(string strID)
{
    switch(strID)
    {
    case "btnNewAccount" :
        MessageBox("DLL MESSAGE = " $ ItemExSort());
        ShowMessageInLogin(GetSystemMessage(1186));
        break;
    }
}
 
Sup, i already tried use TCHAR but i was getting some Critical Errors, i was trying just to send a message to UC, have u already tried it?

here is the code but 0 idea why im having Critical Error:

Пока мне не удалось вернуть текст в скрипт., мне удалось только получить его в DLL, непонятным для мне способом, что я писал в предыдущей теме.

C++:
// Нативная функция
void __stdcall functionUC(struct FFrame& Stack, RESULT_DECL)
    Stack.Code++;

    TCHAR* str = *(TCHAR**)Result;  // Получаем из UnrealScript
    MessageBox(nullptr, str, L"hook", MB_OK)
}
C-подобный:
native(1247) static final function string functionUC();;


function OnClickButton(string strID)
{
    switch(strID)
    {
    case "btnNewAccount" :

TestStringDll("Hello world");

        break;
    }
}

function TestStringDll(string URL){ // Прокладка
    URL = functionUC(); // Отправляем текст в dll (не спрашивайте как это работает я сам не знаю)
    }
 
Кстати можно сделать под windows и linux.
Заменить bass.dll на такое:
Код:
#include <iostream>
#include <curl/curl.h>
#include <portaudio.h>

static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) {
    std::vector<char>* buffer = (std::vector<char>*)userp;
    size_t totalSize = size * nmemb;
    buffer->insert(buffer->end(), (char*)contents, (char*)contents + totalSize);
    return totalSize;
}

int main() {
    const char* url = "http://your-radio-stream-url.m3u";
    CURL* curl;
    CURLcode res;
    std::vector<char> buffer;

    curl_global_init(CURL_GLOBAL_ALL);
    curl = curl_easy_init();
    if(curl) {
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
        res = curl_easy_perform(curl);
        curl_easy_cleanup(curl);

        if(res != CURLE_OK) {
            std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
            return 1;
        }
    }
    curl_global_cleanup();

    Pa_Initialize();
    PaStream* stream;
    Pa_OpenDefaultStream(&stream, 0, 2, paFloat32, 44100, paFramesPerBufferUnspecified, nullptr, nullptr);
    Pa_StartStream(stream);

    // Простой способ воспроизвести загруженные данные
    float* audioBuffer = reinterpret_cast<float*>(buffer.data());
    Pa_WriteStream(stream, audioBuffer, buffer.size() / sizeof(float));

    Pa_StopStream(stream);
    Pa_CloseStream(stream);
    Pa_Terminate();

    return 0;
}
 
Добавил регулировку громкости звука


C-подобный:
/******************************************
 Дата 25.10.2024 23:18

 Разработчик: BITHACK

 Copyright (c) Ваша компания

Описание скрипта:
 Интерфейс интернет-радиоплеера с базовыми
 функциями управления воспроизведением из DLL.
*******************************************/
class aaIT_RadioDLL extends UICommonAPI;

 var int count; // Переменная для хранения индекса текущей станции

// Нативные функции, реализованные в Interface.dll
native(1246) final function bool PlayStop(); // Останавливает или запускает воспроизведение
native(1249) final function string GetStreamURL(); // воспроизведение URL
native(1250) final function VolumeR(float ValTick); // воспроизведение URL

// Импортируем текстуры для кнопок из папки interface/RadioIMG
    #exec Texture Import File=RadioIMG/Back.tga Name=Back Mips=Off MASKED=1
    #exec Texture Import File=RadioIMG/Next.tga Name=Next Mips=Off MASKED=1
    #exec Texture Import File=RadioIMG/Stop.tga Name=Stop Mips=Off MASKED=1
    #exec Texture Import File=RadioIMG/Play.tga Name=Play Mips=Off MASKED=1

// Импортируем текстуры для кнопок в нажатом состоянии из папки interface/RadioIMG
    #exec Texture Import File=RadioIMG/Back_down.tga Name=Back_down Mips=Off MASKED=1
    #exec Texture Import File=RadioIMG/Next_down.tga Name=Next_down Mips=Off MASKED=1
    #exec Texture Import File=RadioIMG/Stop_down.tga Name=Stop_down Mips=Off MASKED=1
    #exec Texture Import File=RadioIMG/Play_down.tga Name=Play_down Mips=Off MASKED=1

function OnLoad() { /* Выполняется при старте игры */
    TextBoxHandle(GetHandle("aaIT_RadioDLL.ValueTxt")).SetText("Volume:"); // Устанавливаем название текста Volume
    }

// Функция обработки нажатия на кнопку
function OnClickButton( String strID ) {

 switch( strID ){
    case "PlayStop":
  // Проверяем, запущено ли воспроизведение
 if ( PlayStop() ){
    ButtonHandle(GetHandle("aaIT_RadioDLL.PlayStop")).SetTexture( "interface.Stop", "interface.Stop_down", "Interface.Stop_down"); // Меняем текстуру кнопки на "Stop"
    }else{
    ButtonHandle(GetHandle("aaIT_RadioDLL.PlayStop")).SetTexture( "interface.Play", "interface.Play_down", "Interface.Play_down"); // Меняем текстуру кнопки на "Play"
    }

 break;
    case "PlayBack": //Назад
    count--; // Уменьшаем индекс текущей станции
 if (count == -1) {
    count = 5; // Если индекс выходит за пределы массива, устанавливаем его в 5
    }
    SteamPlay(count); // Переключаемся на предыдущую станцию
 break;
    case "PlayNext"://Вперед
    count++; // Увеличиваем индекс текущей станции
 if (count == 6) {
    count = 0; // Если индекс выходит за пределы массива, устанавливаем его в 0
    }

    SteamPlay(count); // Переключаемся на следующую станцию
 break;
    }
    }

function SteamPlay(int PlayCount){ // Функция для переключения станции
 local array<String> UrlName; //Массив с ID разрешенных банок

    Split(RadioName(PlayCount), "," ,UrlName); // Разделяем строку с адресом и названием на две части
    PlayStreamURL(UrlName[0]); // Запускаем воспроизведение по полученному адресу
    TextBoxHandle(GetHandle("aaIT_RadioDLL.RadioNameTxt")).SetText(UrlName[1]); // Устанавливаем название станции в текстовое поле
    ButtonHandle(GetHandle("aaIT_RadioDLL.PlayStop")).SetTexture( "interface.Stop", "interface.Stop_down", "");

    }

function PlayStreamURL(string URL){ // Функция для запуска воспроизведения по адресу DLL
    URL = GetStreamURL(); // Получаем адрес станции из DLL
    }

function string RadioName(int Radio){ // Функция для получения адреса и названия станции по индексу
 switch( Radio ){
    case 0:
    return "https://hfm.amgradio.ru/HypeFM , Хайп ФМ" ;
 break;
    case 1:
    return "http://paris.discovertrance.com:8006/;stream.nsv , Discover Trance" ;
 break;
    case 2:
    return "http://listen1.myradio24.com:9000/5967 , 90's Eurodance" ;
 break;
    case 3:
    return "https://radiorecord.hostingradio.ru/rr_main96.aacp , Radio Record «Record»" ;
 break;
    case 4:
    return "https://radiorecord.hostingradio.ru/rus96.aacp , Radio Record «Russian Mix»" ;
 break;
    case 5:
    return "https://radiorecord.hostingradio.ru/hype96.aacp, Radio Record «На Хайпе»" ;
 break;

    }
    }

function OnModifyCurrentTickSliderCtrl(string strID, int iCurrentTick) { //Регулеровка звука

 switch( iCurrentTick ){
    case 0:
    VolumeR(0.0f);
 break;
    case 1:
    VolumeR(0.2f);
 break;
    case 2:
    VolumeR(0.4f);
 break;
    case 3:
    VolumeR(0.6f);
 break;
    case 4:
    VolumeR(0.8f);
 break;
    case 5:
    VolumeR(1.0f);
 break;
    }
    }

    defaultproperties{

    }
 

Вложения

  • L2InterfaceRadio (2).zip
    2,5 МБ · Просмотры: 7
Похоже в прошлый раз я залил тестовую версию - исправил залил новый архив Radio.

C++:
/******************************************
 Дата 25.10.2024 23:18

 Разработчик: BITHACK

 Copyright (c) Ваша компания

Описание скрипта:
 Интерфейс интернет-радиоплеера с базовыми
 функциями управления воспроизведением из DLL.
*******************************************/
class aaIT_RadioDLL extends UICommonAPI;

 var int count; // Переменная для хранения индекса текущей станции

// Нативные функции, реализованные в Interface.dll
native(1246) final function bool PlayStop(); // Останавливает или запускает воспроизведение
native(1249) final function string GetStreamURL(); // воспроизведение URL
native(1250) final function VolumeR(float ValTick); // воспроизведение URL

// Импортируем текстуры для кнопок из папки interface/RadioIMG
    #exec Texture Import File=RadioIMG/Back.tga Name=Back Mips=Off MASKED=1
    #exec Texture Import File=RadioIMG/Next.tga Name=Next Mips=Off MASKED=1
    #exec Texture Import File=RadioIMG/Stop.tga Name=Stop Mips=Off MASKED=1
    #exec Texture Import File=RadioIMG/Play.tga Name=Play Mips=Off MASKED=1

// Импортируем текстуры для кнопок в нажатом состоянии из папки interface/RadioIMG
    #exec Texture Import File=RadioIMG/Back_down.tga Name=Back_down Mips=Off MASKED=1
    #exec Texture Import File=RadioIMG/Next_down.tga Name=Next_down Mips=Off MASKED=1
    #exec Texture Import File=RadioIMG/Stop_down.tga Name=Stop_down Mips=Off MASKED=1
    #exec Texture Import File=RadioIMG/Play_down.tga Name=Play_down Mips=Off MASKED=1

function OnLoad() { /* Выполняется при старте игры */
    TextBoxHandle(GetHandle("aaIT_RadioDLL.ValueTxt")).SetText("Volume:"); // Устанавливаем название текста Volume
    }

// Функция обработки нажатия на кнопку
function OnClickButton( String strID ) {

 switch( strID ){
    case "PlayStop":
  // Проверяем, запущено ли воспроизведение
 if ( PlayStop() ){
    ButtonHandle(GetHandle("aaIT_RadioDLL.PlayStop")).SetTexture( "interface.Stop", "interface.Stop_down", "Interface.Stop_down"); // Меняем текстуру кнопки на "Stop"
    }else{
    ButtonHandle(GetHandle("aaIT_RadioDLL.PlayStop")).SetTexture( "interface.Play", "interface.Play_down", "Interface.Play_down"); // Меняем текстуру кнопки на "Play"
    }

 break;
    case "PlayBack": //Назад
    count--; // Уменьшаем индекс текущей станции
 if (count == -1) {
    count = 5; // Если индекс выходит за пределы массива, устанавливаем его в 5
    }
    SteamPlay(count); // Переключаемся на предыдущую станцию
 break;
    case "PlayNext"://Вперед
    count++; // Увеличиваем индекс текущей станции
 if (count == 6) {
    count = 0; // Если индекс выходит за пределы массива, устанавливаем его в 0
    }

    SteamPlay(count); // Переключаемся на следующую станцию
 break;
    }
    }

function SteamPlay(int PlayCount){ // Функция для переключения станции
 local array<String> UrlName; //Массив с ID разрешенных банок

    Split(RadioName(PlayCount), "," ,UrlName); // Разделяем строку с адресом и названием на две части
    PlayStreamURL(UrlName[0]); // Запускаем воспроизведение по полученному адресу
    TextBoxHandle(GetHandle("aaIT_RadioDLL.RadioNameTxt")).SetText(UrlName[1]); // Устанавливаем название станции в текстовое поле
    ButtonHandle(GetHandle("aaIT_RadioDLL.PlayStop")).SetTexture( "interface.Stop", "interface.Stop_down", "");

    }

function PlayStreamURL(string URL){ // Функция для запуска воспроизведения по адресу DLL

  URL = GetStreamURL();

    }

function string RadioName(int Radio){ // Функция для получения адреса и названия станции по индексу
 switch( Radio ){
    case 0:
    return "https://hfm.amgradio.ru/HypeFM , Хайп ФМ" ;
 break;
    case 1:
    return "http://paris.discovertrance.com:8006/;stream.nsv , Discover Trance" ;
 break;
    case 2:
    return "http://listen1.myradio24.com:9000/5967 , 90's Eurodance" ;
 break;
    case 3:
    return "https://radiorecord.hostingradio.ru/rr_main96.aacp , Radio Record «Record»" ;
 break;
    case 4:
    return "https://radiorecord.hostingradio.ru/rus96.aacp , Radio Record «Russian Mix»" ;
 break;
    case 5:
    return "https://radiorecord.hostingradio.ru/hype96.aacp, Radio Record «На Хайпе»" ;
 break;

    }
    }

function OnModifyCurrentTickSliderCtrl(string strID, int iCurrentTick) { //Регулеровка звука

 switch( iCurrentTick ){
    case 0:
    VolumeR(0.0f);
 break;
    case 1:
    VolumeR(0.2f);
 break;
    case 2:
    VolumeR(0.4f);
 break;
    case 3:
    VolumeR(0.6f);
 break;
    case 4:
    VolumeR(0.8f);
 break;
    case 5:
    VolumeR(1.0f);
 break;
    }
    }

    defaultproperties{

    }




И выкладывайте скрины своих интернет радио у кого что получилось)
 

Вложения

  • Radio.zip
    686,4 КБ · Просмотры: 8
Реакции: Hedgehog и CodeAmaT

    BladeRunner

    Баллов: 10
    Вот это отличная штука! обычнео радио лень идти включать в браузере, а в игре если просто тыкнуть и заработает - то каеф!
Прикольное дополнение, получилось прикрутить на Grand Crusade клиент. Спасибо
 
Возьми графику с 24hz сервиса в хрониках выше. Там тебе и окошко будет и кнопки и все что нужно. Ну и конечно нужно решить проблему с N одновременно запущенными клиентами, чтобы не было какафонии(если конечно она уже не решена).
 
"какафонии(если конечно она уже не решена)" Нет, я не стал создавать мутексы, поскольку новый клиент запускается с отключённым радио.