Improve Diamond Hunt 2
目前為
// ==UserScript==
// @name DH2 Fixed
// @namespace FileFace
// @description Improve Diamond Hunt 2
// @version 0.4.0
// @author Zorbing
// @grant none
// @run-at document-start
// @include http://www.diamondhunt.co/game.php
// ==/UserScript==
(function ()
{
'use strict';
let styleElement = null;
function addStyle(styleCode)
{
if (styleElement === null)
{
styleElement = document.createElement('style');
document.head.appendChild(styleElement);
}
styleElement.innerHTML += styleCode;
}
/**
* observer
*/
let observedKeys = new Map();
/**
* Observes the given key for change
*
* @param {string} key The name of the variable
* @param {Function} fn The function which is called on change
*/
function observe(key, fn)
{
if (key instanceof Array)
{
for (let k of key)
{
observe(k, fn);
}
}
else
{
if (!observedKeys.has(key))
{
observedKeys.set(key, new Set());
}
observedKeys.get(key).add(fn);
}
return fn;
}
function unobserve(key, fn)
{
if (key instanceof Array)
{
let ret = [];
for (let k of key)
{
ret.push(unobserve(k, fn));
}
return ret;
}
if (!observedKeys.has(key))
{
return false;
}
return observedKeys.get(key).delete(fn);
}
function updateValue(key, newValue)
{
const oldValue = window[key];
window[key] = newValue;
if (oldValue !== newValue)
{
(observedKeys.get(key) || []).forEach(fn => fn(key, oldValue, newValue));
}
}
const furnaceLevels = ['stone', 'bronze', 'iron', 'silver', 'gold'];
const oilStorageLevelNum = 7;
function hideFurnaceRecipes(init)
{
const keys2Observe = [];
let maxFurnaceLevel = 0;
for (let i = furnaceLevels.length-1; i >= 0; i--)
{
const level = i+1;
const varName = furnaceLevels[i] + 'Furnace';
const boundVarName = 'bound' + varName[0].toUpperCase() + varName.substr(1);
keys2Observe.push(varName);
keys2Observe.push(boundVarName);
if (window[varName] > 0 || window[boundVarName])
{
maxFurnaceLevel = Math.max(maxFurnaceLevel, level);
}
const hide = level <= maxFurnaceLevel;
const recipeRow = document.getElementById('crafting-' + varName);
if (recipeRow)
{
recipeRow.style.display = hide ? 'none' : '';
}
}
if (init)
{
observe(keys2Observe, () => hideFurnaceRecipes(false));
}
}
function hideOilStorageRecipes(init)
{
const keys2Observe = [];
let maxOilStorageLevel = 0;
for (let i = oilStorageLevelNum-1; i >= 0; i--)
{
const level = i+1;
const varName = 'oilStorage' + level;
const boundVarName = 'boundOilStorage' + level;
keys2Observe.push(varName);
keys2Observe.push(boundVarName);
if (window[varName] > 0 || window[boundVarName])
{
maxOilStorageLevel = Math.max(maxOilStorageLevel, level);
}
const hide = level <= maxOilStorageLevel;
const recipeRow = document.getElementById('crafting-' + varName);
if (recipeRow)
{
recipeRow.style.display = hide ? 'none' : '';
}
}
if (init)
{
observe(keys2Observe, () => hideOilStorageRecipes(false));
}
}
function hideCraftedRecipes()
{
hideFurnaceRecipes(true);
hideOilStorageRecipes(true);
const oldProcessCraftingTab = window.processCraftingTab;
window.processCraftingTab = () =>
{
const reinit = !!window.refreshLoadCraftingTable;
oldProcessCraftingTab();
if (reinit)
{
hideFurnaceRecipes(false);
hideOilStorageRecipes(false);
}
};
}
/**
* fix wood cutting
*/
function fixWoodcutting()
{
addStyle(`
img.woodcutting-tree-img
{
border: 1px solid transparent;
}
`);
}
/**
* init
*/
function init()
{
hideCraftedRecipes();
fixWoodcutting();
}
document.addEventListener('DOMContentLoaded', () =>
{
const oldDoCommand = window.doCommand;
window.doCommand = (data) =>
{
if (data.startsWith('REFRESH_ITEMS='))
{
const itemDataValues = data.split('=')[1].split(';');
const itemArray = [];
for (var i = 0; i < itemDataValues.length; i++)
{
const [key, newValue] = itemDataValues[i].split('~');
itemArray.push(key);
updateValue(key, newValue);
}
window.refreshItemValues(itemArray, false);
if (window.firstLoadGame)
{
window.loadInitial();
window.firstLoadGame = false;
init();
}
else
{
window.clientGameLoop();
}
return;
}
return oldDoCommand(data);
};
});
/**
* fix web socket errors
*/
function webSocketLoaded(event)
{
if (window.webSocket == null)
{
console.error('no webSocket instance found!');
return;
}
const messageQueue = [];
const oldOnMessage = webSocket.onmessage;
webSocket.onmessage = (event) => messageQueue.push(event);
document.addEventListener('DOMContentLoaded', () =>
{
messageQueue.forEach(event => onMessage(event));
webSocket.onmessage = oldOnMessage;
});
const commandQueue = [];
const oldSendBytes = window.sendBytes;
window.sendBytes = (command) => commandQueue.push(command);
const oldOnOpen = webSocket.onopen;
webSocket.onopen = (event) =>
{
window.sendBytes = oldSendBytes;
commandQueue.forEach(command => window.sendBytes(command));
return oldOnOpen(event);
};
}
function isWebSocketScript(script)
{
return script.src.includes('socket.js');
}
function fixWebSocketScript()
{
if (!document.head)
{
return;
}
const scripts = document.head.querySelectorAll('script');
let found = false;
for (let i = 0; i < scripts.length; i++)
{
if (isWebSocketScript(scripts[i]))
{
// does this work?
scripts[i].onload = webSocketLoaded;
return;
}
}
// create an observer instance
const mutationObserver = new MutationObserver((mutationList) =>
{
mutationList.forEach((mutation) =>
{
if (mutation.addedNodes.length === 0)
{
return;
}
for (let i = 0; i < mutation.addedNodes.length; i++)
{
const node = mutation.addedNodes[i];
if (node.tagName == 'SCRIPT' && isWebSocketScript(node))
{
mutationObserver.disconnect();
node.onload = webSocketLoaded;
return;
}
}
});
});
mutationObserver.observe(document.head, {
childList: true
});
}
fixWebSocketScript();
})();