// ==UserScript==
// @name Florr.io Shadows v1.2
// @namespace https://florr.io
// @version 1.21
// @description Adds some stylistic shadow effects to florr.io
// @author Jekyll#1984
// @match https://florr.io/*
// @run-at document-end
// @icon https://media.discordapp.net/attachments/843395236537434192/1054562690925867108/preview.gif
// ==/UserScript==
! function() {
"use strict";
let menuStatus = false;
let menuAlpha = 0;
let menuHasOpened = localStorage.getItem("Shader Menu Opened") != null ? JSON.parse(localStorage.getItem("Shader Menu Opened")) : false;
let helpAlpha = 0;
const lerp = (a, b, c) => a + c * (b - a);
const holder = document.createElement("div");
const shadowProperties = {};
function HandleColor(self, color, isStroke, isOffscreen) {
if (isOffscreen && !shadowProperties.shadowOffscreenCanvas) return color;
for (let key in shadowProperties) self[key] = shadowProperties[key];
if (shadowProperties.shadowColorInherit) self.shadowColor = color;
return color;
}
codeblock_one: {
const {
set: _setFillStyle,
get: _getFillStyle
} = Object.getOwnPropertyDescriptor(CanvasRenderingContext2D.prototype, 'fillStyle');
Object.defineProperty(CanvasRenderingContext2D.prototype, 'fillStyle', {
get() {
return _getFillStyle.call(this);
},
set(v) {
_setFillStyle.call(this, HandleColor(this, v, false, false));
}
});
const {
set: _setStrokeStyle,
get: _getStrokeStyle
} = Object.getOwnPropertyDescriptor(CanvasRenderingContext2D.prototype, 'strokeStyle');
Object.defineProperty(CanvasRenderingContext2D.prototype, 'strokeStyle', {
get() {
return _getStrokeStyle.call(this);
},
set(v) {
_setStrokeStyle.call(this, HandleColor(this, v, true, false));
}
});
}
codeblock_two: {
const {
set: _setFillStyle,
get: _getFillStyle
} = Object.getOwnPropertyDescriptor(OffscreenCanvasRenderingContext2D.prototype, 'fillStyle');
Object.defineProperty(OffscreenCanvasRenderingContext2D.prototype, 'fillStyle', {
get() {
return _getFillStyle.call(this);
},
set(v) {
_setFillStyle.call(this, HandleColor(this, v, false, true));
}
});
const {
set: _setStrokeStyle,
get: _getStrokeStyle
} = Object.getOwnPropertyDescriptor(OffscreenCanvasRenderingContext2D.prototype, 'strokeStyle');
Object.defineProperty(OffscreenCanvasRenderingContext2D.prototype, 'strokeStyle', {
get() {
return _getStrokeStyle.call(this);
},
set(v) {
_setStrokeStyle.call(this, HandleColor(this, v, true, true));
}
});
}
const help = document.createElement("p");
help.style.position = "absolute";
help.style.top = "0%";
help.style.left = "50%";
help.style.fontFamily = "Ubuntu";
help.style.fontSize = "3vw";
help.innerText = "Press F2 to open the Shadow Menu";
help.style.color = "#FFFFFF";
help.style.transform = "translate(-50%, -50%)";
help.style.pointerEvents = "none";
document.body.appendChild(help);
holder.style.position = "absolute";
holder.style.backgroundColor = "#1a1a1a";
holder.style.border = "1.6vw ridge #333333";
holder.style.top = "50%";
holder.style.left = "50%";
holder.style.fontFamily = "Ubuntu";
holder.style.transform = "translate(-50%, -50%)";
holder.style.padding = "0.5vw";
const settings = [
["Shadow Offset X", 0, "slider", [-20, 20], "shadowOffsetX"],
["Shadow Offset Y", 0, "slider", [-20, 20], "shadowOffsetY"],
["Shadow Strength", 0, "slider", [0, 30], "shadowBlur"],
["Shadow Color", "#FFFFFF", "color", [], "shadowColor"],
["Shadow Inherits Color", false, "checkbox", [], "shadowColorInherit"],
["Shadow on GUI (Reload Required)", false, "checkbox", [], "shadowOffscreenCanvas"],
].map(data => {
data[1] = localStorage.getItem(data[0]) != null ? localStorage.getItem(data[0]) : data[1];
const div = document.createElement("div");
div.style.width = "100%";
div.style.height = "4vw";
div.style.fontSize = "2vw";
div.style.color = "#ffffff";
const text = document.createElement("p");
text.style.margin = "0px";
text.style.padding = "0px";
text.style.display = "inline";
div.appendChild(text);
let pussyshittereatcumlol = null;
switch (data[2]) {
case "slider": {
const slider = document.createElement('input');
slider.style.verticalAlign = 'middle';
slider.style.width = '40%';
slider.type = 'range';
text.innerText = `${data[0]} (${data[1]})`;
slider.min = data[3][0];
slider.max = data[3][1];
slider.value = JSON.parse(data[1]);
slider.style.margin = "0px";
slider.style.display = "inline";
slider.style.marginLeft = "1.5vw";
slider.style.float = "right";
slider.style["-webkit-appearance"] = "none";
slider.style.height = "1vw";
slider.addEventListener('input', event => {
text.innerText = `${data[0]} (${event.target.value})`;
localStorage.setItem(data[0], event.target.value);
});
slider.step = 1;
pussyshittereatcumlol = slider;
div.appendChild(slider);
};
break;
case "color": {
const input = document.createElement('input');
input.style.verticalAlign = "middle";
input.type = "color";
input.value = data[1];
input.style.margin = "0px";
input.style.display = "inline";
input.style.marginLeft = "1.5vw";
input.style.float = "right";
input.style.width = '40%';
input.style.border = "0px";
pussyshittereatcumlol = input;
text.innerText = `${data[0]}`;
input.addEventListener('input', event => {
localStorage.setItem(data[0], event.target.value);
});
div.appendChild(input);
};
break;
case "checkbox": {
const box = document.createElement("input");
box.style.verticalAlign = "middle";
box.type = "checkbox";
text.innerText = `${data[0]}`;
box.style.display = "inline";
box.style.float = "right";
box.checked = JSON.parse(data[1]);
box.style.width = "1.5vw";
box.style.height = "1.5vw";
box.addEventListener('input', event => {
localStorage.setItem(data[0], event.target.checked);
console.log(event.target.checked);
});
pussyshittereatcumlol = box;
div.appendChild(box);
/*const slider = document.createElement('input');
slider.style.verticalAlign = 'middle';
slider.style.width = '40%';
slider.type = 'range';
text.innerText = `${data[0]} (${data[1]})`;
slider.min = data[3][0];
slider.max = data[3][1];
slider.value = JSON.parse(data[1]);
slider.style.margin = "0px";
slider.style.display = "inline";
slider.style.marginLeft = "1.5vw";
slider.style.float = "right";
slider.style["-webkit-appearance"] = "none";
slider.style.height = "1vw";
slider.addEventListener('input', event => {
text.innerText = `${data[0]} (${event.target.value})`;
localStorage.setItem(data[0], event.target.value);
});
slider.step = 1;
pussyshittereatcumlol = slider;
div.appendChild(slider);*/
}
break;
}
holder.appendChild(div);
return {
getValue: () => pussyshittereatcumlol.value === "on" ? pussyshittereatcumlol.checked : pussyshittereatcumlol.value,
property: data[4]
};
});
const div = document.createElement("div");
div.style.width = "100%";
div.style.height = "1.5vw";
div.style.fontSize = "1vw";
div.style.color = "#ffffff";
div.style.position = "absolute";
div.style.bottom = "0px";
const text = document.createElement("a");
text.text = "Script by Jekyll#1984, Enjoy!";
text.title = "Skara's Biolink";
text.href = "https://skara.glitch.me/";
text.style.float = "right";
text.style.padding = "0px";
text.style.margin = "0px";
text.style.marginRight = "1vw";
div.appendChild(text);
holder.appendChild(div);
document.body.appendChild(holder);
const animationLoop = () => {
menuAlpha = lerp(menuAlpha, menuStatus, 0.2);
holder.style.opacity = menuAlpha;
holder.style.top = `${50 * menuAlpha | 0}%`;
helpAlpha = lerp(helpAlpha, !menuHasOpened, 0.2);
help.style.opacity = helpAlpha;
//holder.style.top = `${50 * menuAlpha | 0}%`;
if (menuAlpha > 0.8) holder.style.pointerEvents = "auto";
else holder.style.pointerEvents = "none";
const ratio = Math.min(innerWidth, innerHeight) / 1080;
holder.style.width = `${800 * ratio}px`;
holder.style.height = `${500 * ratio}px`;
requestAnimationFrame(animationLoop);
for (let setting of settings) {
let value = isNaN(setting.getValue()) ? setting.getValue() : +(setting.getValue());
shadowProperties[setting.property] = value;
};
}
animationLoop();
window.addEventListener("keydown", event => {
if (event.keyCode === 113) {
event.preventDefault();
menuStatus = !menuStatus
localStorage.setItem("Shader Menu Opened", true);
menuHasOpened = true;
};
});
}();