DiepShadow (Fixed)

Press CTRL + I to activate. Create cool glow or 3D effects using this tool. Fixed for modern diep.io

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

You will need to install an extension such as Tampermonkey to install this script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==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);
})();