// ==UserScript==
// @name florr.io | Playtime counter
// @version 1.1.4
// @description Shows how no life you are
// @author Furaken
// @match https://florr.io/*
// @grant unsafeWindow
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js
// @namespace https://github.com/Samer-Kizi
// ==/UserScript==
var totalServers = 17 - 1
var today = new Date().toString().substring(0,15)
var leech = [{"date":today,"value":0,map:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}],
cvs = document.querySelector('canvas')
var newDoc = document.createElement('div')
newDoc.style = `
right: 6px;
bottom: -3px;
color: white;
text-shadow: rgb(0, 0, 0) 2px 0px 0px, rgb(0, 0, 0) 1.75517px 0.958851px 0px, rgb(0, 0, 0) 1.0806px 1.68294px 0px, rgb(0, 0, 0) 0.141474px 1.99499px 0px, rgb(0, 0, 0) -0.832294px 1.81859px 0px, rgb(0, 0, 0) -1.60229px 1.19694px 0px, rgb(0, 0, 0) -1.97998px 0.28224px 0px, rgb(0, 0, 0) -1.87291px -0.701566px 0px, rgb(0, 0, 0) -1.30729px -1.5136px 0px, rgb(0, 0, 0) -0.421592px -1.95506px 0px, rgb(0, 0, 0) 0.567324px -1.91785px 0px, rgb(0, 0, 0) 1.41734px -1.41108px 0px, rgb(0, 0, 0) 1.92034px -0.558831px 0px;
position: absolute;
z-index: 1;
font-family: Ubuntu;
line-height: 0px;
text-align: right;
pointer-events: none;
`
document.querySelector('body').appendChild(newDoc)
if (localStorage.getItem("florrTime") === null) localStorage.setItem('florrTime', JSON.stringify(leech))
if (JSON.parse(localStorage.getItem("florrTime"))[0].date != today) {
let x = JSON.parse(localStorage.getItem('florrTime'))
x.unshift({"date":today,"value":0,map:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]})
localStorage.setItem('florrTime', JSON.stringify(x));
}
if (JSON.parse(localStorage.getItem("florrTime"))[0].map == undefined) {
let x = JSON.parse(localStorage.getItem('florrTime'))
x[0].map = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
localStorage.setItem('florrTime', JSON.stringify(x));
}
var url
const nativeWebSocket = unsafeWindow.WebSocket;
unsafeWindow.WebSocket = function(...args){
const socket = new nativeWebSocket(...args);
url = socket.url
return socket;
};
var start = Date.now() - Number(JSON.parse(localStorage.getItem("florrTime"))[0].value) * 1000,
time,
allTime = 0,
allTimeA,
stop = false,
servers = [],
indexV,
start2,
urlA = [],
delta2
function Time(seconds) {
var hoursLeft = Math.floor(seconds / 3600);
var min = Math.floor((seconds - hoursLeft * 3600) / 60);
var secondsLeft = seconds - hoursLeft * 3600 - min * 60;
secondsLeft = Math.round(secondsLeft * 100) / 100;
var answer = hoursLeft< 10 ? "0" + hoursLeft : hoursLeft;
answer += ":" + (min < 10 ? "0" + min : min);
answer += ":" + (secondsLeft< 10 ? "0" + secondsLeft : secondsLeft);
return answer
}
for (let i = 0; i <= totalServers; i++) {
fetch("https://api.n.m28.io/endpoint/florrio-map-" + i + "-green/findEach/").then((response) => response.json()).then((data) => {
servers[i] = `${data.servers["vultr-miami"].id} ${data.servers["vultr-frankfurt"].id} ${data.servers["vultr-tokyo"].id}`
})
}
setInterval(function() {
if (stop) {
start = Date.now()
stop = false
} else {
var delta = Date.now() - start,
start2 = JSON.parse(localStorage.getItem('florrTime'))[0].value
let x = JSON.parse(localStorage.getItem('florrTime'))
x[0].value = Math.floor(delta / 1000)
time = Time(Math.floor(Number(x[0].value)))
x.forEach(k => {allTime += Number(k.value)})
allTimeA = Time(Math.floor(Number(allTime)))
localStorage.setItem('florrTime', JSON.stringify(x));
newDoc.innerHTML = `<p style="font-size:12px">Since ${JSON.parse(localStorage.getItem('florrTime')).at(-1).date}: ${allTimeA}</p><p style="font-size:20px">${time}</p>`
allTime = 0
delta2 = JSON.parse(localStorage.getItem('florrTime'))[0].value - start2
var xyz = JSON.parse(localStorage.getItem("florrTime"))
xyz[0].map[indexV] += delta2
localStorage.setItem('florrTime', JSON.stringify(xyz));
urlA.unshift(url)
if (urlA.length > 2) urlA.splice(2)
if (urlA.at(-1) != urlA[0]) {
start2 = JSON.parse(localStorage.getItem('florrTime'))[0].value
servers.forEach(function callback(x, index) {
if (x.includes(url.slice(6, 9))) indexV = index
});
}
}
}, 1000)
var chartCon = document.createElement('div')
chartCon.style = `
width: 100%;
height: 100%;
position: absolute;
z-index: 100;
font-family: Ubuntu;
top: 0;
margin: 0;
opacity: 0;
pointer-events: none;
transition: 0.4s ease-in-out;
`
chartCon.innerHTML = `
<canvas id="chartCtx" style="background: rgba(255, 255, 255, 0.9);padding: 50px;font-family: Ubuntu;transition: 0.4s ease-in-out;position: absolute;z-index: 1;"></canvas>
<canvas id="chartCtx2" style="background: rgba(255, 255, 255, 0.9);padding: 50px;font-family: Ubuntu;;transition: 0.4s ease-in-out;position: absolute;"></canvas>
`
document.querySelector('body').appendChild(chartCon)
Chart.defaults.font.family = 'Ubuntu';
Chart.defaults.font.size = 16;
var chart = new Chart(document.getElementById('chartCtx'), {
type: 'line',
data: {
labels: null,
datasets: null
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
title: {
text: 'Playtime (Month)',
display: true
}
},
scales: {
x: {
title: {
display: true,
text: 'Date'
}
},
y: {
title: {
display: true,
text: 'Hours'
}
}
},
},
});
var chart2 = new Chart(document.getElementById('chartCtx2'), {
type: 'doughnut',
data: {
labels: null,
datasets: null
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
title: {
text: 'Playtime (Hours)',
display: true
}
},
},
});
function updateData() {
var data = [],
labels = [],
labels2 = [],
mapData = [],
allMap = [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]],
localStr = JSON.parse(localStorage.getItem("florrTime")),
len = 30,
pieMapData = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
colorRandomPie = []
function be(date) {
return date.slice(8, 10) + "/" + (new Date(Date.parse(date.slice(4, 7) + " 1, 2012")).getMonth() + 1) + "/" + date.slice(-4)
}
for (let i = 0; i <= totalServers; i++) {
labels2.push('MAP'+i)
}
if (localStr.length < 30) len = localStr.length
for (let i = 0; i < len; i++) {
data.unshift(localStr[i].value / 3600)
labels.unshift(be(localStr[i].date))
mapData.unshift(localStr[i].map)
}
mapData.forEach(x => {
for (let i = 0; i <= totalServers; i++) {
if (x == undefined) x = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
allMap[i].push(x[i] / 3600)
pieMapData[i] += (x[i] / 3600)
}
})
var colorPalette = [
"#067A69",
"#09BB9F",
"#39F3BB",
"#18A1CD",
"#1D81A2",
"#15607A",
"#003f5c",
"#2f4b7c",
"#665191",
"#a05195",
"#d45087",
"#f95d6a",
"#ff7c43",
"#ffa600",
"#DE6D12",
"#C27A24",
"#A68736"
]
var chartObj = [{ label: 'All', data: data, fill: true, borderColor: 1, borderWidth: 4, tension: 0.3 }],
color
for (let i = 0; i <= totalServers; i++) {
chartObj.push({ "label": "MAP" + i, "data": allMap[i], "fill": true, "backgroundColor": colorPalette[i] + "1A", "borderColor": colorPalette[i], "borderWidth": 2.5, "tension": 0.3 })
localStr[0].map[i] = localStr[0].map[i] / 3600
}
chart.data.datasets = chartObj
chart.data.labels = labels
chart.update()
chart2.data.labels = labels2
chart2.data.datasets = [
{
label: 'Latest 30 Days',
data: pieMapData,
backgroundColor: colorPalette,
hoverOffset: 10
},
{
label: 'Today',
data: localStr[0].map,
backgroundColor: colorPalette,
hoverOffset: 10
}
]
chart2.update()
}
document.documentElement.addEventListener("keydown", function() {
if (event.keyCode === 191 && event.ctrlKey && event.shiftKey) {
if (confirm("Confirm reset all")) {
stop = true;
localStorage.setItem('florrTime', JSON.stringify(leech))
}
}
else if (event.keyCode === 186) newDoc.style.display = newDoc.style.display === 'none' ? '' : 'none'
else if (event.keyCode === 220) {
if (chartCon.style.opacity == '0') {
chartCon.style.opacity = '1'
chartCon.style.pointerEvents = 'all'
updateData()
} else {
chartCon.style.opacity = '0'
chartCon.style.pointerEvents = 'none'
}
}
else if (event.keyCode === 221) {
var x = document.getElementById('chartCtx')
x.style.zIndex = x.style.zIndex === '1' ? '-1' : '1'
}
});