// ==UserScript==
// @name PetriMod
// @namespace https://vk.com/petrimod
// @description Мод-пак для Чашки Петри
// @version 2.0
// @author Anonim
// @include http://petridish.pw/*
// @run-at document-start
// @grant unsafeWindow
// @license MIT
// ==/UserScript==
const config = [//True - включено, false - отключено
true,//Разблокированный зум
false,//Границы карты
false,//Интерактивные цвета игроков
true,//Фиолетовая подсветка твоих сообщений в чате (Цвет можно поменять ниже)
false,//Удалять рекламу и метрики
false,//Деление и кормёжка мышью
true,//Не показывать статистику после игры (Когда тебя съедают)
true,//Авто-обновление компаса на актуальные координаты из чата, Показ точки компаса на мини-карте
true,//Исправленая цифра общего онлайна (Вычитаются боты игры)
false,//Скрытие сообщений с координатами
true,//По умолчанию скрывать сообщения от "GameInfo Global Message" (рекорды и т.п.)
false,//Отключение анимационных скинов (Список ников с анимацией анулируется - возможны баги, сообщайте!)
false,//Отключение квадратных скинов (Список квадратных скинов анулируется - возможны баги, сообщайте!)
//
500,//История чата (100 - как у всех, 500 - как у Модеров)
//Цвет указывать только в таком же формате! (HEX-цвета)
'#a357eb',//Цвет подсветки в чате (Цвет по умочланию - фиолетовый)
'#360101',//Цвет границ карты Цвет по умочланию - тёмно-красный)
//Ниже указаны коды клавиш, чтобы поменять на своё - гугли "коды клавиш javascript"
81,//(Q) Быстрая кормежка
82,//(R) Изменить всем цвет на случайный
83,//(S) Поставить случайный скин
66,//(B) Изменить свой цвет на случайный
115//(F4) Быстрый перезаход на сервер
];//После изменения настроек, перезагрузи страницу с игрой!
var p = {};
var m = {
registerObserver: function() {
if (typeof(window.WebKitMutationObserver) == 'undefined') return;
p.observer = new window.WebKitMutationObserver(function(mutationRecords) {
mutationRecords.forEach(function(mutationRecord) {
for (var i = 0; i < mutationRecord.addedNodes.length; ++i) {
checkNode(mutationRecord.addedNodes[i]);
}
});
});
p.observer.observe(window.document, {
subtree: true,
childList: true,
attribute: false
});
}
};
m.registerObserver();
function checkNode(node) {
var tag = node.parentElement ? node.parentElement.tagName : "";
if (tag == "SCRIPT" || node.tagName == "SCRIPT") {
node.textContent = node.textContent.replaceAll('sizePlot.setValue(ballmass);', 'sizePlot.setValue(1000 > ballmass ? ballmass : "".concat(Math.round(ballmass / 100) / 10, "k"));');
}
if (tag == "SCRIPT" || node.tagName == "SCRIPT") {
node.textContent = node.textContent.replaceAll('playByLocationHash();', '');
}
if (tag == "SCRIPT" || node.tagName == "SCRIPT") {
node.textContent = node.textContent.replaceAll('animationTick++;', 'animationTick++;fps.tick();');
}
if (tag == "SCRIPT" || node.tagName == "SCRIPT") {
if (config[2]) {
node.textContent = node.textContent.replaceAll('// color = this.color;', 'color = this.color;');
node.textContent = node.textContent.replaceAll('// color = "#300A48";', 'color = "#300A48";');
node.textContent = node.textContent.replaceAll('// color = "#A020F0";', 'color = "#A020F0";');
node.textContent = node.textContent.replaceAll('// color = "#3371FF";', '');
node.textContent = node.textContent.replaceAll('// color = "#FF3C3C";', 'color = "#FF3C3C";');
node.textContent = node.textContent.replaceAll('// color = "#FFBF3D";', 'color = "#FFBF3D";');
node.textContent = node.textContent.replaceAll('// color = "#44F720";', 'color = "#44F720";');
node.textContent = node.textContent.replaceAll('//color = "#00AA00";', 'color = "#00AA00";');
node.textContent = node.textContent.replaceAll('//color = "#FFFF00";', 'color = "#FFFF00";');
}
}
if (tag == "SCRIPT" || node.tagName == "SCRIPT") {
if (config[0]) {
node.textContent = node.textContent.replace(/ > zoom/g, ' > zoom && false');
node.textContent = node.textContent.replaceAll('if (isFB == 1) { event.preventDefault(); }', 'if (0.1 > zoom) { zoom = 0.1; }\nif (isFB == 0.1) { event.preventDefault(); }');
}
}
if (tag == "SCRIPT" || node.tagName == "SCRIPT") {
if (config[1]) {
node.textContent = node.textContent.replace(/ function drawBorders(ctx) {/g, ' function drawBorders(ctx) {');
node.textContent = node.textContent.replaceAll(' function drawBorders(ctx) {', `function drawBorders(ctx) { ctx.save();
ctx.beginPath();
ctx.fillStyle = '${config[15]}';
ctx.rect(-mapmaxX, -mapmaxY, mapmaxX * 3, mapmaxY);
ctx.rect(mapmaxX, 0, mapmaxX, mapmaxY * 2);
ctx.rect(-mapmaxX, 0, mapmaxX, mapmaxY * 2);
ctx.rect(0, mapmaxY, mapmaxX, mapmaxY);
ctx.fill();
ctx.lineWidth = 1;
ctx.strokeStyle = '#FFFFFF';
ctx.strokeRect(0, 0, mapmaxX, mapmaxY);
ctx.restore();`);
}
}
if (tag == "SCRIPT" || node.tagName == "SCRIPT") {
node.textContent = node.textContent.replace('var chathistory = 100;', `var chathistory = ${config[13]};`);
}
if (tag == "SCRIPT" || node.tagName == "SCRIPT") {
node.textContent = node.textContent.replace(
'var checkchat = readCookie("ruschat");',
`if ((GameInfoHide == true) && (escnick.indexOf('***** GameInfo Global Message *****') != -1)) {
state = ' style="display:none;" ';
}
if (blacklistchat.indexOf(Number(chatid)) != -1) {
state = ' style="display:none;" ';
}
var checkchat = readCookie("ruschat");`
);
node.textContent = node.textContent.replace(
"if (chatBoard[len - 1].message.indexOf('**coords:') != -1) {",
`if (chatBoard[len - 1].message.indexOf('**coords:') != -1) {
state = '';
if (chatCordiHide) {
state = ' style="display:none;" ';
}
`
);
node.textContent = node.textContent.replace("<div class='chatenter'>", `<div " + state + " class='chatenter'>`);
}
if (tag == "SCRIPT" || node.tagName == "SCRIPT") {
if (config[3]) {
node.textContent = node.textContent.replace(
"if (supermods.indexOf(chatnicknoid.toLowerCase()) != -1) {",
`if ((podcvetka == true) && (chatid == igrokId)) {
mod = "style='color:white;background-color:${config[14]};padding:0px 5px;'";
}
if (supermods.indexOf(chatnicknoid.toLowerCase()) != -1) {`
);
}
}
if (tag == "SCRIPT" || node.tagName == "SCRIPT") {
if (config[8]) {
node.textContent = node.textContent.replace(`$("p.online span").html(srs['total']);`, `var total = 0;`);
node.textContent = node.textContent.replace(
/\$\("#now" \+ sern \+ ", #likednow" \+ sern\).html\(cura\);\n\s+}/,
`let el = $("#now" + sern + ", #likednow" + sern).html(cura)[0];
if ((typeof el != 'undefined') && (/^arena\d+/i.test(sern) == false)) {total = total+cura;};};
var botiki = (20+25+10+20+33+10+10+10+10+10+10+10+30+25+10+30+100+25+20+15+25+17+17+27+27+15+20+15+5+30+5+50+5);
$("p.online span").html(total-botiki);`
);
}
}
if (tag == "SCRIPT" || node.tagName == "SCRIPT") {
if (config[7]) {
node.textContent = node.textContent.replace(`setCompas("`, `setCompas(" + chatid + ", " `);
node.textContent = node.textContent.replace(`setCompas(posX,posY)`, `setCompas(chatid, posX, posY)`);
node.textContent = node.textContent.replace(
`$("#kompasx").val(posX);`,
`kompasId = chatid;kompasPosX = posX;kompasPosY = posY;$("#kompasposition").css("display", "block");$("#kompasx").val(posX);`
);
node.textContent = node.textContent.replace(
`if (Yhere < 0) { Yhere = 0; }`,
`if (Yhere < 0) { Yhere = 0; };if (chatid == kompasId) { setCompas(chatid, Xhere, Yhere); };`);
node.textContent = node.textContent.replace(
`$("div.map-header .coords").html(bbuuX + '.' + bbuuY);`,
`$("div.map-header .coords").html(bbuuX + '.' + bbuuY);
if ((kompasPosX > 0) || (kompasPosY > 0)) {
var kompasX = ~~(kompasPosX / maxX * 100);
var kompasY = ~~(kompasPosY / maxY * 100);
$("#kompasposition").css("top", kompasY+ "%").css("left", kompasX+"%");
}
`);
}
}
if (tag == "SCRIPT" || node.tagName == "SCRIPT") {
node.textContent = node.textContent.replaceAll(`sendChat("***playerenter***");`, `sendChat("***playerenter***");lovimIgrokId = true;`);
node.textContent = node.textContent.replaceAll(`chatBoard.push({`, `let nick = getString();let msg = getString();chatBoard.push({`);
node.textContent = node.textContent.replaceAll(`"name": getString(),`, `"name": nick, `);
node.textContent = node.textContent.replaceAll(`"message": getString(),`, `"message": msg, `);
node.textContent = node.textContent.replaceAll(
`if (window.currentStatus != 'secret') {`,
`var iddlina = nick.indexOf(")") - 1;
var chatid = Number(nick.substr(1, iddlina));
if ((lovimIgrokId == true) && (msg == '***playerenter***')) {
igrokId = chatid;
lovimIgrokId = false;
}
if (window.currentStatus != 'secret') {`
);
}
if (tag == "SCRIPT" || node.tagName == "SCRIPT") {
node.textContent = node.textContent.replace(/[ \S]+old-design-ru[ \S]+/ig, '');
}
if (tag == "SCRIPT" || node.tagName == "SCRIPT") {
if (config[4]) {
if (node.textContent.indexOf('www.acint.net/aci.js') != -1) {
node.remove();
}
}
}
if (tag == "SCRIPT" || node.tagName == "SCRIPT") {
if (config[4]) {
if ((node.src == 'https://mc.yandex.ru/metrika/watch.js') || (node.textContent.indexOf('https://mc.yandex.ru/metrika/watch.js') != -1)) {
node.remove();
}
}
}
if (tag == "NOSCRIPT" || node.tagName == "NOSCRIPT") {
if (config[4]) {
if (node.textContent.indexOf('https://mc.yandex.ru/watch/') != -1) {
node.remove();
}
}
}
if (tag == "SCRIPT" || node.tagName == "SCRIPT") {
if (config[4]) {
if ((node.textContent.indexOf('adsbygoogle') != -1) || (typeof node.src != 'undefined' && node.src.indexOf('adsbygoogle') != -1)) {
node.remove();
}
}
}
if (tag == "INS" || node.tagName == "INS") {
if (config[4]) {
node.remove();
}
}
if (tag == "IFRAME" || node.tagName == "IFRAME") {
if (config[4]) {
if ((typeof node.src != 'undefined') && (node.src == 'https://www.youtube.com/embed/Ye0XkOKxM4w')) {
node.remove();
}
}
}
}
////////////////////////////////////////////////////////////////////////////////////////
document.addEventListener("DOMContentLoaded", function(event) {
p.observer.disconnect();
const win = unsafeWindow;
win.igrokId = 0;
win.lovimIgrokId = false;
win.kompasId = 0;
win.kompasPosX = 0;
win.kompasPosY = 0;
win.podcvetka = config[3];
if (config[11]) {
win.animated = [];
}
if (config[12]) {
win.squareskins = [];
}
$('#twrbutton').hide();
$('#how').hide();
var fpsDiv = document.createElement('div');
fpsDiv.id = 'fps'
fpsDiv.style = 'font-size: 18px;color: #50f500;position: absolute;right: 200px;bottom: 10px;'
fpsDiv.textContent = '0';
$("#map").before(fpsDiv);
setInterval(function () {
if (fps.value > 0 && fps.value < 61) {
document.getElementById("fps").textContent = fps.value;
}
}, 120);
var span = document.createElement('span');
span.id = 'kompasposition'
span.style = 'background:red;display:none;'
span.className = 'round blue';
$("#map > .map-container").append(span);
var li = document.createElement('li');
li.title = 'Отображение координат в чате';
li.innerHTML = '<label><input type="checkbox" id="chatCordi" onchange="chatCordiFunc();" checked="checked"><i class="mdi mdi-target mdi-18px"></i></label>';
$("#chat > .chat-header > ul").append(li);
var li2 = document.createElement('li');
li2.title = 'Отображение сообщений от "GameInfo Global Message" (рекорды и т.п.)';
li2.innerHTML = '<label><input type="checkbox" id="GameInfo" onchange="GameInfoFunc();" checked="checked"><i class="mdi mdi-message-bulleted mdi-18px"></i></label>';
$("#chat > .chat-header > ul").append(li2);
var li3 = document.createElement('li');
li3.title = 'Отображение входов в чате';
li3.innerHTML = '<label><input type="checkbox" id="chatVxodi" onchange="chatVxodiFunc();" checked="checked"><i class="mdi mdi-login mdi-18px"></i></label>';
$("#chat > .chat-header > ul").append(li3);
chatenter.closest('li').remove();
var nikigroka = readCookie("playername");
var chatwelcome = $('.chatwelcome').html();
var newchatwelcome = chatwelcome.replace(/https.*Google Play/ig, 'Добро пожаловать!<br>Новости и обновления PetriMod в группе ВК: <a target="_blank" href="https://vk.com/petrimod">https://vk.com/petrimod</a>');
$('.chatwelcome').html(newchatwelcome);
win.chatCordiHide = config[9];
if (config[9]) {
$("#chatCordi").removeAttr("checked");
win.document.getElementById('chatCordi').nextSibling.style.opacity = '0.5';
}
win.GameInfoHide = config[10];
if (config[10]) {
$("#GameInfo").removeAttr("checked");
win.document.getElementById('GameInfo').nextSibling.style.opacity = '0.5';
}
if (readCookie('chatenter') == 'false') {
$("#chatVxodi").removeAttr("checked");
win.document.getElementById('chatVxodi').nextSibling.style.opacity = '0.5';
}
else {
$("#chatVxodi").attr("checked","checked");
win.document.getElementById('chatVxodi').nextSibling.style.opacity = '1';
}
win.chatCordiFunc = function(e) {
var el = document.querySelectorAll('#chatlog > div');
if ($("#chatCordi").prop('checked') == true) {
$("#chatCordi").attr("checked","checked");
win.chatCordiHide = false;
win.document.getElementById('chatCordi').nextSibling.style.opacity = '1';
for (let elem of el) {
if (elem.innerHTML.indexOf('title="Player Coords"') != -1) {
elem.style.display = 'block';
}
}
}
else {
$("#chatCordi").removeAttr("checked");
win.chatCordiHide = true;
win.document.getElementById('chatCordi').nextSibling.style.opacity = '0.5';
for (let elem of el) {
if (elem.innerHTML.indexOf('title="Player Coords"') != -1) {
elem.style.display = 'none';
}
}
}
}
win.GameInfoFunc = function(e) {
var el = document.querySelectorAll('#chatlog > div');
if ($("#GameInfo").prop('checked') == true) {
$("#GameInfo").attr("checked","checked");
win.GameInfoHide = false;
win.document.getElementById('GameInfo').nextSibling.style.opacity = '1';
for (let elem of el) {
if (elem.innerHTML.indexOf('***** GameInfo Global Message *****') != -1) {
elem.style.display = 'block';
}
}
}
else {
$("#GameInfo").removeAttr("checked");
win.GameInfoHide = true;
win.document.getElementById('GameInfo').nextSibling.style.opacity = '0.5';
for (let elem of el) {
if (elem.innerHTML.indexOf('***** GameInfo Global Message *****') != -1) {
elem.style.display = 'none';
}
}
}
}
win.chatVxodiFunc = function(e) {
var el = document.querySelectorAll('#chatlog > div');
createCookie('chatenter', $("#chatVxodi").is(':checked'), 999);
var chatenter = readCookie("chatenter");
if (chatenter == null) {
$("#chatVxodi").removeAttr("checked");
for (let elem of el) {
if ((elem.className == 'chatenter') && (elem.innerHTML.indexOf('title="Player Coords"') == -1)) {
elem.style.display = 'none';
}
}
}
if (chatenter == 'true') {
win.document.getElementById('chatVxodi').nextSibling.style.opacity = '1';
$("#chatVxodi").attr("checked","checked");
for (let elem of el) {
if ((elem.className == 'chatenter') && (elem.innerHTML.indexOf('title="Player Coords"') == -1)) {
elem.style.display = 'block';
}
}
$("#chatlog").scrollTop(500000);
}
if (chatenter == 'false') {
win.document.getElementById('chatVxodi').nextSibling.style.opacity = '0.5';
$("#chatVxodi").removeAttr("checked");
for (let elem of el) {
if ((elem.className == 'chatenter') && (elem.innerHTML.indexOf('title="Player Coords"') == -1)) {
elem.style.display = 'none';
}
}
}
}
var banSkinov = document.createElement ('div');
banSkinov.innerHTML = `
<div id="ban-skinov" class="ban-skinov"><div class="ban-skinov-w">
<div class="ban-skinov-i"><div class="ban-skinov-h">
<h3 class="ban-skinov-t">Блокировка скинов</h3>
<span class="ban-skinov-c" id="zabanitbskinclose">×</span></div>
<div id="spisokskinov"></div></div></div></div>
<style>
.ban-skinov{background:rgba(0,0,0,0.7);pointer-events:none;position:fixed;
top:0;right:0;bottom:0;left:0;z-index:9999;transition:all .5s ease;margin:0;padding:0;opacity:0}
.ban-skinov:target{opacity:1;pointer-events:auto;overflow-y:auto}
.ban-skinov-w{margin:auto;margin-top:60px;margin-bottom:20px}
.ban-skinov-i{position:relative;border:1px solid;border-color:red;border-radius:25px}
.ban-skinov-h{padding:15px;position:relative}
.ban-skinov-t{text-align:center;font-size:18px;color:#555;
font-weight:700;line-height:1.5;margin-top:0;margin-bottom:0}
.ban-skinov-c{position:absolute;top:4px;right:12px;font-size:28px;color:red;text-decoration:none}
.ban-skinov-c:focus,.ban-skinov-c:hover{color:red;cursor:pointer}
div#ban-skinov img{background-color:#dc3f3f;cursor:pointer;border:2px solid;
border-color:red;border-radius:50%;width:128px;height:128px;margin:8px}
@media (min-width:550px) {.ban-skinov-w{max-width:890px}}
</style>
`;
document.body.appendChild(banSkinov);
var divIkonka = document.createElement('div');
divIkonka.id = 'zabanitbskinopen';
divIkonka.title = 'Скрыть определённый скин';
divIkonka.className = 'button no-hover round opacity';
divIkonka.innerHTML = `<i class="mdi mdi-delete-circle mdi-24px"></i>`;
$('#sun').after(divIkonka);
$( "#zabanitbskinopen" ).click(function() {
var ujeDobavleno = [];
var HTML = '';
for (var key in playerSkins) {
if ((playerSkins[key] != 0) && (ujeDobavleno.indexOf(playerSkins[key]) == -1)) {
ujeDobavleno.push(playerSkins[key]);
HTML = HTML+'<img src="http://petridish.pw/engine/serverskins/'+playerSkins[key]+'.png" onclick="zabanitbSkin('+key+');this.remove();">';
}
}
document.getElementById('spisokskinov').innerHTML = HTML;
if (ujeDobavleno.length) {
win.location.hash = '#ban-skinov';
}
else if (skinsspisok.length) {
alert("Ты уже перебанил всех!");
}
});
$( "#zabanitbskinclose" ).click(function() {
win.location.hash = '#'+win.currentStatus;
});
var skinsspisok = [];
setInterval(function () {
if (skinsspisok.length < 1) return;
for (var key in playerSkins) {
if (skinsspisok.indexOf(playerSkins[key]) != -1) {
playerSkins[key] = 0;
}
}
}, 5000);
win.zabanitbSkin = function(ID) {
alert("Скин "+playerSkins[ID]+" скрыт в игре до перезагрузки страницы!");
skinsspisok.push(playerSkins[ID]);
playerSkins[ID] = 0;
}
var feeding = false;
var wDown = $.Event("keydown", { keyCode: 87});
var wUp = $.Event("keyup", { keyCode: 87});
var interval = null;
var splitdown = $.Event("keydown", { keyCode: 32});
var splitup = $.Event("keyup", { keyCode: 32});
$(document).bind('mousedown', function(e){
if ((isTyping == false) && config[5]) {
if (e.which == 1) {
clearInterval(interval);
feeding = true;
setTimeout(function () {
clearInterval(interval);
if (feeding) {
interval = setInterval(function () {
$("body").trigger(wDown);
$("body").trigger(wUp);
}, 0);
}
}, 150);
}
if (e.which == 3) {
$("body").trigger(splitdown);
$("body").trigger(splitup);
}
}
}).bind('mouseup', function(e){
if (config[5]) {
if (e.which == 1) {
feeding = false;
clearInterval(interval);
}
}
}).bind('keydown', function(e){
if ((e.keyCode == config[16]) && (isTyping == false)) {
$("body").trigger(wDown);
$("body").trigger(wUp);
}
if ((e.keyCode == config[17]) && (isTyping == false)) {
var key = null;
for (key in win.playerColorIndexes) {
if (key != igrokId) {
win.playerColorIndexes[key] = randomnumber(127);
}
}
win.fly('Рандомные цвета!');
}
if ((e.keyCode == config[18]) && (igrokId > 0) && (isTyping == false)) {
win.playerSkins[igrokId] = randomnumber(333333);
win.fly('Рандомный скин!');
}
}).bind('keyup', function(e){
if ((e.keyCode == config[19]) && (isTyping == false)) {
win.playercolor = randomnumber(127);
sendCol();
win.fly('Рандомный цвет!');
}
if (e.keyCode == config[20]) {
win.socketaddr = '';
$('#newplaybutton').click();
}
});
$('canvas').bind('contextmenu', function(e){
e.preventDefault();
});
if (config[6]) {
var targetNode = document.getElementById('endgameoverlay');
var observer = new MutationObserver(function(){
if (targetNode.style.display != 'none') {
win.$('#endgameoverlay, #gameoverlay').hide();
win.jQuery('#specbutton').show();
win.setSpectate(true);
win.setUnlimitedZoom(true);
win.startthegame();
win.sp(1);
win.performFullHide();
win.fly('ПОТРАЧЕНО!))');
}
});
observer.observe(targetNode, { attributes: true, childList: true });
}
win.blacklistchat = [];
var chatobserver = new MutationObserver(function(mutationsList) {
for (var mutation of mutationsList) {
for (var node of mutation.addedNodes) {
if (node.matches('ul.chat-context-menu')) {
var text = 'Заблокировать';
var playerID = Number(node.dataset.chatId);
if (blacklistchat.indexOf(playerID) != -1) { text = 'Разблокировать'; }
node.appendChild($(`<li><a onclick="blacklistchatFunc(${playerID})">${text}</a></li>`)[0]);
}
}
}
});
chatobserver.observe(document.body, { childList: true });
win.blacklistchatFunc = function (playerID) {
var index = blacklistchat.indexOf(playerID);
if (index != -1) {
blacklistchat.splice(index, 1);
}
else {
blacklistchat.push(playerID);
}
}
function randomnumber(max) {
return Math.floor(Math.random() * max);
}
});
unsafeWindow.fps = {
sampleSize : 60,
value : 0,
_sample_ : [],
_index_ : 0,
_lastTick_: false,
tick : function(){
// if is first tick, just set tick timestamp and return
if( !this._lastTick_ ){
this._lastTick_ = performance.now();
return 0;
}
// calculate necessary values to obtain current tick FPS
let now = performance.now();
let delta = (now - this._lastTick_)/1000;
let fps = 1/delta;
// add to fps samples, current tick fps value
this._sample_[ this._index_ ] = Math.round(fps);
// iterate samples to obtain the average
let average = 0;
for(var i=0; i<this._sample_.length; i++) average += this._sample_[ i ];
average = Math.round( average / this._sample_.length);
// set new FPS
this.value = average;
// store current timestamp
this._lastTick_ = now;
// increase sample index counter, and reset it
// to 0 if exceded maximum sampleSize limit
this._index_++;
if( this._index_ === this.sampleSize) this._index_ = 0;
return this.value;
}
}