Sigmally Fixes

Many necessary improvements for Sigmally and SigMod

目前為 2024-01-07 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Sigmally Fixes
// @namespace    https://8y8x.dev/sigmally-fixes
// @version      2024-01-07
// @description  Many necessary improvements for Sigmally and SigMod
// @author       8y8x
// @match        https://sigmally.com/
// @icon         https://8y8x.dev/favicon.ico
// @license      MIT
// @grant        none
// ==/UserScript==
 
'use strict';
 
async function wait(ms) {
	return new Promise(r => setTimeout(r, ms));
}
 
// Cell improvements
(async function() {
    const { options, settings } = await import('./assets/mjs/settings.mjs');
 
	// search for Cell prototype
	let CellProto;
	do {
		const allCells = options.cells.list;
		if (allCells.length === 0) {
			await wait(50);
		} else {
			CellProto = Object.getPrototypeOf(allCells[0]);
		}
	} while (!CellProto);
 
	// prevent setting transparency while drawing cells
	// gets rid of a lot of lag when big
	let drawingCell = false;
	const globalAlphaDescriptor = Object.getOwnPropertyDescriptor(CanvasRenderingContext2D.prototype, 'globalAlpha');
	Object.defineProperty(CanvasRenderingContext2D.prototype, 'globalAlpha', {
		set: function(x) {
			if (drawingCell) return;
			globalAlphaDescriptor.set.call(this, x);
		}
	})
 
	// don't call ctx.save() and ctx.restore(), saves a bit per frame
	// may cause problems in the future if rendering changes, but unlikely
	CellProto.draw = function(ctx) {
		ctx.globalAlpha = 1;
		drawingCell = true;
		try {
			this.drawShape(ctx);
			this.drawText(ctx);
		} finally {
			drawingCell = false;
		}
	}
 
    // outline cell if it can't split
	const oldDrawShape = CellProto.drawShape;
	CellProto.drawShape = function(ctx) {
		const { byId, mine } = options.cells;
		const idx = mine.indexOf(this.id);
		if (idx === -1)
			return oldDrawShape.call(this, ctx);
 
		if (this.ns >= 128) {
			// mass >= 163
			let nextId = options.cells.mine.length;
			for (let i = 0; i < idx; ++i) {
				const cell = byId[mine[i]];
				if (cell.ns >= 128) // mass >= 163
					++nextId;
			}
 
			if (nextId < 16)
				return oldDrawShape.call(this, ctx);
		}
 
		const realSColor = this.sColor;
		this.sColor = settings.gameSettings.darkTheme ? '#fff' : '#000';
		oldDrawShape.call(this, ctx);
		this.sColor = realSColor;
	}
 
	// sidestep text caching altogether - which significantly drags game performance -
	// and just draw the damn text
	// this mostly gets rid of lag spikes when switching tabs, especially when multiboxing
	function drawText(ctx, x, y, size, text, isSub) {
		ctx.save();
		ctx.font = size + 'px Ubuntu';
		ctx.textBaseline = 'middle';
		ctx.textAlign = 'center';
		if (isSub) {
			ctx.fillStyle = '#f9bf0d';
			ctx.strokeStyle = '#40200a';
		} else {
			ctx.fillStyle = '#fff';
			ctx.strokeStyle = '#000';
		}
 
		// note: game uses floor, i use ceil and +1
		ctx.lineWidth = Math.ceil(size / 10) + 1;
		if (ctx.lineWidth * options.camera.scale > 1)
			ctx.strokeText(text, x, y);
		ctx.fillText(text, x, y);
		ctx.restore();
	}
 
	// always draw mass text, avoid text caching
	CellProto.drawText = function(ctx) {
		if (this.isPellet || this.isJagged) return;
		let y = this.y;
		if (this.name && settings.gameSettings.showNames) {
			drawText(ctx, this.x, this.y, this.drawNameSize, this.name, this.isSub);
			y += Math.max(this.s / 4.5, this.nameSize / 1.5);
		}
 
		if (settings.gameSettings.showMass) {
			const mass = Math.floor(this.s * this.s / 100).toString();
			if (mass > 50)
				drawText(ctx, this.x, y, this.drawNameSize / 2, mass, this.isSub);
		}
	}
})();
 
// Networking improvements
(async function() {
    const { options } = await import('./assets/mjs/settings.mjs');
    const { C, sendMouseMove } = await import('./assets/mjs/ws.mjs');
 
	let lastW = performance.now();
 
	const nativeSend = WebSocket.prototype.send;
	WebSocket.prototype.send = function(buf) {
		let dv;
		if (buf instanceof Uint8Array) {
			dv = new DataView(buf.buffer);
		} else if (buf instanceof ArrayBuffer) {
			dv = new DataView(buf);
		} else {
			nativeSend.call(this, buf);
			return;
		}
 
 
		if (dv.getUint8(0) === C[17]) { // space key / split
			const { mainCanvas } = options.gameOptions;
			// before splitting, always send your exact mouse position.
			// splits are sent immediately, but mouse movements are normally not. so, you might split before
			// the server knows where you aimed.
			setTimeout(() => { // timeout to allow mouse events to fire
				// copy+pasted from source
				sendMouseMove(
					(options.gameOptions.mouseX - mainCanvas.width / 2) /
						options.camera.scale +
						options.camera.x,
					(options.gameOptions.mouseY - mainCanvas.height / 2) /
						options.camera.scale +
						options.camera.y
				);
 
				nativeSend.call(this, buf);
			});
			return;
		}
 
		if (dv.getUint8(0) === C[21]) { // W
			// SigMod for whatever reason sends ~300 W's per second when only
			// 25/s are ever registered. we ratelimit most of these sends.
			if (performance.now() - lastW < 30) return;
			lastW = performance.now();
		}
 
		nativeSend.call(this, buf);
	}
})();
 
// Lag improvements
(async function() {
    // note: no idea if this actually does anything lol
    const oldRequestAnimationFrame = requestAnimationFrame;
    window.requestAnimationFrame = function(fn) {
        if (document.visibilityState === 'hidden') // if tab is not visible (ctrl+w'd away or minimized)
            oldRequestAnimationFrame(() => requestAnimationFrame(fn)); // try rendering again next frame
        else
            oldRequestAnimationFrame(fn);
    }
})();
 
// Input improvements
(async function() {
	const { C, wsSend } = await import('./assets/mjs/ws.mjs');

	// create a dialog when closing a tab, in case of an accident
	addEventListener('beforeunload', e => {
	    e.preventDefault();
	    e.returnValue = '';
	});
 
	// disable ctrl+w (only when in fullscreen) - helps when multiboxing quickly
	document.addEventListener('keydown', e => {
	    const code = e.which || e.keyCode;
	    if (e.ctrlKey && code === 87) { // ctrl+w
	        e.preventDefault();
	    } else if (e.ctrlKey && code === 9) { // ctrl+tab
	        e.returnValue = true; // undo e.preventDefault()
	        e.stopImmediatePropagation(); // prevent sigmod from calling e.preventDefault() afterwards
	    }
	});
 
	// sometimes, splits won't go through. happens if you hold Space while switching tabs, which can happen
	// often if multiboxing quickly.
	addEventListener('blur', () => {
		const ev = new KeyboardEvent('keyup', { key: ' ', code: 'Space' });
		dispatchEvent(ev);
	});

	// send the release of the Q key, which allows you to switch spectate modes
	document.addEventListener('keyup', e => {
		if (e.key === 'q') {
			wsSend(new Uint8Array([ C[19] ]));
		}
	});
})();
 
(async function() {
	// SigMod-specific fixes
 
	// forcefully enable "remove outlines" (a SigMod feature) when big,
	// as it's ugly AND massively impacts performance.
	setInterval(() => {
		const checkbox = document.querySelector('#fps-remOutlines');
		if (!checkbox) return;
 
		if (!checkbox.checked) {
			checkbox.click(); // enable the checkbox
			checkbox.disabled = true;
		}
	}, 500);
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址