Press CTRL + I to activate. Create cool glow or 3D effects using this tool. Fixed for modern diep.io
// ==UserScript==
// @name DiepShadow (Fixed)
// @namespace *://diep.io/*
// @version 1.4
// @description Press CTRL + I to activate. Create cool glow or 3D effects using this tool. Fixed for modern diep.io
// @author Binary (maintained and fixed by razor)
// @match *://diep.io/*
// @match *://localhost:8080/*
// @run-at document-start
// @grant none
// ==/UserScript==
(function() {
'use strict';
var hotkey_activate_sequence = function(event) { // CTRL + I
if (event.ctrlKey && !event.altKey && !event.shiftKey && event.code === 'KeyI' && !event.repeat) {
event.preventDefault();
return true;
}
};
var localStorage_key = 'diepshadow_preferences';
var version = '1.4';
var presets = [{
name: 'funny 1',
description: 'yeah',
shadowBlur: 0,
shadowOffsetX: 8,
shadowOffsetY: 8,
shadowStrength: 1,
shadowColor: 'rgb(35,14,53)'
},{
name: 'funny 2',
description: 'yeah',
shadowBlur: 0,
shadowOffsetX: 8,
shadowOffsetY: 8,
shadowStrength: 1,
shadowColor: 'rgb(24,1,55)'
}];
var storageSettings;
try{
storageSettings = JSON.parse(window.localStorage.getItem(localStorage_key));
}catch(e){storageSettings = {}}
if(!(storageSettings instanceof Object)) storageSettings = {};
var booleanOrDefault = function(key, defaultValue){
if(typeof storageSettings[key] === 'boolean') return storageSettings[key];
return defaultValue;
};
var numberOrDefault = function(key, defaultValue){
if(typeof storageSettings[key] === 'number' && !isNaN(storageSettings[key])) return storageSettings[key];
return defaultValue;
};
var settings = {
enableShadow: booleanOrDefault('enableShadow', true),
enableSaving: booleanOrDefault('enableSaving', true),
shadowBlur: numberOrDefault('shadowBlur', 0),
shadowOffsetX: numberOrDefault('shadowOffsetX', 8),
shadowOffsetY: numberOrDefault('shadowOffsetY', 8),
shadowStrength: numberOrDefault('shadowStrength', 1),
shadowColor: typeof storageSettings.shadowColor === 'string' ? storageSettings.shadowColor : 'rgb(24,1,55)'
};
// ==== INTERCEPT CANVAS CONTEXT BEFORE PAGE LOADS ====
var OriginalGetContext = HTMLCanvasElement.prototype.getContext;
var OriginalFill = CanvasRenderingContext2D.prototype.fill;
var OriginalStroke = CanvasRenderingContext2D.prototype.stroke;
var OriginalFillRect = CanvasRenderingContext2D.prototype.fillRect;
var OriginalFillText = CanvasRenderingContext2D.prototype.fillText;
var trackedContexts = new WeakMap();
function getShadowSettings() {
if (!settings.enableShadow) {
return {
shadowBlur: 0,
shadowColor: 'rgba(0,0,0,0)',
shadowOffsetX: 0,
shadowOffsetY: 0
};
}
return {
shadowBlur: settings.shadowBlur,
shadowColor: settings.shadowColor
.replace('rgb(', 'rgba(')
.replace(')', ',' + settings.shadowStrength + ')'),
shadowOffsetX: settings.shadowOffsetX,
shadowOffsetY: settings.shadowOffsetY
};
}
function applyShadow(ctx) {
var shadow = getShadowSettings();
ctx.shadowBlur = shadow.shadowBlur;
ctx.shadowColor = shadow.shadowColor;
ctx.shadowOffsetX = shadow.shadowOffsetX;
ctx.shadowOffsetY = shadow.shadowOffsetY;
}
function removeShadow(ctx) {
ctx.shadowBlur = 0;
ctx.shadowColor = 'rgba(0,0,0,0)';
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
}
// Intercept getContext
HTMLCanvasElement.prototype.getContext = function() {
var ctx = OriginalGetContext.apply(this, arguments);
if (ctx && arguments[0] === '2d' && !trackedContexts.has(ctx)) {
trackedContexts.set(ctx, true);
console.log('DiepShadow: New 2D context detected');
}
return ctx;
};
// Only apply shadow to fill operations (not strokes)
CanvasRenderingContext2D.prototype.fill = function() {
applyShadow(this);
var result = OriginalFill.apply(this, arguments);
removeShadow(this);
return result;
};
CanvasRenderingContext2D.prototype.fillRect = function() {
applyShadow(this);
var result = OriginalFillRect.apply(this, arguments);
removeShadow(this);
return result;
};
CanvasRenderingContext2D.prototype.fillText = function() {
applyShadow(this);
var result = OriginalFillText.apply(this, arguments);
removeShadow(this);
return result;
};
// Make sure stroke operations DON'T have shadow
CanvasRenderingContext2D.prototype.stroke = function() {
removeShadow(this);
return OriginalStroke.apply(this, arguments);
};
console.log('DiepShadow: Canvas hooks installed at document-start');
// ==== UI SETUP (runs when DOM is ready) ====
function initUI() {
var wrapper = document.createElement('div');
wrapper.style.position = 'fixed';
wrapper.style.backgroundColor = '#a3bfce';
wrapper.style.padding = '10px';
wrapper.style.top = '0px';
wrapper.style.right = '0px';
wrapper.style.bottom = '0px';
wrapper.style.overflowY = 'auto';
wrapper.style.overflowX = 'hidden';
wrapper.style.fontFamily = 'Ubuntu';
wrapper.style.display = 'none';
wrapper.style.zIndex = '999999';
wrapper.style.width = '460px';
var checkbox_inputs = {};
var addCheckboxInput = function(displayText, name) {
checkbox_inputs[name] = document.createElement('input');
var enableShadowLabel = document.createElement('label');
var enableShadowText = document.createTextNode(displayText);
checkbox_inputs[name].type = 'checkbox';
checkbox_inputs[name].checked = settings[name];
enableShadowLabel.style.display = 'block';
enableShadowLabel.style.width = 'fit-content';
enableShadowLabel.appendChild(checkbox_inputs[name]);
enableShadowLabel.appendChild(enableShadowText);
wrapper.appendChild(enableShadowLabel);
checkbox_inputs[name].addEventListener('change', function() {
settings[name] = checkbox_inputs[name].checked;
saveSettings(true);
console.log('DiepShadow: Setting changed -', name, '=', settings[name]);
});
};
var sliders = {};
var addSliderInput = function(displayText, name, min, max, step) {
var slider = document.createElement('input');
slider.type = 'range';
slider.style.verticalAlign = 'middle';
slider.style.width = '250px';
slider.style.transform = 'none';
slider.min = min;
slider.max = max;
slider.step = step;
var label = document.createElement('label');
var displayTextSpan = document.createElement('span');
var displayValueSpan = document.createElement('span');
label.style.display = 'block';
label.style.width = 'fit-content';
displayTextSpan.style.width = '140px';
displayTextSpan.style.display = 'inline-block';
displayTextSpan.textContent = displayText;
displayValueSpan.style.width = '30px';
displayValueSpan.style.display = 'inline-block';
displayValueSpan.style.textAlign = 'center';
label.appendChild(displayTextSpan);
label.appendChild(displayValueSpan);
label.appendChild(slider);
wrapper.appendChild(label);
sliders[name] = {
addonchange: function(callback) {
var listener = function() {
displayValueSpan.textContent = slider.value;
callback(parseFloat(slider.value));
};
slider.addEventListener('change', listener);
slider.addEventListener('input', listener);
},
setValue: function(newValue) {
slider.value = newValue;
displayValueSpan.textContent = newValue;
slider.dispatchEvent(new window.Event('input', { bubbles: true }));
}
};
sliders[name].setValue(settings[name]);
sliders[name].addonchange(function(newValue) {
settings[name] = newValue;
saveSettings();
console.log('DiepShadow: Setting changed -', name, '=', newValue);
});
};
var colors = {};
var addColorInput = function(displayText, name) {
var colorInput = document.createElement('input');
colorInput.type = 'color';
colorInput.style.verticalAlign = 'middle';
var label = document.createElement('label');
var displayTextSpan = document.createElement('span');
label.style.display = 'block';
label.style.width = 'fit-content';
displayTextSpan.style.width = '170px';
displayTextSpan.style.display = 'inline-block';
displayTextSpan.textContent = displayText;
label.appendChild(displayTextSpan);
label.appendChild(colorInput);
wrapper.appendChild(label);
colors[name] = {
addonchange: function(callback) {
var listener = function() {
callback(hexToRgb(colorInput.value));
};
colorInput.addEventListener('change', listener);
colorInput.addEventListener('input', listener);
},
setValue: function(newValue) {
colorInput.value = newValue;
colorInput.dispatchEvent(new window.Event('input', { bubbles: true }));
}
};
colors[name].setValue(rgbToHex(settings[name]));
colors[name].addonchange(function(newValue) {
settings[name] = newValue;
saveSettings();
console.log('DiepShadow: Color changed -', name, '=', newValue);
});
};
var addPreset = function(eachPreset){
var presetWrap = document.createElement('div');
var name = document.createElement('p');
var description = document.createElement('p');
var demo_lighttheme = document.createElement('p');
var demo_darktheme = document.createElement('p');
var btn = document.createElement('p');
presetWrap.style.marginTop = '20px';
presetWrap.style.borderTop = '2px solid black';
name.textContent = 'Preset name: ' + eachPreset.name;
name.style.width = '440px';
name.style.margin = '5px 0px';
description.textContent = 'Preset description: ' + eachPreset.description;
description.style.width = '440px';
description.style.margin = '5px 0px';
var applyThemeToDemo = function(element){
element.style.textShadow =
eachPreset.shadowOffsetX + 'px ' +
eachPreset.shadowOffsetY + 'px ' +
eachPreset.shadowBlur + 'px ' +
eachPreset.shadowColor.replace('rgb(', 'rgba(').replace(')', ',' + eachPreset.shadowStrength + ')');
element.style.padding = '0px 20px 5px 7px';
element.style.display = 'inline-block';
element.style.borderRadius = '8px';
element.style.margin = '0px';
element.style.fontSize = '40px';
element.style.webkitTextStrokeWidth = '3px';
};
applyThemeToDemo(demo_lighttheme);
demo_lighttheme.textContent = '\u2B24';
demo_lighttheme.style.backgroundColor = '#cdcdcd';
demo_lighttheme.style.webkitTextStrokeColor = '#0084a6';
demo_lighttheme.style.color = '#00b1de';
applyThemeToDemo(demo_darktheme);
demo_darktheme.textContent = '\u2B24';
demo_darktheme.style.backgroundColor = 'black';
demo_darktheme.style.webkitTextStrokeColor = '#0084a6';
demo_darktheme.style.color = 'black';
demo_darktheme.style.marginLeft = '5px';
btn.style.marginTop = '5px';
btn.style.width = 'fit-content';
btn.style.cursor = 'pointer';
btn.style.color = '#004981';
btn.textContent = 'Load preset';
presetWrap.appendChild(name);
presetWrap.appendChild(description);
presetWrap.appendChild(demo_lighttheme);
presetWrap.appendChild(demo_darktheme);
presetWrap.appendChild(btn);
wrapper.appendChild(presetWrap);
btn.addEventListener('click', function() {
sliders['shadowBlur'].setValue(eachPreset.shadowBlur);
sliders['shadowOffsetX'].setValue(eachPreset.shadowOffsetX);
sliders['shadowOffsetY'].setValue(eachPreset.shadowOffsetY);
sliders['shadowStrength'].setValue(eachPreset.shadowStrength);
colors['shadowColor'].setValue(rgbToHex(eachPreset.shadowColor));
saveSettings();
});
};
var addSeparator = function(height, parentElement = wrapper) {
var separator = document.createElement('div');
separator.style.height = height + 'px';
parentElement.appendChild(separator);
};
var versionHeader = document.createElement('p');
versionHeader.style.margin = '0px';
versionHeader.style.fontSize = '12px';
versionHeader.style.position = 'absolute';
versionHeader.style.right = '10px';
versionHeader.textContent = 'Version: ' + version;
wrapper.appendChild(versionHeader);
var hotkeyTip = document.createElement('p');
hotkeyTip.style.margin = '0px';
hotkeyTip.style.fontSize = '12px';
hotkeyTip.style.position = 'absolute';
hotkeyTip.textContent = 'Press CTRL + i to activate';
wrapper.appendChild(hotkeyTip);
var heading = document.createElement('h1');
heading.textContent = 'DiepShadow';
heading.style.filter = 'drop-shadow(5px 0px 2px black)';
heading.style.color = 'white';
wrapper.appendChild(heading);
var warning = document.createElement('p');
warning.style.color = '#bb1e1e';
warning.appendChild(document.createTextNode('Warning: canvas\'s shadowBlur function is very CPU heavy.'));
addSeparator(0, warning);
warning.appendChild(document.createTextNode('Do not use if your computer is a turtle'));
wrapper.appendChild(warning);
var statusText = document.createElement('p');
statusText.style.color = '#00aa00';
statusText.style.fontWeight = 'bold';
statusText.textContent = '✓ Shadow on fills only (v4)';
wrapper.appendChild(statusText);
addCheckboxInput('Enable DiepShadow', 'enableShadow');
addCheckboxInput('Enable saving', 'enableSaving');
addSeparator(16);
addSliderInput('Shadow Radius: ', 'shadowBlur', 0, 200, 1);
addSliderInput('Shadow X Offset: ', 'shadowOffsetX', -50, 50, 1);
addSliderInput('Shadow Y Offset: ', 'shadowOffsetY', -50, 50, 1);
addSliderInput('Shadow Strength: ', 'shadowStrength', 0, 1, 0.01);
addColorInput('Shadow Color: ', 'shadowColor');
var darkDemoNotice = document.createElement('p');
darkDemoNotice.textContent = 'Note: Dark mode colors are taken from Diep.Style';
wrapper.appendChild(darkDemoNotice);
presets.forEach(addPreset);
document.body.appendChild(wrapper);
var isDisplaying = false;
document.addEventListener('keydown', function(event) {
if (!hotkey_activate_sequence(event)) return;
if (isDisplaying) {
isDisplaying = false;
wrapper.style.display = 'none';
}
else {
isDisplaying = true;
wrapper.style.display = 'block';
}
});
console.log('DiepShadow: UI initialized');
}
function saveSettings(bypass) {
if (!settings.enableSaving && !bypass) return;
window.localStorage.setItem(localStorage_key, JSON.stringify(settings));
}
// Helper functions
function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return `rgb(${parseInt(result[1], 16)},${parseInt(result[2], 16)},${parseInt(result[3], 16)})`;
}
function componentToHex(c) {
var hex = parseInt(c).toString(16);
return hex.length == 1 ? "0" + hex : hex;
}
function rgbToHex(rgb) {
var rgbsplit = rgb.split('rgb(')[1].replace(')', '').split(',');
return "#" + componentToHex(rgbsplit[0]) + componentToHex(rgbsplit[1]) + componentToHex(rgbsplit[2]);
}
// Initialize UI when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initUI);
} else {
initUI();
}
console.log('DiepShadow v' + version + ' loaded successfully!');
console.log('Current settings:', settings);
})();