DiepShadow (Fixed)

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

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

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