// ==UserScript==
// @name stonehub_updateUI_xyz
// @namespace http://tampermonkey.net/
// @version 1.1
// @description retrieve prices from idlescape.xyz and inject it in idlescape inventory
// @author godi, weld, gamergeo, flo
// @match https://idlescape.com/game*
// @run-at document-start
// @grant GM_xmlhttpRequest
// ==/UserScript==
class Stonehub_updateUI_xyz {
constructor() {
this.xyz_inventory_HTML = "";
this.xyz_market_HTML = "";
this.xyz_inventory_items = [];
this.xyz_market_items = [];
this.xyz_active_market_tag = "";
this.xyz_refresh_rate = 2000;
this.timer_hook = 0;
this.go_interval_retry = 2000;
this.go_nb_geode = 0;
}
error_handler(that, e) {
let alert_msg = "Something goes wrong with Stonehub_updateUI_xyz ! \nError msg: " + e.message + "\nPlease reload the page or contact messenoire / Gamergeo / Godi";
console.log(alert_msg);
//alert(alert_msg);
}
start() {
let that = this;
// launch xyz prices (xyz) daemon
setInterval(() => {
try {
that.xyz_main(that);
} catch(e) {that.error_handler(that, e);}
}, that.xyz_refresh_rate);
// launch geode_opener (go) daemon
this.timer_hook = setInterval(() => {
try {
that.go_hook(that);
} catch(e) {that.error_handler(that, e);}
}, that.go_interval_retry);
}
}
Stonehub_updateUI_xyz.prototype.int_to_commas = function(x) {
// src https://stackoverflow.com/questions/2901102/how-to-print-a-number-with-commas-as-thousands-separators-in-javascript
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
Stonehub_updateUI_xyz.prototype.xyz_main = function(that) {
// This function is called every "xyz_refresh_rate" seconds and refreshes price according to items displayed on screen
that.xyz_get_inventory_HTML(that);
that.xyz_get_market_HTML(that);
if(that.xyz_inventory_items.length > 0 || that.xyz_market_items.length > 0) that.xyz_get_prices(that);
that.xyz_show_gold_heat(that);
}
Stonehub_updateUI_xyz.prototype.xyz_get_inventory_HTML = function(that) {
that.xyz_inventory_HTML = "";
that.xyz_inventory_items = [];
if (! document.getElementsByClassName("inventory-panel")[0]) {return;} // Inventory isn't being displayed => Leave
that.xyz_inventory_HTML = document.getElementsByClassName("inventory-container-all-items")[0].children[0];
for (var i = 0; i < that.xyz_inventory_HTML.childElementCount; i++) {
let item_node = that.xyz_inventory_HTML.children[i];
if(item_node){
let node_value = item_node.attributes['data-for'].nodeValue;
let item_name = ""
if (node_value.includes("stockpile", 1)) {
item_name = node_value.substring(7,node_value.indexOf("stockpile"));
} else {
item_name = node_value.substring(7,node_value.indexOf("vault"));
}
that.xyz_inventory_items.push([item_name,]);
}
}
}
Stonehub_updateUI_xyz.prototype.xyz_get_market_HTML = function(that) {
that.xyz_market_HTML = "";
that.xyz_market_items = [];
that.xyz_active_market_tag = ""
if (! document.getElementsByClassName("marketplace-content")[0]) {return;} // Market isn't open => Leave
if (document.getElementsByClassName("marketplace-sell-items all-items")[0]) {
// market is open on "Sell" tab
that.xyz_active_market_tag = "marketplace-sell-items all-items";
} else {
// market is open on "Buy" tab
that.xyz_active_market_tag = "marketplace-content";
}
if (that.xyz_active_market_tag=="marketplace-sell-items all-items") {
// Since we're unable to read item names in sell tab, let's just copy the inventory list since it must be the same (tricky but should work), then leave
that.xyz_market_HTML = document.getElementsByClassName(that.xyz_active_market_tag)[0];
that.xyz_market_items = that.xyz_inventory_items;
return;
}
that.xyz_market_HTML = document.getElementsByClassName(that.xyz_active_market_tag)[0].children[0];
for (var i = 0; i < that.xyz_market_HTML.childElementCount; i++) {
let current_item_node = that.xyz_market_HTML.children[i].children[0].children[0];
if(current_item_node){
let item_name = current_item_node.attributes['alt'].nodeValue;
that.xyz_market_items.push([item_name,]);
}
}
}
Stonehub_updateUI_xyz.prototype.xyz_update_inventory_HTML = function(that) {
// Create HTML div into the item node so we can display the price onto it
for (var i = 0; i < that.xyz_inventory_items.length; i++) {
let item_node = that.xyz_inventory_HTML.children[i];
if(item_node){
if(item_node.getElementsByClassName("price").length==0){
// If the div was not created yet, create it with adapted CSS style and also move down the enchant icon
var newNode = document.createElement("div");
newNode.className = "price";
newNode.style.position = "absolute";
newNode.style.top = "-4px";
newNode.style.left = "1px";
newNode.style.color = "#54FF9F";
newNode.style.fontSize = "9px";
var lastNode = item_node.lastElementNode;
item_node.insertBefore(newNode, lastNode);
var enchantNode = item_node.getElementsByClassName("item-enchant").item(0);
enchantNode.style.position = "absolute";
enchantNode.style.top = "8px";
enchantNode.style.left = "0px";
}
// Populate the div with xyz API current price
let value = that.xyz_inventory_items[i][1];
item_node.getElementsByClassName("price").item(0).textContent = value ? that.int_to_commas(value) : 'no data...';
}
}
}
Stonehub_updateUI_xyz.prototype.xyz_update_market_HTML = function(that) {
// Create HTML div into the item node so we can display the price onto it
for (var i = 0; i < that.xyz_market_items.length; i++) {
let item_node = that.xyz_market_HTML.children[i].children[0];
if(item_node){
if(item_node.getElementsByClassName("price").length==0){
// If the div was not created yet, create it with adapted CSS style and also move down the enchant icon
var newNode = document.createElement("div");
newNode.className = "price";
newNode.style.position = "absolute";
newNode.style.top = "-4px";
newNode.style.left = "1px";
newNode.style.color = "#54FF9F";
newNode.style.fontSize = "9px";
var lastNode = item_node.lastElementNode;
item_node.insertBefore(newNode, lastNode);
if(that.xyz_active_market_tag == "marketplace-sell-items all-items"){
var enchantNode = item_node.getElementsByClassName("item-enchant").item(0);
enchantNode.style.position = "absolute";
enchantNode.style.top = "8px";
enchantNode.style.left = "0px";
}
}
// Populate the div with xyz API current price
let value = that.xyz_market_items[i][1];
item_node.getElementsByClassName("price").item(0).textContent = value ? that.int_to_commas(value) : 'no data...';
}
}
}
Stonehub_updateUI_xyz.prototype.xyz_get_prices = function(that) {
// xhr request to scrape idlescape.xyz prices in JSON format
// xhr request is asynchronous as for now (synchronous = true not working, neither callback apparently), and so HTML edits must happen inside the onload event for now
GM_xmlhttpRequest({
url: "https://api.idlescape.xyz/prices",
method: "GET",
onload: response => {
var xyz_data = JSON.parse(response.responseText)['items'];
// Get price for each item in inventory
for (var i = 0; i < that.xyz_inventory_items.length; i++) {
for (var j = 0; j < xyz_data.length; j++) {
if (xyz_data[j]['name'] == that.xyz_inventory_items[i][0]) {
that.xyz_inventory_items[i][1]=xyz_data[j]['price'];
break;
}
}
}
if(that.xyz_inventory_items.length > 0) that.xyz_update_inventory_HTML(that);
// Get price for each item in inventory
for (i = 0; i < that.xyz_market_items.length; i++) {
for (j = 0; j < xyz_data.length; j++) {
if (xyz_data[j]['name'] == that.xyz_market_items[i][0]) {
that.xyz_market_items[i][1]=xyz_data[j]['price'];
break;
}
}
}
if(that.xyz_market_items.length > 0) that.xyz_update_market_HTML(that);
}
});
}
Stonehub_updateUI_xyz.prototype.xyz_show_gold_heat = function(that) {
// Simply shows entirely gold and heat amounts
if (! document.getElementsByClassName("inventory-panel")[0]) {return;} // Inventory isn't being displayed => Leave
document.getElementById('gold').textContent = document.getElementById('gold-tooltip').children[1].textContent
document.getElementById('heat').textContent = document.getElementById('heat-tooltip').children[1].textContent
}
// **************************************************************************
// PARTIE GEODE - OPENER
// **************************************************************************
Stonehub_updateUI_xyz.prototype.go_hook = function(that) {
try {
var inventory_HTML = document.getElementsByClassName("inventory-container-all-items")[0].children[0];
} catch(e) { return;}
var geode_div = "";
for(var i = 0; i < inventory_HTML.childElementCount; i++) {
if (inventory_HTML.children[i].outerHTML.includes("Geode")) {geode_div = inventory_HTML.children[i]; break;}
}
if (geode_div) {
if(! geode_div.getElementsByClassName('geode_clicker')[0]){
var dummy_div = document.createElement('div');
dummy_div.className = "geode_clicker";
geode_div.appendChild(dummy_div);
geode_div.addEventListener("click", (e) => {that.go_geode_item_clicked(that,e);}, false);
}
}
}
Stonehub_updateUI_xyz.prototype.go_geode_item_clicked = function(that) {
var UI_Geode_hook = setInterval(() => {
try{
var menu_open = document.getElementsByClassName("MuiDialogActions-root item-dialogue-button-div MuiDialogActions-spacing")[0];
var new_button = document.createElement('div');
new_button.innerHTML = `<div variant="contained" color="secondary" class="item-dialogue-button idlescape-button idlescape-button-green">OUVRE MOI ÇA FDP ! <img src="https://raw.githubusercontent.com/geode-booster/geode-booster.github.io/master/211148-full.png" alt="Geode" class="icon40"></div>`;
menu_open.insertBefore(new_button, menu_open.children[1]);
menu_open.children[1].children[0].addEventListener("click", (e) => {that.go_run(that,e);}, false);
clearInterval(UI_Geode_hook);
} catch(e) { return; }
}, 100);
}
Stonehub_updateUI_xyz.prototype.go_run = function(that) {
that.go_nb_geode = parseInt(document.getElementsByClassName("MuiInputBase-input MuiInput-input MuiInputBase-inputMarginDense MuiInput-inputMarginDense")[0].value,10);
var Bouton_open = document.getElementsByClassName("MuiDialogActions-root item-dialogue-button-div MuiDialogActions-spacing")[0].children[0].children[0];
Bouton_open.click();
document.getElementsByClassName('chat-tabs')[0].children[1].click();
// Retrieve all items in geode
var Activity_Geode_hook = setInterval(() => {
try{
var messages = document.getElementsByClassName("activity-log");
var geode = ""
if(messages[messages.length-1].textContent.includes("You cracked open") && ! messages[messages.length-1].attributes["opened"]) {
geode = messages[messages.length-1].textContent;
messages[messages.length-1].attributes["opened"]=true;
} else {
// no log yet in Activity tab, we need to wait 40 more ms for server to respond
return;
}
// Only for testing purpose
// geode = "You cracked open 4 geodes and found Copper Ore x 27, Iron Ore x 39, Gold Ore x 139, Mithril Ore x 22, Runite Ore x 21, Clay x 19, Stone x 43, Sand x 16, Silver x 75, Coal x 82, Sapphire x 2, Diamond x 1, as loot."
geode = geode.substring(geode.indexOf("found ")+6,geode.indexOf(((that.go_nb_geode>1) ? "," : "") + " as loot."));
geode = geode.split(", ");
for(var j = 0; j < geode.length; j++){
geode[j] = geode[j].split(" x ");
}
clearInterval(Activity_Geode_hook);
that.go_main_game(that, geode);
} catch(e) {console.log(e.message); return; }
}, 40);
}
Stonehub_updateUI_xyz.prototype.go_main_game = function(that, geode) {
var x = document.getElementById("root");
x.style.display = "none";
var audio = new Audio('https://raw.githubusercontent.com/geode-booster/geode-booster.github.io/master/eussou.mp3');
audio.volume = 0.05;
audio.play();
that.go_gl = [];
that.go_pl = [];
that.go_geode = new Image();
that.go_copper_ore = new Image();
that.go_tin_ore = new Image();
that.go_iron_ore = new Image();
that.go_gold_ore = new Image();
that.go_mithril_ore = new Image();
that.go_adamantite_ore = new Image();
that.go_runite_ore = new Image();
that.go_clay = new Image();
that.go_stone = new Image();
that.go_sand = new Image();
that.go_silver = new Image();
that.go_coal = new Image();
that.go_stygian_ore = new Image();
that.go_sapphire = new Image();
that.go_emerald = new Image();
that.go_ruby = new Image();
that.go_diamond = new Image();
that.go_black_opal = new Image();
that.go_air_talisman = new Image();
that.go_earth_talisman = new Image();
that.go_fire_talisman = new Image();
that.go_water_talisman = new Image();
that.go_blood_talisman = new Image();
that.go_death_talisman = new Image();
that.go_chaos_talisman = new Image();
that.go_nature_talisman = new Image();
that.go_mind_talisman = new Image();
that.go_cosmic_talisman = new Image();
that.go_geode.src = "/images/misc/geode.png";
that.go_copper_ore.src = "/images/mining/copper_ore.png";
that.go_tin_ore.src = "/images/mining/tin_ore.png";
that.go_iron_ore.src = "/images/mining/tin_ore.png";
that.go_gold_ore.src = "/images/mining/tin_ore.png";
that.go_mithril_ore.src = "/images/mining/tin_ore.png";
that.go_adamantite_ore.src = "/images/mining/tin_ore.png";
that.go_runite_ore.src = "/images/mining/runite_ore.png";
that.go_clay.src = "/images/mining/clay.png";
that.go_stone.src = "/images/mining/stone.png";
that.go_sand.src = "/images/mining/sand.png";
that.go_silver.src = "/images/mining/silver.png";
that.go_coal.src = "/images/mining/coal.png";
that.go_stygian_ore.src = "/images/mining/stygian_ore.png";
that.go_sapphire.src = "/images/mining/sapphire.png";
that.go_emerald.src = "/images/mining/emerald.png";
that.go_ruby.src = "/images/mining/ruby.png";
that.go_diamond.src = "/images/mining/diamond.png";
that.go_black_opal.src = "/images/mining/black_opal.png";
that.go_air_talisman.src = "/images/runecrafting/air_talisman.png";
that.go_earth_talisman.src = "/images/runecrafting/earth_talisman.png";
that.go_fire_talisman.src = "/images/runecrafting/fire_talisman.png";
that.go_water_talisman.src = "/images/runecrafting/water_talisman.png";
that.go_blood_talisman.src = "/images/runecrafting/blood_talisman.png";
that.go_death_talisman.src = "/images/runecrafting/death_talisman.png";
that.go_chaos_talisman.src = "/images/runecrafting/chaos_talisman.png";
that.go_nature_talisman.src = "/images/runecrafting/nature_talisman.png";
that.go_mind_talisman.src = "/images/runecrafting/mind_talisman.png";
that.go_cosmic_talisman.src = "/images/runecrafting/cosmic_talisman.png";
var imgs = {};
imgs["Geode"] = that.go_geode;
imgs["Copper Ore"] = that.go_copper_ore;
imgs["Tin Ore"] = that.go_tin_ore;
imgs["Iron Ore"] = that.go_iron_ore;
imgs["Gold Ore"] = that.go_gold_ore;
imgs["Mithril Ore"] = that.go_mithril_ore;
imgs["Adamantite Ore"] = that.go_adamantite_ore;
imgs["Runite Ore"] = that.go_runite_ore;
imgs["Clay"] = that.go_clay;
imgs["Stone"] = that.go_stone;
imgs["Sand"] = that.go_sand;
imgs["Silver"] = that.go_silver;
imgs["Coal"] = that.go_coal;
imgs["Stygian Ore"] = that.go_stygian_ore;
imgs["Sapphire"] = that.go_sapphire;
imgs["Emerald"] = that.go_emerald;
imgs["Ruby"] = that.go_ruby;
imgs["Diamond"] = that.go_diamond;
imgs["Black Opal"] = that.go_black_opal;
imgs["Air Talisman"] = that.go_air_talisman;
imgs["Earth Talisman"] = that.go_earth_talisman;
imgs["Fire Talisman"] = that.go_fire_talisman;
imgs["Water Talisman"] = that.go_water_talisman;
imgs["Blood Talisman"] = that.go_blood_talisman;
imgs["Death Talisman"] = that.go_death_talisman;
imgs["Chaos Talisman"] = that.go_chaos_talisman;
imgs["Nature Talisman"] = that.go_nature_talisman;
imgs["Mind Talisman"] = that.go_mind_talisman;
imgs["Cosmic Talisman"] = that.go_cosmic_talisman;
document.getElementsByTagName("body")[0].style.cursor = "url('https://raw.githubusercontent.com/geode-booster/geode-booster.github.io/master/pick0.png') 5 65, auto";
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.style.position = "absolute";
canvas.style.top = "0px";
canvas.style.left = "0px";
document.body.appendChild(canvas);
var w = canvas.width = innerWidth;
var h = canvas.height = innerHeight;
// Shuffle what we can find in each geode
var probability = geode.map((v, i) => Array(parseInt(v[1],10)).fill(i)).reduce((c, v) => c.concat(v), []);
shuffle(probability);
var total_part = probability.length;
for(let i = 0; i < that.go_nb_geode; i++) {
that.go_gl.push({
x : canvas.width/2, y : canvas.height/2,
xr : rand(canvas.width), yr : rand(canvas.height),
r : rand(0,1), // mélangeons les goudjas
scale : rand(0.9,1.2), // chanclons la bougnadère
dx : rand(-3,3), dy : rand(-3,3),
dr : rand(-0.4,0.4),
})
}
canvas.addEventListener('click', function(event) {
var pas = that.go_gl.length-1;
while(pas >= 0) {
var spr = that.go_gl[pas];
if(event.offsetX > spr.xr-(that.go_geode.width/2*spr.scale) && event.offsetX < spr.xr+(that.go_geode.width/2*spr.scale) && event.offsetY > spr.yr-(that.go_geode.height/2*spr.scale) && event.offsetY < spr.yr+(that.go_geode.height/2*spr.scale)){
let nb_part = (that.go_gl.length > 1) ? Math.ceil(total_part / that.go_nb_geode) : probability.length;
for(let i = 0; i < nb_part; i++) {
that.go_pl.push({
name: geode[probability[i]][0],
img : imgs[geode[probability[i]][0]],
x : event.offsetX+(imgs[geode[probability[i]][0]].width/2*spr.scale), y : event.offsetY+(imgs[geode[probability[i]][0]].height/2*spr.scale),
xr : 0, yr : 0,
r : rand(0,1), // mélangeons les goudjas
scale : rand(0.2,0.5), // chanclons la bougnadère
dx : rand(-2,2), dy : rand(-2,2),
dr : rand(-0.2,0.2),
tick : Math.floor(rand(900, 1400))
})
}
probability = probability.splice(nb_part);
that.go_gl.splice(pas, 1);
break;
}
pas--
}
});
// src "accepted answer" https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
function shuffle(array) {
var currentIndex = array.length, temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
function rand(min,max){
return Math.random() * (max ?(max-min) : min) + (max ? min : 0)
}
function drawImage(image, spr){
// ctx.setTransform(spr.scale, 0, 0, spr.scale, spr.xr, spr.yr); // yatangaki par là
ctx.setTransform(spr.scale, 0, 0, spr.scale, spr.xr, spr.yr); // yatangaki par là
ctx.rotate(spr.r/10);
ctx.drawImage(image, -image.width / 2, -image.height / 2);
}
function update(){
var ihM,iwM;
ctx.setTransform(1,0,0,1,0,0);
ctx.clearRect(0,0,w,h);
ctx.fillStyle = 'rgba(0,0,0,0.75)';
ctx.fillRect(0,0,window.innerWidth,window.innerHeight);
var iw = imgs['Geode'].width;
var ih = imgs['Geode'].height;
for(i = 0; i < that.go_pl.length; i ++){
spr = that.go_pl[i];
spr.x += spr.dx;
spr.y += spr.dy;
spr.r += spr.dr;
spr.tick -= 1;
iwM = iw * spr.scale * 2 + w;
ihM = ih * spr.scale * 2 + h;
spr.xr = ((spr.x % iwM) + iwM) % iwM - iw * spr.scale;
spr.yr = ((spr.y % ihM) + ihM) % ihM - ih * spr.scale;
drawImage(spr.img,spr);
}
for(var i = 0; i < that.go_gl.length; i ++){
var spr = that.go_gl[i];
spr.x += spr.dx;
spr.y += spr.dy;
spr.r += spr.dr;
iwM = iw * spr.scale * 2 + w;
ihM = ih * spr.scale * 2 + h;
spr.xr = ((spr.x % iwM) + iwM) % iwM - iw * spr.scale;
spr.yr = ((spr.y % ihM) + ihM) % ihM - ih * spr.scale;
drawImage(imgs['Geode'],spr);
}
var pas = 0
while(pas < that.go_pl.length ) {
if(that.go_pl[pas].tick == 0){
that.go_pl.splice(pas,1);
} else {
pas += 1;
}
}
if(that.go_pl.length==0 && that.go_gl.length==0){
audio.pause();
document.body.removeChild(canvas)
document.getElementsByTagName("body")[0].style.cursor = "auto";
x.style.display = "block";
return;
}
requestAnimationFrame(update);
}
requestAnimationFrame(update);
}
let s = new Stonehub_updateUI_xyz(); s.start()