Greasy Fork is available in English.
Drag and drop any font file onto the screen to replace the default fonts
// ==UserScript==
// @name Font Swapper
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Drag and drop any font file onto the screen to replace the default fonts
// @author Qwerty Matthew
// @license MIT
// @match *://*.minefun.io/*
// @grant none
// @run-at document-start
// ==/UserScript==
(function() {
'use strict';
// 1. Create a global style element to hold our injected font override rules
const fontOverrideStyle = document.createElement('style');
document.head.appendChild(fontOverrideStyle);
// Keys used for local storage caching
const STORAGE_KEY_DATA = "mf_custom_font_data";
const STORAGE_KEY_NAME = "mf_custom_font_name";
// Track injected font objects so we can cleanly remove them on reset
let activeFonts = [];
// 2. The Low-Level FontFace API Engine
function applyCustomFont(fontDataUrl, fontName, shouldSave = true) {
if (shouldSave) {
try {
localStorage.setItem(STORAGE_KEY_DATA, fontDataUrl);
localStorage.setItem(STORAGE_KEY_NAME, fontName);
} catch (e) {
console.error("[MineFun Mod] Font file is too large to store in localStorage!");
}
}
// Convert the Data URL into an ArrayBuffer for the binary FontFace API
fetch(fontDataUrl)
.then(res => res.blob())
.then(blob => blob.arrayBuffer())
.then(buffer => {
// Clear any previous custom fonts out of the registry first
clearActiveFonts();
const customFont = new FontFace('MineFunCustomFont', buffer);
const lilitaOverride = new FontFace('Lilita One', buffer);
const robotoOverride = new FontFace('Roboto', buffer);
return Promise.all([customFont.load(), lilitaOverride.load(), robotoOverride.load()]);
})
.then((loadedFonts) => {
// Add to document and track them so we can delete them later without a reload
loadedFonts.forEach(font => {
document.fonts.add(font);
activeFonts.push(font);
});
console.log(`[MineFun Mod] Active font: ${fontName}`);
fontOverrideStyle.innerHTML = `
@font-face {
font-family: 'MineFunCustomFont';
src: url('${fontDataUrl}');
}
body, div, span, p, input, button {
font-family: 'MineFunCustomFont', sans-serif !important;
}
`;
// Force game canvas text update
setTimeout(() => { window.dispatchEvent(new Event('resize')); }, 150);
})
.catch(err => console.error("[MineFun Mod] FontFace injection failed:", err));
}
// 3. Clean Reset Engine (No Page Reload)
function clearActiveFonts() {
// Remove the custom font objects from the browser's active font set
activeFonts.forEach(font => {
document.fonts.delete(font);
});
activeFonts = [];
// Clear CSS rules to let native stylesheet rules take back control
fontOverrideStyle.innerHTML = '';
}
function resetToDefault() {
localStorage.removeItem(STORAGE_KEY_DATA);
localStorage.removeItem(STORAGE_KEY_NAME);
clearActiveFonts();
console.log("[MineFun Mod] Fonts reset to native defaults mid-match.");
// Wake up canvas to render old fonts again
setTimeout(() => { window.dispatchEvent(new Event('resize')); }, 150);
}
// 4. Keyboard Shortcut Listener
window.addEventListener('keydown', (e) => {
if (e.key === '\\') {
e.preventDefault();
resetToDefault();
}
});
// 5. Invisible Drag & Drop Listener
window.addEventListener('dragover', (e) => e.preventDefault());
window.addEventListener('drop', (e) => {
e.preventDefault();
const file = e.dataTransfer.files[0];
// ADDED: Added .otf extension verification here
if (file && (file.name.endsWith('.ttf') || file.name.endsWith('.otf') || file.name.endsWith('.woff') || file.name.endsWith('.woff2'))) {
const reader = new FileReader();
reader.onload = function(event) {
const fontUrl = event.target.result;
const cleanedName = file.name.split('.')[0];
applyCustomFont(fontUrl, cleanedName, true);
};
reader.readAsDataURL(file);
}
});
// 6. Auto-Load Existing Cached Font on Startup
const savedFontData = localStorage.getItem(STORAGE_KEY_DATA);
const savedFontName = localStorage.getItem(STORAGE_KEY_NAME);
if (savedFontData && savedFontName) {
applyCustomFont(savedFontData, savedFontName, false);
}
})();