Загрузка данных
-- 1. Ждем полной загрузки игры и персонажа (обязательно для autoexec)
if not game:IsLoaded() then
game.Loaded:Wait()
end
local Players = game:GetService("Players")
local HttpService = game:GetService("HttpService")
local TeleportService = game:GetService("TeleportService")
local GuiService = game:GetService("GuiService")
local player = Players.LocalPlayer
if not player then
player = Players.PlayerAdded:Wait()
end
-- Небольшая пауза, чтобы клиент Roblox успел прогрузить список всех игроков на сервере
task.wait(3)
-- НАСТРОЙКИ
local MAX_PLAYERS = 5 -- Максимальное количество игроков (если станет 6 и больше — реконнект)
local placeId = game.PlaceId
local currentJobId = game.JobId
local env = (getgenv and getgenv()) or _G
env.FailedServers = env.FailedServers or {}
env.CandidateServers = {}
env.IsBusy = false
env.HandlingError = false
-- Очищаем старые подписки при перезапуске скрипта
if env.TeleportFailConn then env.TeleportFailConn:Disconnect() end
if env.ErrorMsgConn then env.ErrorMsgConn:Disconnect() end
if env.PlayerAddedConn then env.PlayerAddedConn:Disconnect() end
local findAliveServers
local function tryNextServer()
if env.IsBusy then
return
end
env.IsBusy = true
while #env.CandidateServers > 0 do
local targetServerId = table.remove(env.CandidateServers)
if not env.FailedServers[targetServerId] and targetServerId ~= currentJobId then
env.FailedServers[targetServerId] = true
print("[AutoHop] Переход на сервер: " .. targetServerId .. " (В запасе: " .. #env.CandidateServers .. ")")
pcall(function()
GuiService:ClearError()
end)
local success, err = pcall(function()
TeleportService:TeleportToPlaceInstance(placeId, targetServerId, player)
end)
if not success then
warn("[AutoHop] Ошибка вызова телепорта: " .. tostring(err))
task.wait(1.5)
else
task.delay(8, function()
if env.IsBusy and not env.HandlingError then
env.IsBusy = false
end
end)
return
end
end
end
env.IsBusy = false
warn("[AutoHop] Список серверов закончился. Повторное сканирование через 2 сек...")
task.wait(2)
findAliveServers()
end
local function handleFailure(reason)
if env.HandlingError then
return
end
env.HandlingError = true
warn("[AutoHop] Сбой подключения (" .. tostring(reason) .. "). Смена сервера через 2 сек...")
pcall(function()
GuiService:ClearError()
end)
task.wait(2)
pcall(function()
GuiService:ClearError()
end)
env.IsBusy = false
env.HandlingError = false
tryNextServer()
end
-- Перехват ошибок телепорта (772 и др.)
env.TeleportFailConn = TeleportService.TeleportInitFailed:Connect(function(failedPlayer, teleportResult, errorMessage)
if failedPlayer == player then
handleFailure(tostring(teleportResult.Name) .. " - " .. tostring(errorMessage))
end
end)
-- Перехват сетевых ошибок (277 и др.)
env.ErrorMsgConn = GuiService.ErrorMessageChanged:Connect(function(errorMessage)
if errorMessage and errorMessage ~= "" then
handleFailure("Окно ошибки: " .. tostring(errorMessage))
end
end)
local function getServers(cursor)
local url = "https://games.roblox.com/v1/games/" .. placeId .. "/servers/Public?sortOrder=Asc&excludeFullGames=true&limit=100"
if cursor then
url = url .. "&cursor=" .. HttpService:UrlEncode(cursor)
end
local success, decoded = pcall(function()
local response = game:HttpGet(url)
return HttpService:JSONDecode(response)
end)
if success and type(decoded) == "table" and type(decoded.data) == "table" then
return decoded
end
return nil
end
findAliveServers = function()
local cursor = nil
local pagesChecked = 0
env.CandidateServers = {}
local backupServers = {}
print("[AutoHop] На сервере больше " .. MAX_PLAYERS .. " игроков! Ищем пустой живой сервер...")
repeat
local data = getServers(cursor)
if not data then
warn("[AutoHop] Лимит запросов API Roblox. Ждем 3 сек...")
task.wait(3)
break
end
for _, server in ipairs(data.data) do
if type(server) == "table" and type(server.id) == "string" then
local playing = tonumber(server.playing) or 0
local maxPlayers = tonumber(server.maxPlayers) or 0
local fps = tonumber(server.fps) or 0
local ping = tonumber(server.ping) or 0
local tokens = (type(server.playerTokens) == "table" and #server.playerTokens) or 0
if server.id ~= currentJobId and not env.FailedServers[server.id] and (maxPlayers - playing) >= 2 then
-- Фильтр против ошибки 277 (живой FPS, адекватный пинг, реальные токены)
local isAlive = (fps >= 45) and (ping >= 15 and ping <= 350) and (tokens >= playing)
if playing == 1 and isAlive then
table.insert(env.CandidateServers, server.id)
elseif (playing == 2 or playing == 3) and isAlive then
table.insert(backupServers, server.id)
end
end
end
end
if #env.CandidateServers >= 6 then
break
end
pagesChecked = pagesChecked + 1
cursor = data.nextPageCursor
if cursor and pagesChecked < 4 then
task.wait(0.3)
end
until not cursor or pagesChecked >= 4
-- Если серверов с 1 игроком нет в живых, берем живые с 2-3 игроками (это всё равно меньше лимита в 5)
if #env.CandidateServers == 0 and #backupServers > 0 then
env.CandidateServers = backupServers
end
if #env.CandidateServers > 0 then
print("[AutoHop] Найдено подходящих серверов: " .. #env.CandidateServers)
env.IsBusy = false
tryNextServer()
else
warn("[AutoHop] Подходящих серверов пока нет, повтор через 4 сек...")
task.wait(4)
findAliveServers()
end
end
-- Функция проверки количества игроков на текущем сервере
local function checkPlayerCount()
local currentCount = #Players:GetPlayers()
if currentCount > MAX_PLAYERS then
warn("[AutoHop] Игроков на сервере: " .. currentCount .. " (Лимит: " .. MAX_PLAYERS .. "). Переключаем сервер!")
if not env.IsBusy and not env.HandlingError then
findAliveServers()
end
else
print("[AutoHop] Сервер подходит! Сейчас игроков: " .. currentCount .. " из " .. MAX_PLAYERS .. " допустимых.")
end
end
-- 2. Проверяем онлайн сразу при заходе на сервер
checkPlayerCount()
-- 3. Следим за заходом новых игроков: если зайдет 6-й человек — сразу прыгаем дальше
env.PlayerAddedConn = Players.PlayerAdded:Connect(function()
task.wait(0.5)
checkPlayerCount()
end)