Загрузка данных
local Players = game:GetService("Players")
local HttpService = game:GetService("HttpService")
local TeleportService = game:GetService("TeleportService")
local GuiService = game:GetService("GuiService")
local CoreGui = game:GetService("CoreGui")
local MAX_PLAYERS = 5
local placeId = game.PlaceId
local currentJobId = game.JobId
local env = (getgenv and getgenv()) or _G
env.RunId = (env.RunId or 0) + 1
local currentRunId = env.RunId
env.FailedServers = env.FailedServers or {}
env.CandidateServers = env.CandidateServers or {}
env.IsSearching = false
env.IsTeleporting = false
if env.TeleportFailConn then env.TeleportFailConn:Disconnect() end
if env.PlayerAddedConn then env.PlayerAddedConn:Disconnect() end
local cacheFileName = "ServerCache_" .. tostring(placeId) .. ".json"
-- Загрузка и сохранение кэша (чтобы сторож 277 знал, куда прыгать прямо с экрана загрузки)
local function loadCache()
if readfile and isfile and isfile(cacheFileName) then
local ok, data = pcall(function()
return HttpService:JSONDecode(readfile(cacheFileName))
end)
if ok and type(data) == "table" and type(data.servers) == "table" then
if type(data.failed) == "table" then
for k, v in pairs(data.failed) do
env.FailedServers[k] = v
end
end
if data.time and (os.time() - data.time) < 120 then
return data.servers
end
end
end
return nil
end
local function saveCache(servers)
if writefile then
pcall(function()
writefile(cacheFileName, HttpService:JSONEncode({
time = os.time(),
servers = servers or env.CandidateServers,
failed = env.FailedServers
}))
end)
end
end
-- Проверяем, висит ли сейчас окно любой ошибки (277, 772, 267 и т.д.)
local function isErrorOnScreen()
local okCode, errCode = pcall(function()
return GuiService:GetErrorCode()
end)
if okCode and errCode and errCode ~= Enum.ConnectionError.OK then
return true
end
local okGui, hasPrompt = pcall(function()
local promptOverlay = CoreGui:FindFirstChild("RobloxPromptGui")
and CoreGui.RobloxPromptGui:FindFirstChild("promptOverlay")
if promptOverlay then
local errPrompt = promptOverlay:FindFirstChild("ErrorPrompt")
if errPrompt and errPrompt.Visible then
return true
end
end
return false
end)
return okGui and hasPrompt
end
local findAliveServers
local function tryNextServer()
if env.RunId ~= currentRunId then return end
if #env.CandidateServers == 0 then
local cached = loadCache()
if cached and #cached > 0 then
env.CandidateServers = cached
end
end
while #env.CandidateServers > 0 do
local targetServerId = table.remove(env.CandidateServers, 1)
if not env.FailedServers[targetServerId] and targetServerId ~= currentJobId then
env.FailedServers[targetServerId] = true
env.IsTeleporting = true
saveCache(env.CandidateServers)
print("[AutoHop] Телепорт на сервер: " .. targetServerId .. " (В запасе: " .. #env.CandidateServers .. ")")
pcall(function()
GuiService:ClearError()
end)
local lp = Players.LocalPlayer
local success, err = pcall(function()
if lp then
TeleportService:TeleportToPlaceInstance(placeId, targetServerId, lp)
else
TeleportService:TeleportToPlaceInstance(placeId, targetServerId)
end
end)
if not success then
warn("[AutoHop] Ошибка вызова телепорта: " .. tostring(err))
env.IsTeleporting = false
task.wait(1.5)
else
return
end
end
end
env.IsTeleporting = false
env.IsSearching = false
-- Если мы застряли на экране ошибки 277 и кэш пуст, делаем обычный реконнект в игру, чтобы оживить сеть
if isErrorOnScreen() then
warn("[AutoHop] Кэш пуст во время ошибки 277! Перезаходим в плейс...")
pcall(function() GuiService:ClearError() end)
pcall(function() TeleportService:Teleport(placeId) end)
return
end
warn("[AutoHop] Список серверов закончился. Новый поиск через 8 сек...")
task.wait(8)
if env.RunId == currentRunId then
findAliveServers(true)
end
end
-- ============================================================================
-- СТОРОЖ ОШИБКИ 277 (Запускается СРАЗУ, даже если игра зависла на загрузке!)
-- ============================================================================
task.spawn(function()
while env.RunId == currentRunId do
if isErrorOnScreen() then
warn("[AutoHop] Обнаружена ошибка 277 / окно дисконнекта! Переподключение через 2 сек...")
task.wait(2)
if env.RunId ~= currentRunId then break end
pcall(function()
GuiService:ClearError()
end)
env.IsTeleporting = false
env.IsSearching = false
tryNextServer()
-- Ждем 4 секунды, чтобы телепорт успел начаться; если ошибка не ушла — цикл нажмет еще раз
task.wait(4)
end
task.wait(0.8)
end
end)
env.TeleportFailConn = TeleportService.TeleportInitFailed:Connect(function(failedPlayer, teleportResult, errorMessage)
if env.RunId ~= currentRunId then return end
if not Players.LocalPlayer or failedPlayer == Players.LocalPlayer then
warn("[AutoHop] Отказ телепорта (" .. tostring(teleportResult.Name) .. "). Меняем сервер...")
task.wait(2)
pcall(function() GuiService:ClearError() end)
env.IsTeleporting = false
tryNextServer()
end
end)
-- ============================================================================
-- ОЖИДАНИЕ ЗАГРУЗКИ МИРА (Теперь не блокирует сторожа ошибки 277!)
-- ============================================================================
if not game:IsLoaded() then
game.Loaded:Wait()
end
local player = Players.LocalPlayer or Players.PlayerAdded:Wait()
task.wait(2.5)
currentJobId = game.JobId
local function fetchServerPage(cursor)
local endpoints = {
"https://games.roblox.com/v1/games/" .. placeId .. "/servers/Public?sortOrder=Asc&excludeFullGames=true&limit=100",
"https://games.roproxy.com/v1/games/" .. placeId .. "/servers/Public?sortOrder=Asc&excludeFullGames=true&limit=100"
}
for i, baseUrl in ipairs(endpoints) do
local url = baseUrl
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
if i == 1 then
task.wait(1)
end
end
return nil
end
findAliveServers = function(ignoreCache)
if env.RunId ~= currentRunId then return end
if env.IsSearching or env.IsTeleporting then return end
env.IsSearching = true
if not ignoreCache then
local cached = loadCache()
if cached and #cached > 0 then
print("[AutoHop] Взято серверов из кэша: " .. #cached)
env.CandidateServers = cached
tryNextServer()
return
end
end
print("[AutoHop] Сканирование серверов (ищем меньше " .. MAX_PLAYERS .. " игроков)...")
local data = fetchServerPage(nil)
if not data then
warn("[AutoHop] Лимит запросов API. Ждем 15 сек...")
task.wait(15)
env.IsSearching = false
if env.RunId == currentRunId then
findAliveServers(true)
end
return
end
local collected = {}
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 60
local ping = tonumber(server.ping) or 100
if server.id ~= currentJobId and not env.FailedServers[server.id] then
if playing >= 1 and playing < MAX_PLAYERS and (maxPlayers - playing) >= 2 and fps >= 30 and ping <= 500 then
table.insert(collected, { id = server.id, playing = playing })
end
end
end
end
table.sort(collected, function(a, b)
return a.playing < b.playing
end)
env.CandidateServers = {}
for _, item in ipairs(collected) do
table.insert(env.CandidateServers, item.id)
end
if #env.CandidateServers > 0 then
print("[AutoHop] Найдено серверов: " .. #env.CandidateServers)
saveCache(env.CandidateServers)
tryNextServer()
else
warn("[AutoHop] Подходящих серверов на странице нет. Повтор через 10 сек...")
task.wait(10)
env.IsSearching = false
if env.RunId == currentRunId then
findAliveServers(true)
end
end
end
local function checkPlayerCount()
if env.RunId ~= currentRunId then return end
local currentCount = #Players:GetPlayers()
if currentCount > MAX_PLAYERS then
if not env.IsSearching and not env.IsTeleporting then
warn("[AutoHop] На сервере " .. currentCount .. " игроков (лимит: " .. MAX_PLAYERS .. "). Переключаем сервер...")
findAliveServers(false)
end
else
print("[AutoHop] Сервер подходит! Игроков: " .. currentCount .. "/" .. MAX_PLAYERS)
end
end
checkPlayerCount()
env.PlayerAddedConn = Players.PlayerAdded:Connect(function()
task.wait(0.5)
checkPlayerCount()
end)