SF Plugin CoolReconnect

Статус
В этой теме нельзя размещать новые ответы.

SR_team

like pancake
Автор темы
BH Team
4,804
6,475
Если вы не играете на samp-rp и у вас уже есть реконнект, то можете пропустить эту тему.
Фишка данного реконнекта в том, что он позволяет переподключиться к серверам СРП после кика, и для этого не придется использовать сраунчер или сворачивать игру и кликать по серверу в обычном лаунчере - udp пропинговка встроенна в плагин!

Использование 1: /rej <time> - переподключиться к серверу с заданным временем. Время указывается в секундах
Использование 2: /rej <time> <nick> - то же, что и выше, но со сменой ника.
Команду так же можно вызывать из консоли SF. Пример: rej <time> | rej <time> <nick>

P.S. На других серверах реконнект тоже работает.

C++:
#define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS

#include <windows.h>
#include <string>
#include <assert.h>
#include <process.h>
#include <regex>
#include <thread>
#include <atomic>
#include <future>
#pragma comment(lib, "WS2_32")

#include "SAMPFUNCS_API.h"
#include "game_api\game_api.h"

SAMPFUNCS *SF = new SAMPFUNCS();

template <typename T>
union byteValue {
    T value;
    byte bytes[sizeof(T)];
};

void UdpThread(std::string ip, byte ip_0, byte ip_1, byte ip_2, byte ip_3, WORD port)
{
    WSADATA wsaData;
    SOCKET SendRecvSocket;  // сокет для приема и передачи
    sockaddr_in ServerAddr;  // это будет адрес сервера и клиентов
    char query[64];  // буфер отправки

                    // Initialize Winsock
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    // Create a SOCKET for connecting to server
    SendRecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

    ServerAddr.sin_family = AF_INET;
    ServerAddr.sin_addr.s_addr = inet_addr(ip.c_str());
    ServerAddr.sin_port = htons(port);

    connect(SendRecvSocket, (struct sockaddr *)&ServerAddr, sizeof(sockaddr));

    query[0] = 'S';
    query[1] = 'A';
    query[2] = 'M';
    query[3] = 'P';

    query[4] = ip_0;
    query[5] = ip_1;
    query[6] = ip_2;
    query[7] = ip_3;
    byteValue<WORD> _port;
    _port.value = port;
    query[8] = _port.bytes[0];
    query[9] = _port.bytes[1];
    query[11] = '\0';

    // отправляем запрос на сервер
    for (int i = 0; i < 3; ++i) {
        query[10] = 'p';
        sendto(SendRecvSocket, query, strlen(query), 0, (sockaddr *)&ServerAddr, sizeof(ServerAddr));
        query[10] = 'i';
        sendto(SendRecvSocket, query, strlen(query), 0, (sockaddr *)&ServerAddr, sizeof(ServerAddr));
        query[10] = 'r';
        sendto(SendRecvSocket, query, strlen(query), 0, (sockaddr *)&ServerAddr, sizeof(ServerAddr));
        Sleep(250);
    }

    closesocket(SendRecvSocket);
    WSACleanup();
}

DWORD g_timer = 0;
const std::regex REJ_NICK(R"(\s*(\d+)\s*(.{3,26})\s*)");
const std::regex REJ_TIME(R"(\s*(\d+)\s*)");

void CALLBACK cmd(std::string param)
{
    std::smatch match;
    if (std::regex_match(param, match, REJ_NICK)) {
        SF->getSAMP()->disconnect(100);

        SF->getSAMP()->getPlayers()->SetLocalPlayerName(match[2].str().c_str());
        g_timer = atoi(match[1].str().c_str()) * 1000 + GetTickCount();
    }
    else if (std::regex_match(param, match, REJ_TIME)) {
        SF->getSAMP()->disconnect(100);

        g_timer = atoi(match[1].str().c_str()) * 1000 + GetTickCount();
    }
    else SF->Log("[CoolReconnect]: Can't match '%s'", param.c_str());
}

void CALLBACK mainloop()
{
    static bool init = false;
    if (!init)
    {
        if (GAME == nullptr)
            return;
        if (GAME->GetSystemState() != eSystemState::GS_PLAYING_GAME)
            return;
        if (!SF->getSAMP()->IsInitialized())
            return;
        SF->registerConsoleCommand("rej", cmd);
        SF->getSAMP()->registerChatCommand("rej", cmd);
        SF->getSAMP()->setChatCommandDescription("rej", "{FFFFAAAA}see help for console rej");
        SF->setConsoleCommandDescription("rej", "Reconnect to server.\n\
{FFFFFFFF}Can get 2 params:\n\
{FFFFFFFF}--1: time\n\
{FFFFFFFF}--2: nick\n\n\
{FFAAFFAA}Example: rej 15\n\
{FFAAFFAA}Example: rej 15 SR_team\n");

        init = true;
    }
    else if (g_timer)
    {
        static bool UdpReconnect = false;
        if (g_timer - GetTickCount() < 5000 && !UdpReconnect) {
            char newIp[64];
            WSADATA wsaData;
            WSAStartup(MAKEWORD(1, 1), &wsaData);
            struct hostent *he = gethostbyname(SF->getSAMP()->getInfo()->szIP);
            if (he != NULL) {
                strcpy(newIp, inet_ntoa(*((struct in_addr *) he->h_addr_list[0])));
            }
            WSACleanup();

            byte ip_0 = 127;
            byte ip_1 = 0;
            byte ip_2 = 0;
            byte ip_3 = 1;
            if (sscanf(newIp, "%d.%d.%d.%d", &ip_0, &ip_1, &ip_2, &ip_3)) {
                std::thread thr(UdpThread, std::string(newIp), ip_0, ip_1, ip_2, ip_3, SF->getSAMP()->getInfo()->ulPort);
                thr.detach();
                UdpReconnect = true;
            }
        }
        if (g_timer > GetTickCount())
            return;
        SF->getSAMP()->getInfo()->RestartGame();
        SF->getSAMP()->getInfo()->iGameState = GAMESTATE_WAIT_CONNECT;
        g_timer = 0;
        UdpReconnect = false;
    }
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReasonForCall, LPVOID lpReserved)
{
    switch (dwReasonForCall)
    {
        case DLL_PROCESS_ATTACH:
            SF->initPlugin(mainloop, hModule);
            break;
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
    }
    return TRUE;
}
 

Вложения

  • CoolReconnect.sf
    335.5 KB · Просмотры: 552

ID_Heaven

Известный
812
294
Если вы не играете на samp-rp и у вас уже есть реконнект, то можете пропустить эту тему.
f5fa59f8190946deba2d492370232692.png
 

DarkP1xel

Сила воли наше всё.
BH Team
3,635
4,983
Завуалированные строки. Они понятны, но не многим.
 

-Bamboocho-

Известный
142
17
Годный плагин.
Можешь добавить настройку (командой или иник) что бы при реконнекте очищало чат, как будто ты только зашел на сервер?
 
Последнее редактирование:

SR_team

like pancake
Автор темы
BH Team
4,804
6,475
Годный плагин.
Можешь добавить настройку (командой или иник) что бы при реконнекте очищало чат, какбудт-то ты только зашел на сервер?
Ты сам можешь добавить! Исходник отрытый
 
  • Нравится
Реакции: 4el0ve4ik

MAHEKEH

Известный
2,010
504
После ввода команды ждет минуты 2,затем рекконектит с указанным временем.Так и задумывалось?
 

Clopster

Известный
143
96
А этот плагин исправляет хрень что мол сервер не отвечает, когда реконнектишься 2-3 раз за сессию?
 

Clopster

Известный
143
96
если ты про реконнект без задержки, то нет. ставь хотя бы 3 секунды
нее. Вот лично у меня такая проблема и еще у нескольких людей, которых я спрашивал, что когда ты обычным реконектом (или с обходом краша для ДРП) реконектишься на сервер с обычной задержкой >15 секунд (ибо на серверах ограничение), то на какой-то раз (а иногда и с первой попытки), при подключении будет постоянно выдавать "The server didn't respond. Retrying.." и пока в игру не перезайдешь, к серву не подключишься. А тут я увидел что мол пингует и еще пара умных слов и еще раз это реконект, значит он должен как-то отличаться от других. И я вообще хз почему ты сделал акцент на Samp-RP, потому что я туда сразу попробовал реконектнуться обычным и вроде как все удачно прошло.
 
Статус
В этой теме нельзя размещать новые ответы.

Похожие темы

  1. Ответы
    18
    Просмотры
    26K