Skip to content

Instantly share code, notes, and snippets.

@PhrozenByte
Last active June 6, 2016 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PhrozenByte/9eb16e643369838cd30f to your computer and use it in GitHub Desktop.
Save PhrozenByte/9eb16e643369838cd30f to your computer and use it in GitHub Desktop.
Updates resources in OGame's retro universe using JavaScript
// ==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