Last active
June 6, 2016 14:03
-
-
Save PhrozenByte/9eb16e643369838cd30f to your computer and use it in GitHub Desktop.
Updates resources in OGame's retro universe using JavaScript
This file contains 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 OGame Retro Live Resources | |
// @namespace 960b5e6b7ff3c701d802352d15941d89 | |
// @description Updates resources in OGame's retro universe using JavaScript | |
// @author Daniel Rudolf <www.daniel-rudolf.de> | |
// @license GNU GPL version 3.0 <http://opensource.org/licenses/GPL-3.0> | |
// @include http://ogame1304.de/game/index.php?page=* | |
// @downloadURL https://gist.github.com/PhrozenByte/9eb16e643369838cd30f/raw/ogame-retro-live-resources.user.js | |
// @updateURL https://gist.github.com/PhrozenByte/9eb16e643369838cd30f/raw/ogame-retro-live-resources.user.js | |
// @version 6 | |
// @grant none | |
// ==/UserScript== | |
var scriptName = 'OGame Retro Live Resources'; | |
var scriptRevision = 6; | |
var scriptStorage = JSON.parse(localStorage.getItem('ogameRetroLiveResources') || '{}'); | |
function main() { | |
var requestTime = (new Date()).getTime(); | |
var currentPage = (window.location.search.match(/^\?page=(.+?)(?:&|$)/) || [])[1]; | |
if (document.querySelector('#header_top')) { | |
var planets = document.querySelector('#header_top select'); | |
if (!planets) throw new MalformedPageException('Planet dropdown not found'); | |
var coords = (planets.options[planets.selectedIndex].textContent.match(/ \[(\d+:\d+:\d+)\]$/) || [])[1]; | |
if (!coords) throw new MalformedPageException('Invalid coords'); | |
switch (currentPage) { | |
case 'resources': | |
// read & store resource production | |
var prodRow = document.querySelector('#content #ressourcen tr:nth-last-child(2)'); | |
if (!prodRow) throw new MalformedPageException('Resources total row not found'); | |
var metalProdNode = prodRow.querySelector('td:nth-of-type(1) > *'), | |
crystalProdNode = prodRow.querySelector('td:nth-of-type(2) > *'), | |
deuteriumProdNode = prodRow.querySelector('td:nth-of-type(3) > *'), | |
energyProdNode = prodRow.querySelector('td:nth-of-type(4) > *'); | |
if (!metalProdNode || !crystalProdNode || !deuteriumProdNode || !energyProdNode) { | |
throw new MalformedPageException('Resources total row malformed'); | |
} | |
log('Updating resource production...', coords); | |
updateProduction(coords, { | |
metal: parseNumber(metalProdNode.textContent) || 20, | |
crystal: parseNumber(crystalProdNode.textContent) || 10, | |
deuterium: parseNumber(deuteriumProdNode.textContent) || 0, | |
energy: parseNumber(energyProdNode.textContent) || 0, | |
_lastUpdate: requestTime | |
}); | |
break; | |
case 'b_building': | |
// a mine is under construction | |
// using OGame's pk and ss globals actually isn't necessary, but makes it much easier ;-) | |
if ((typeof pk !== 'undefined') && (pk < 4)) { | |
var observerCallback = function () { | |
if ((typeof ss !== 'undefined') && (ss < 0)) { | |
// the mine was completed, wait for the user to click on the "Finished" button | |
document.querySelector('#bxx a').addEventListener('click', function () { | |
log('Building finished; resetting resource production...', coords); | |
resetProduction(coords); | |
}); | |
} | |
}; | |
var observer = new MutationObserver(observerCallback); | |
observer.observe(document.getElementById('bxx'), { childList: true }); | |
observerCallback(); | |
} | |
break; | |
} | |
var resRow = document.querySelector('#header_top #resources tr:last-child'); | |
if (!resRow) throw new MalformedPageException('Current resources not found'); | |
var metalNode = resRow.querySelector('td:nth-of-type(1) > *'), | |
crystalNode = resRow.querySelector('td:nth-of-type(2) > *'), | |
deuteriumNode = resRow.querySelector('td:nth-of-type(3) > *'), | |
energyNode = resRow.querySelector('td:nth-of-type(4) > *'); | |
if (!metalNode || !crystalNode || !deuteriumNode || !energyNode) { | |
throw new MalformedPageException('Current resources row malformed'); | |
} | |
// check for a positive or at least constant energy level | |
// otherwise the mine production has changed | |
var currentEnergy = parseNumber(energyNode.textContent) || 0, | |
expectedEnergy = (scriptStorage[coords] || {}).energy || 0; | |
if ((currentEnergy != expectedEnergy) && ((currentEnergy < 0) || (expectedEnergy < 0))) { | |
log('Fluctuating energy level; resetting resource production...', coords); | |
resetProduction(coords); | |
} | |
if (scriptStorage[coords]) { | |
// update current resources | |
var startMetal = parseNumber(metalNode.textContent) || 0, | |
startCrystal = parseNumber(crystalNode.textContent) || 0, | |
startDeuterium = parseNumber(deuteriumNode.textContent) || 0; | |
var metalProd = (metalNode.color !== '#ff0000') ? scriptStorage[coords].metal / 3600 : 0, | |
crystalProd = (crystalNode.color !== '#ff0000') ? scriptStorage[coords].crystal / 3600 : 0, | |
deuteriumProd = (deuteriumNode.color !== '#ff0000') ? scriptStorage[coords].deuterium / 3600 : 0; | |
var prodString = (metalProd * 3600) + '/' + (crystalProd * 3600) + '/' + (deuteriumProd * 3600); | |
log('Current resource production: ' + prodString, coords); | |
window.setInterval(function () { | |
var now = (new Date()).getTime(), | |
interval = (now - requestTime) / 1000; | |
metalNode.textContent = formatNumber(startMetal + (metalProd * interval)); | |
crystalNode.textContent = formatNumber(startCrystal + (crystalProd * interval)); | |
deuteriumNode.textContent = formatNumber(startDeuterium + (deuteriumProd * interval)); | |
}, 1000); | |
} else { | |
log('Current resource production unknown', coords); | |
// unable to determine the current mine production | |
// notify the user by highlighting the resources menu item | |
var resLink = document.querySelector('#leftmenu #menu table a[accesskey="r"]'); | |
if (resLink !== null) resLink.style.color = 'orange'; | |
} | |
} | |
} | |
function updateProduction(coords, data) { | |
scriptStorage[coords] = data; | |
localStorage.setItem('ogameRetroLiveResources', JSON.stringify(scriptStorage)); | |
} | |
function resetProduction(coords) { | |
delete scriptStorage[coords]; | |
localStorage.setItem('ogameRetroLiveResources', JSON.stringify(scriptStorage)); | |
} | |
function formatNumber(number, decimals) { | |
number = parseFloat(number) || 0; | |
/* | |
if (number >= 1000000) { | |
number = (+number.toFixed(-3).slice(0, -3) / 1000); | |
number = (number + 'M').split('.'); | |
} else if (number >= 100000) { | |
number = [ number.toFixed(-3).slice(0, -3) + 'k' ]; | |
} else { | |
*/ | |
number = number.toFixed(decimals || 0).split('.'); | |
//} | |
number[0] = number[0].replace(/\B(?=(\d{3})+(?!\d))/g, '.'); | |
return number[0] + (number[1] ? ',' + number[1] : ''); | |
} | |
function parseNumber(string) { | |
if (typeof string !== 'number') { | |
string = (string || '').toString() | |
.replace(/\./g, '') | |
.replace(',', '.'); | |
var multiplier = 1; | |
switch (string.substr(-1)) { | |
case 'M': multiplier *= 1000; | |
case 'k': multiplier *= 1000; | |
string = string.slice(0, -1); | |
} | |
string = parseFloat(string) * multiplier; | |
} | |
return string; | |
} | |
function log(message, coords, level) { | |
var messagePrefix = scriptName + ' (rev ' + scriptRevision + '): '; | |
if (typeof coords === 'string') { | |
messagePrefix += '[' + coords + '] '; | |
} else if (level === undefined) { | |
level = coords; | |
} | |
if (!(level > 0) && !scriptStorage._debug) return; | |
var method = (level > 3) ? 'error' : (level > 2) ? 'warn' : (level > 1) ? 'info' : (level > 0) ? 'log' : 'info'; | |
console[method](messagePrefix + message); | |
} | |
function MalformedPageException(message) { this.message = message; } | |
MalformedPageException.prototype = Object.create(Error.prototype); | |
MalformedPageException.prototype.name = "MalformedPageException"; | |
MalformedPageException.prototype.constructor = MalformedPageException; | |
try { | |
var scriptStorageExists = (Object.keys(scriptStorage).length > 0); | |
if (!scriptStorageExists || (!scriptStorage._revision || (scriptStorage._revision < scriptRevision))) { | |
log(!scriptStorageExists ? 'Initializing...' : 'Script updated; resetting storage...', 2); | |
scriptStorage = { _revision: scriptRevision, _debug: !!scriptStorage._debug }; | |
localStorage.setItem('ogameRetroLiveResources', JSON.stringify(scriptStorage)); | |
} | |
main(); | |
} catch (e) { | |
log(e, 4); | |
throw e; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment