Created
January 19, 2025 22:19
-
-
Save EklipZgit/c221e3d7a35f4f5133c3d9195eff8fbe to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name zzd233's Queue Sniper | |
// @namespace http://tampermonkey.net/ | |
// @version 1.1 | |
// @description A tool for 1v1 to get stars. v1.1 changes: Updated to use new recent games APIs. Improved performance. Stop ddosing server from other browser tabs. Improve layout and formatting to fit more names and resize large lists better. | |
// @author zzd233 + EklipZ | |
// @match https://*.generals.io/* | |
// @icon https://generals.io/favicon/favicon-32x32.png | |
// @grant none | |
// ==/UserScript== | |
let abs = Math.abs, max = Math.max, min = Math.min; | |
function load(src) { | |
return new Promise((resolve, reject) => { | |
let c = document.createElement('script'); | |
c.src = src; | |
c.addEventListener('load', resolve); | |
c.addEventListener('error', reject); | |
document.body.appendChild(c); | |
}); | |
} | |
let logDebug = false; | |
// let socket; | |
// function waitConnect() { | |
// return new Promise((resolve, reject) => { | |
// socket.once('disconnect', reject); | |
// socket.once('connect', resolve); | |
// }); | |
// } | |
function clickButton(text) { | |
Array.from(document.getElementsByTagName('button')).find(e => e.innerText.trim().toLowerCase() === text.toLowerCase().trim()).click(); | |
} | |
function shouldRenderSniperModal() { | |
const mainMenuSideButtons = document.getElementById('main-menu-side-buttons'); | |
if (mainMenuSideButtons && mainMenuSideButtons.checkVisibility()) | |
return true; | |
const tipBanner = document.getElementById('tip-banner'); | |
if (tipBanner && tipBanner.checkVisibility()) | |
return true; | |
const queueAd = document.getElementById('custom-queue-bottom-ad'); | |
if (queueAd && queueAd.checkVisibility()) { | |
let buttons = Array.from(document.getElementsByTagName('button')).map(a => a.innerHTML); | |
if (!buttons.find(a => a === "PLAY" || a === "1v1" || a === "Play Again" || a === "Cancel")) { | |
return false; | |
} | |
return true; | |
} | |
const customQueueAd = document.getElementById('custom-queue-ad-top'); | |
if (customQueueAd && customQueueAd.checkVisibility()) { | |
let buttons = Array.from(document.getElementsByTagName('button')).map(a => a.innerHTML); | |
if (!buttons.find(a => a === "PLAY" || a === "1v1" || a === "Play Again" || a === "Cancel")) { | |
return false; | |
} | |
return true; | |
} | |
const igc = document.getElementById('in-game-chat'); | |
if (igc && igc.checkVisibility()) { | |
var isGameOver = false; | |
for (var n of igc.childNodes.item(0).childNodes.item(0).childNodes) { | |
if (n.classList.contains('server-chat-message')) { | |
const messageItem = n.childNodes.item(3); | |
if (messageItem && messageItem.textContent.endsWith(' wins!')) { | |
isGameOver = true; | |
break; | |
} | |
} | |
// console.log(n); | |
} | |
return isGameOver; | |
} | |
// const userNameInput = document.getElementById('main-menu-username-input'); | |
// if (userNameInput && userNameInput.checkVisibility()) | |
// return true; | |
// let buttons = Array.from(document.getElementsByTagName('button')).map(a => a.innerHTML); | |
// if (!buttons.find(a => a === "PLAY" || a === "1v1" || a === "Play Again" || a === "Cancel")) { | |
// return false; | |
// } | |
// return true; | |
return false; | |
} | |
async function load_elements() { | |
let c = document.createElement("style"); | |
c.innerHTML = ` | |
body { | |
background-color: #222; | |
} | |
#Sniper-all { | |
-moz-user-select: none; | |
-webkit-user-select: none; | |
-ms-user-select: none; | |
-khtml-user-select: none; | |
user-select: none; | |
z-index: 9999; | |
position: absolute; | |
top: 70px; | |
left: 10px; | |
width: 343px; | |
} | |
#Sniper-option, #Sniper-list { | |
font-size: 18px; | |
background-color: #333333; | |
border: #333333 solid 5px; | |
border-radius: 1px; | |
// font-family: Quicksand-Bold; | |
//text-shadow: 1px 1px 1px white; | |
} | |
#Sniper-title { | |
font-size: 22px; | |
height: 30px; | |
padding: 5px 10px 0px 10px; | |
} | |
#Sniper-option { | |
margin-top: 5px; | |
height: 164px; | |
padding: 10px 10px 10px 10px; | |
} | |
#Sniper-range { | |
border: #333333 solid 3px; | |
margin-bottom: 3px; | |
color: white; | |
} | |
#Sniper-list { | |
text-align: center; | |
margin-top: 5px; | |
font-size: 18px; | |
min-height: 260px; | |
max-height: 60vh; | |
padding: 5px 5px 5px 5px; | |
overflow-y: scroll; | |
} | |
#Sniper-list-table { | |
display: table; | |
} | |
.Sniper-button { | |
border: teal solid 1px; | |
border-radius: 1px; | |
background-color: teal; | |
height: 25px; | |
width: 50px; | |
text-align: center; | |
color: white; | |
} | |
#Sniper-button4 { | |
border: teal solid 1px; | |
border-radius: 1px; | |
background-color: teal; | |
height: 25px; | |
width: 76px; | |
text-align: center; | |
color: white; | |
} | |
#Sniper-enable_match, #Sniper-enable_leaderboard, #Sniper-enable_friends, #Sniper-new_friend, #Sniper-toggle_list { | |
display: flex; | |
flex-direction: row; | |
align-items: center; | |
color: white; | |
} | |
#Sniper-match-starbound { | |
font-size: 15px; | |
height: 30px; | |
width: 45px; | |
color: black; | |
} | |
#Sniper-new_friend { | |
padding-top: 3px; | |
color: white; | |
} | |
#Sniper-addfriend { | |
text-align: left; | |
font-size: 12px; | |
height: 25px; | |
width: 90px; | |
color; white; | |
} | |
.Sniper-table_row { | |
text-align: center; | |
display: table-row; | |
color: white; | |
} | |
.Sniper-table_cell { | |
text-align: center; | |
color: white; | |
display: table-cell; | |
border: #333333 solid 1px; | |
padding: 1px 1px 1px 1px; | |
} | |
.Sniper-header { | |
text-align: center; | |
background-color: teal; | |
color: white; | |
} | |
.Sniper-friendcell { | |
background-color: teal; | |
color: white; | |
} | |
.Sniper-name { | |
width: 75%; | |
// text-align: right; | |
} | |
.Sniper-links { | |
text-align: center; | |
color: white; | |
} | |
#Sniper-titlelink { | |
color: white; | |
text-align: center; | |
text-shadow: 2px 2px teal; | |
font-family: Quicksand-Bold; | |
} | |
`; | |
c.rel = "stylesheet"; | |
document.body.appendChild(c); | |
let d = document.createElement("div"); | |
d.innerHTML = ` | |
<div id = "Sniper-all" hidden = "true"> | |
<div id = "Sniper-title"> | |
<a id = "Sniper-titlelink" href = "https://generals.io" target = "_blank">Generals.io 1v1 Match Helper</a> | |
</div> | |
<div id = "Sniper-option"> | |
<div id = "Sniper-range"> | |
<div> | |
Finding Range | |
</div> | |
<div id = "Sniper-enable_leaderboard"> | |
<div> | |
Leaderboard: ★ ≥ | |
</div> | |
<input id = "Sniper-match-starbound" placeholder = "inf"> | |
<div class = "Sniper-button" id = "Sniper-button2">OFF</div> | |
</div> | |
<div id = "Sniper-enable_friends"> | |
<div> | |
Friends: | |
</div> | |
<div class = "Sniper-button" id = "Sniper-button3">OFF</div> | |
</div> | |
<div id = "Sniper-enable_match"> | |
<div> | |
Auto Match: | |
</div> | |
<div class = "Sniper-button" id = "Sniper-button1">OFF</div> | |
</div> | |
<div id = "Sniper-new_friend"> | |
<div> Modify friend: </div> | |
<input id = "Sniper-addfriend" placeholder = "Someone"> | |
<div id = "Sniper-button4"> | |
Add/Del | |
</div> | |
</div> | |
<div id = "Sniper-toggle_list"> | |
<div> | |
Show list: | |
</div> | |
<div class = "Sniper-button" id = "Sniper-toggle">ON</div> | |
</div> | |
</div> | |
</div> | |
<div id = "Sniper-list"> | |
<div id = "Sniper-list-table"> | |
</div> | |
</div> | |
</div> | |
`; | |
document.body.appendChild(d); | |
} | |
let main_div, button1, button2, button3, button4, option_element, list_element, toggle; | |
let match_starbound, addfriend; | |
let list_table; | |
let enable_auto_match = false; | |
let enable_leaderboard = false; | |
let enable_friends = false; | |
let friend_list = []; | |
const Eps = 1e-3; | |
let myname = undefined; | |
let data = {};//store other's star and last 1v1 game time; example: data["zzd233"] = {star: 70.00, time: 1617360510077} | |
let friend_dictionary = {}; | |
function px2int(s) { | |
return parseInt(s.substr(0, s.length - 2)); | |
} | |
function int2px(a) { | |
return `${a}px`; | |
} | |
function main() { | |
// after one second, try to run the thing, hopefully the site is loaded by then (?) | |
setTimeout(async () => { | |
// let lib_socket = 'https://cdn.jsdelivr.net/npm/socket.io-client@4/dist/socket.io.js'; | |
let lib_jquery = 'https://code.jquery.com/jquery-3.6.0.min.js'; | |
// await load(lib_socket); | |
await load(lib_jquery); | |
await load_elements(); | |
// Detect when this is the active tab or not. | |
let isWindowFocused = true; | |
$(window).on("blur focus", function(e) { | |
var prevType = $(this).data("prevType"); | |
if (prevType != e.type) { // reduce double fire issues | |
switch (e.type) { | |
case "blur": | |
isWindowFocused = false; | |
break; | |
case "focus": | |
isWindowFocused = true; | |
break; | |
} | |
} | |
$(this).data("prevType", e.type); | |
}); | |
// // This opens its own socket...? Why not grab the socket thats already open, is that not possible with js? | |
// socket = io('https://ws.generals.io'); | |
// await waitConnect(); | |
// console.log('connected'); | |
function get_myname() { | |
let tmp = document.getElementById('main-menu-username-input'); | |
if (tmp) | |
myname = tmp.value; | |
} | |
get_myname(); | |
main_div = document.getElementById('Sniper-all'); | |
let local_main_div_position = JSON.parse(localStorage.getItem("SniperScript_main_div_position")); | |
if (!local_main_div_position) { | |
local_main_div_position = {x: 0, y: 0}; | |
localStorage.setItem("SniperScript_main_div_position", JSON.stringify(local_main_div_position)); | |
} | |
main_div.style.left = int2px(local_main_div_position.x); | |
main_div.style.top = int2px(local_main_div_position.y); | |
button1 = document.getElementById('Sniper-button1'); | |
button2 = document.getElementById('Sniper-button2'); | |
button3 = document.getElementById('Sniper-button3'); | |
button4 = document.getElementById('Sniper-button4'); | |
toggle = document.getElementById('Sniper-toggle'); | |
option_element = document.getElementById('Sniper-option'); | |
list_element = document.getElementById('Sniper-list'); | |
toggle.style.backgroundColor = "teal"; | |
if(window.localStorage["QUEUE_SNIPER_HIDE_LIST"] == "hide") { | |
toggle.textContent = "OFF"; | |
list_element.style.display = "none"; | |
toggle.style.backgroundColor = "#333333"; | |
} | |
toggle.addEventListener('click', () => { | |
if(window.localStorage["QUEUE_SNIPER_HIDE_LIST"] == "hide") { | |
window.localStorage["QUEUE_SNIPER_HIDE_LIST"] = "show"; | |
toggle.textContent = "ON"; | |
list_element.style.display = ""; | |
toggle.style.backgroundColor = "teal"; | |
} else { | |
window.localStorage["QUEUE_SNIPER_HIDE_LIST"] = "hide"; | |
toggle.textContent = "OFF"; | |
list_element.style.display = "none"; | |
toggle.style.backgroundColor = "#333333"; | |
} | |
}); | |
match_starbound = document.getElementById("Sniper-match-starbound"); | |
addFriendInputBox = document.getElementById("Sniper-addfriend"); | |
list_table = document.getElementById("Sniper-list-table"); | |
var enable_match = false; | |
let settings = JSON.parse(localStorage.getItem("zzdscript_settings")); | |
if (!settings) { | |
settings = [enable_match, enable_leaderboard, enable_friends, "50"]; | |
localStorage.setItem('zzdscript_settings',JSON.stringify(settings)); | |
} | |
[enable_match, enable_leaderboard, enable_friends, match_starbound.value] = settings; | |
if (enable_match) { | |
button1.innerHTML = "ON"; | |
button1.style.backgroundColor = "teal"; | |
} else { | |
button1.innerHTML = "OFF"; | |
button1.style.backgroundColor = "#333333"; | |
} | |
if (enable_leaderboard) { | |
button2.innerHTML = "ON"; | |
button2.style.backgroundColor = "teal"; | |
} else { | |
button2.innerHTML = "OFF"; | |
button2.style.backgroundColor = "#333333"; | |
} | |
if (enable_friends) { | |
button3.innerHTML = "ON"; | |
button3.style.backgroundColor = "teal"; | |
} else { | |
button3.innerHTML = "OFF"; | |
button3.style.backgroundColor = "#333333"; | |
} | |
friend_list = JSON.parse(localStorage.getItem("zzdscript_Friends")); | |
if (!friend_list) { | |
friend_list = []; | |
localStorage.setItem("zzdscript_Friends", JSON.stringify(friend_list)); | |
} | |
for (let name of friend_list) | |
friend_dictionary[name] = true; | |
button1.addEventListener('click', () => { | |
if (button1.innerHTML === "OFF") { | |
button1.innerHTML = "ON"; | |
button1.style.backgroundColor = "teal"; | |
enable_match = true; | |
} else { | |
button1.innerHTML = "OFF"; | |
button1.style.backgroundColor = "#333333"; | |
enable_match = false; | |
} | |
settings = [enable_match, enable_leaderboard, enable_friends, match_starbound.value]; | |
localStorage.setItem('zzdscript_settings',JSON.stringify(settings)); | |
}); | |
button2.addEventListener('click', () => { | |
if (button2.innerHTML === "OFF") { | |
button2.innerHTML = "ON"; | |
button2.style.backgroundColor = "teal"; | |
enable_leaderboard = true; | |
} else { | |
button2.innerHTML = "OFF"; | |
button2.style.backgroundColor = "#333333"; | |
enable_leaderboard = false; | |
} | |
settings = [enable_match, enable_leaderboard, enable_friends, match_starbound.value]; | |
localStorage.setItem('zzdscript_settings',JSON.stringify(settings)); | |
}); | |
button3.addEventListener('click', () => { | |
if (button3.innerHTML === "OFF") { | |
button3.innerHTML = "ON"; | |
button3.style.backgroundColor = "teal"; | |
enable_friends = true; | |
} else { | |
button3.innerHTML = "OFF"; | |
button3.style.backgroundColor = "#333333"; | |
enable_friends = false; | |
} | |
settings = [enable_match, enable_leaderboard, enable_friends, match_starbound.value]; | |
localStorage.setItem('zzdscript_settings',JSON.stringify(settings)); | |
}); | |
function executeAddDelFriend() { | |
let name = addFriendInputBox.value.trim(); | |
if (name.length === 0) | |
return; | |
let index = friend_list.findIndex(x => x === name); | |
if (index === -1) { | |
friend_list.push(name); | |
friend_dictionary[name] = true; | |
} else { | |
friend_list.splice(index,1); | |
friend_dictionary[name] = undefined; | |
} | |
addFriendInputBox.value = ""; | |
localStorage.setItem("zzdscript_Friends", JSON.stringify(friend_list)); | |
} | |
button4.addEventListener('click', executeAddDelFriend); | |
addFriendInputBox.addEventListener('keydown', (kEvent) => { | |
if (kEvent.keyCode === 13) | |
executeAddDelFriend(); | |
}); | |
let leaderboard_initialized = false, leaderboard_cnt = 0; | |
let NOREPLAY = ""; | |
let time_delta = 0; | |
let real_time = Number(new Date($.ajax({async:false}).getResponseHeader("Date"))); | |
let system_time = Number(new Date()); | |
time_delta = real_time - system_time; | |
console.log(`time_delta = `, time_delta); | |
// Auto-hide on pages where this shouldnt show | |
setInterval(async () => { | |
if (!shouldRenderSniperModal()) { | |
main_div.hidden = true; | |
} | |
}, 100); | |
var lastUpdatedLadder = 0; | |
let players_from_leaderboard, bound; | |
let tasks = 0, time_0 = undefined, friend_list_loaded = false; | |
let count_tasks_n0 = 0, last_tasks = -1; | |
let requestNumber = 0; | |
players_from_leaderboard = new Set(); | |
// Every half second, update the leaderboard | |
let main_interval = setInterval(async () => { | |
requestNumber++; | |
// Dont DDOS the server and get ourselves banned running for non-focused windows. | |
if (!isWindowFocused && requestNumber % 20 !== 0 && !enable_auto_match) { | |
if (logDebug) | |
console.log(`Skipping iteration ${requestNumber} because isWindowFocused ${isWindowFocused}`); | |
return; | |
} | |
if (logDebug) | |
console.log(`Main iteration: Tasks ${tasks}, last_tasks ${last_tasks}, count_tasks_n0 ${count_tasks_n0}`); | |
if (tasks !== 0 && last_tasks === tasks) | |
count_tasks_n0 ++; | |
else | |
count_tasks_n0 = 0; | |
if (count_tasks_n0 > 500) { | |
// clearInterval(main_interval); | |
tasks = count_tasks_n0 = 0; | |
} | |
last_tasks = tasks; | |
if (tasks < 0) { | |
clearInterval(main_interval); | |
throw "tasks < 0"; | |
} | |
if (tasks > 0) | |
return; | |
if (time_0 !== undefined) { | |
let now = Number(new Date()) + time_delta; | |
if (now - time_0 > 2500) | |
console.log(new Date(), `last fetch time = ${now - time_0}ms ago`); | |
let pool = []; | |
if (enable_friends) | |
for (let name of friend_list) { | |
if (!data.hasOwnProperty(name)) | |
continue; | |
pool.push({ | |
name: name, | |
star: data[name].star, | |
time_past: isNaN(data[name].time) ? NaN : now - data[name].time, | |
isfriend: true, | |
type: data[name].type, | |
}); | |
} | |
if (enable_leaderboard) { | |
for (let name of players_from_leaderboard) { | |
if (!name) | |
continue; | |
if ((friend_dictionary[name] === true && enable_friends) || !data[name] || !(data[name].star > bound) || name === myname) | |
continue; | |
if (isNaN(data[name].time) || now - data[name].time > 1000 * 60 * 30) | |
continue; | |
pool.push({ | |
name: name, | |
star: data[name].star, | |
time_past: isNaN(data[name].time) ? NaN : now - data[name].time, | |
isfriend: false, | |
type: data[name].type, | |
}); | |
} | |
} | |
pool.sort((a, b) => { | |
let [x, y] = [a.time_past, b.time_past]; | |
if (isNaN(x) && isNaN(y)) { | |
return b.star - a.star; | |
} | |
if (isNaN(x) !== isNaN(y)) | |
return isNaN(x) ? 1 : -1; | |
return x - y; | |
}); | |
let htmlstring = ` | |
<div class = "Sniper-table_row"> | |
<div class = "Sniper-table_cell Sniper-header Sniper-name"> | |
PLAYER | |
</div> | |
<div class = "Sniper-table_cell Sniper-header"> | |
★ | |
</div> | |
<div class = "Sniper-table_cell Sniper-header"> | |
1V1 | |
</div> | |
<div class = "Sniper-table_cell Sniper-header"> | |
LAST | |
</div> | |
</div> | |
`; | |
function time_past_to_string(t) { | |
if (isNaN(t)) | |
return ""; | |
t = Math.floor(t / 1000); | |
if (t < 60) | |
return `${t}s`; | |
else if (t < 3600) | |
return `${Math.floor(t/60)}m`; | |
else if (t < 3600 * 24) | |
return `${(t/3600).toFixed(1)}h`; | |
else if (t < 3600 * 24 * 30) | |
return `${(t/(3600 * 24)).toFixed(1)}d`; | |
else | |
return ''; | |
} | |
for (let user of pool) { | |
var typeName = user.type === 'classic' ? 'FFA' : (user.type === 'custom' ? 'Cust' : user.type); | |
htmlstring += ` | |
<div class = "Sniper-table_row"> | |
<div class = "Sniper-table_cell ${user.isfriend ? "Sniper-friendcell" : ""} Sniper-name"> | |
<a class = "Sniper-links" href = "https://generals.io/profiles/${encodeURIComponent(user.name)}" target = "_blank">${user.name}</a> | |
</div> | |
<div class = "Sniper-table_cell ${user.isfriend ? "Sniper-friendcell" : ""}"> | |
${user.star} | |
</div> | |
<div class = "Sniper-table_cell ${user.isfriend ? "Sniper-friendcell" : ""}"> | |
${isNaN(user.time_past) ? '' : time_past_to_string(user.time_past)} | |
</div> | |
<div class = "Sniper-table_cell ${user.isfriend ? "Sniper-friendcell" : ""}"> | |
${typeName} | |
</div> | |
</div> | |
`; | |
} | |
list_table.innerHTML = htmlstring; | |
// Automatch for 8 seconds, then cancel queue if no match | |
if (enable_match && pool.length > 0) { | |
let t = pool[0]; | |
if (t.time_past < 8000) { | |
console.log("join 1v1!"); | |
try { clickButton('play'); } catch (e) { } | |
try { clickButton('1v1'); } catch (e) { } | |
try { clickButton('play again'); } catch (e) { } | |
button1.innerHTML = "OFF"; | |
button1.style.backgroundColor = "#333333"; | |
enable_match = false; | |
// cancel in 8 seconds if the game hasn't started by then. | |
setTimeout(() => { | |
try { | |
clickButton('cancel'); | |
button1.innerHTML = "ON"; | |
button1.style.backgroundColor = "teal"; | |
enable_match = true; | |
} catch (e) {} | |
}, 8000); | |
} | |
} | |
} | |
if (!shouldRenderSniperModal()) { | |
main_div.hidden = true; | |
time_0 = undefined; | |
return; | |
} | |
main_div.hidden = false; | |
time_0 = Number(new Date()) + time_delta; | |
get_myname(); | |
function update_player(name, current_star) { | |
if (data[name] != undefined && abs(current_star - data[name].star) < 0.01) | |
return; | |
else { | |
if (logDebug) | |
console.log(`name = ${name} star = ${current_star}`, data[name]); | |
tasks+=100; | |
let task_id = Number(new Date())%100000; | |
// console.log(`+${task_id}, ${tasks}`); | |
let url = 'https://generals.io/api/replaysForUsername?u=' + encodeURIComponent(name) + '&offset=0&count=100'; | |
fetch(url).then(tmp => { | |
return tmp.json(); | |
}).then(tmp => { | |
if (!data.hasOwnProperty[name]) { | |
data[name] = {star: 0, time: NaN, type: NOREPLAY, timeOther: NaN}; | |
} | |
if (!!tmp && !!tmp.length) { | |
var dataObj = data[name]; | |
dataObj.star = current_star; | |
var isFirst = true; | |
for (var playerReplay of tmp) { | |
var replayTime = playerReplay.started + (playerReplay.turns - 1) * 500; | |
if (isFirst) { | |
dataObj.timeOther = replayTime; | |
dataObj.type = playerReplay.type; | |
} | |
if (playerReplay.type === '1v1') | |
{ | |
dataObj.time = replayTime; | |
break; | |
} | |
isFirst = false; | |
} | |
} else { | |
console.log("cant find any replays for user " + name); | |
} | |
tasks-=100; | |
// console.log(`-${task_id}, ${tasks}`); | |
}); | |
} | |
} | |
settings = [enable_match, enable_leaderboard, enable_friends, match_starbound.value]; | |
localStorage.setItem('zzdscript_settings',JSON.stringify(settings)); | |
bound = parseFloat(match_starbound.value); | |
if (isNaN(bound)) | |
bound = Infinity; | |
bound -= Eps; | |
tasks+=10000; | |
// console.log(`+${task_id}, ${tasks}`); | |
const now = Number(new Date()); | |
let gamesToRequest = 5; | |
// if its been longer than a second since we last updated | |
var timeSinceLast = now - lastUpdatedLadder; | |
if (logDebug) | |
console.log(`timeSinceLast ${timeSinceLast}`); | |
if (timeSinceLast > 1000) { | |
gamesToRequest = 20; | |
} | |
// if its been longer than 20 seconds since we last updated | |
if (timeSinceLast > 20 * 1000) { | |
gamesToRequest = 200; | |
} | |
lastUpdatedLadder = now; | |
let task_id = now%100000; | |
// console.log(`+${task_id}, ${tasks}`); | |
let url = `https://generals.io/api/replays?count=${gamesToRequest}&offset=0`; | |
if (logDebug) | |
console.log(`Making main recent games call to ${url}`); | |
var tmp = await fetch(url); | |
var deserialized = await tmp.json(); | |
var handled = new Set(); | |
for (let replay of deserialized) { | |
var timeFinished = replay.started + (replay.turns - 1) * 500; | |
for (let ranking of replay.ranking) { | |
var name = ranking.name; | |
if (handled.has(name)) | |
continue; | |
if (!data.hasOwnProperty(name)) { | |
data[name] = {star: 0, time: NaN, type: NOREPLAY, timeOther: NaN}; | |
} | |
const playerData = data[name]; | |
if (replay.type === '1v1') { | |
playerData.star = ranking.stars; | |
playerData.time = timeFinished; | |
handled.add(name); | |
players_from_leaderboard.add(name); | |
} | |
playerData.timeOther = timeFinished; | |
playerData.type = replay.type; | |
} | |
} | |
// if (enable_friends || !friend_list_loaded) { | |
if (!friend_list_loaded) { | |
friend_list_loaded = true; | |
// for (var i = 0; i < users.length; i++) | |
for (let name of friend_list) { | |
// skip players we've seen play 1v1 already | |
if (handled.has(name) || (data.hasOwnProperty(name) && !isNaN(data[name].time))) | |
continue; | |
tasks++; | |
let task_id = Number(new Date())%100000; | |
// console.log(`+${task_id}, ${tasks}`); | |
let url = 'https://generals.io/api/starsAndRanks?u=' + encodeURIComponent(name); | |
// Leave this non-async, I guess, so it is parallel. May cause bans still though? | |
fetch(url).then(tmp => { | |
return tmp.json(); | |
}).then(tmp => { | |
let star = parseFloat(tmp.stars.duel).toFixed(0); | |
if (isNaN(star)) | |
star = 0; | |
update_player(name, star); | |
tasks--; | |
// console.log(`-${task_id}, ${tasks}`); | |
}); | |
} | |
} | |
tasks-=10000; | |
}, 100); | |
}, 1000); | |
}; | |
let checkready = setInterval(() => { | |
if (document.readyState === "complete") { | |
main(); | |
clearInterval(checkready); | |
} | |
}, 250); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment