Client-side SkyWars HUD, visual controls, diagnostics, and compatible movement helpers for Minefun.io.
// ==UserScript==
// @name Minefun.io SkyWars VIP Client
// @namespace https://greasyfork.org/userscripts/minefun-skywars-vip
// @version 4.0.1
// @description Client-side SkyWars HUD, visual controls, diagnostics, and compatible movement helpers for Minefun.io.
// @author Minefun Modder
// @license MIT
// @match https://minefun.io/*
// @match https://*.minefun.io/*
// @grant none
// @run-at document-start
// ==/UserScript==
(function () {
'use strict';
const VERSION = '4.0.1';
const MENU_KEY = ',';
const STORAGE_KEY = 'MINEFUN_SKYWARS_VIP_V4';
const Client = {
name: 'MINEFUN SKY WARS VIP',
version: VERSION,
menuOpen: false,
ready: false,
uiBuilt: false,
gameDetected: false,
lastEngineScan: 0,
lastStatus: 'Starting...',
modules: [],
categories: [
'SkyWars',
'Visuals',
'HUD',
'Movement',
'Utility',
'Diagnostics'
],
engine: null,
player: null,
world: null,
store: null,
app: null,
raf: null
};
// =========================================================
// HELPERS
// =========================================================
function now() {
return performance.now();
}
function num(value, fallback = 0) {
return Number.isFinite(Number(value))
? Number(value)
: fallback;
}
function firstDefined(...values) {
for (const value of values) {
if (value !== undefined && value !== null) {
return value;
}
}
return undefined;
}
function escapeHtml(value) {
return String(value)
.replaceAll('&', '&')
.replaceAll('<', '<')
.replaceAll('>', '>')
.replaceAll('"', '"')
.replaceAll("'", ''');
}
function cssEscape(value) {
try {
if (
window.CSS &&
typeof window.CSS.escape === 'function'
) {
return window.CSS.escape(String(value));
}
} catch (_) {}
return String(value).replace(
/([\\.#$%&'()*+,/:;<=>?@\[\\\]^`{|}~])/g,
'\\$1'
);
}
function getCanvas() {
return document.querySelector('canvas');
}
function log(...args) {
console.log(
`%c[${Client.name}]`,
'color:#ff0055;font-weight:bold',
...args
);
}
function warn(...args) {
console.warn(
`%c[${Client.name}]`,
'color:#ffaa00;font-weight:bold',
...args
);
}
// =========================================================
// CONFIG
// =========================================================
function saveConfig() {
const config = {};
for (const module of Client.modules) {
config[module.name] = !!module.enabled;
}
try {
localStorage.setItem(
STORAGE_KEY,
JSON.stringify(config)
);
} catch (_) {}
}
function loadConfig() {
let saved = null;
try {
saved = localStorage.getItem(
STORAGE_KEY
);
} catch (_) {}
if (!saved) return;
try {
const config = JSON.parse(saved);
for (const module of Client.modules) {
if (
Object.prototype.hasOwnProperty.call(
config,
module.name
)
) {
module.enabled =
!!config[module.name];
}
}
} catch (error) {
warn('Config error:', error);
}
}
// =========================================================
// MODULE SYSTEM
// =========================================================
class Module {
constructor(
name,
category,
description,
options = {}
) {
this.name = name;
this.category = category;
this.description = description;
this.defaultEnabled =
!!options.defaultEnabled;
this.enabled =
this.defaultEnabled;
this.status =
this.enabled ? 'ON' : 'OFF';
this.reason = '';
this.settings =
options.settings || {};
this.onEnableHandler =
options.onEnable || null;
this.onDisableHandler =
options.onDisable || null;
this.tickHandler =
options.onTick || null;
this.renderHandler =
options.onRender || null;
Client.modules.push(this);
}
setStatus(status, reason = '') {
this.status = status;
this.reason = reason;
const card =
document.querySelector(
`[data-mod="${cssEscape(this.name)}"]`
);
if (!card) return;
card.classList.toggle(
'enabled',
this.enabled
);
card.classList.toggle(
'waiting',
status === 'WAIT'
);
card.classList.toggle(
'error',
status === 'ERR'
);
const statusNode =
card.querySelector(
'.vip-status'
);
if (statusNode) {
statusNode.textContent =
this.enabled
? status
: 'OFF';
}
const reasonNode =
card.querySelector(
'.vip-reason'
);
if (reasonNode) {
reasonNode.textContent =
reason;
}
}
enable() {
this.enabled = true;
try {
if (this.onEnableHandler) {
this.onEnableHandler(this);
}
if (
Client.gameDetected ||
this.category === 'Diagnostics'
) {
this.setStatus(
'ON',
'Active'
);
} else {
this.setStatus(
'WAIT',
'Waiting for engine'
);
}
} catch (error) {
this.setStatus(
'ERR',
String(error)
);
}
saveConfig();
}
disable() {
try {
if (this.onDisableHandler) {
this.onDisableHandler(this);
}
} catch (_) {}
this.enabled = false;
this.setStatus('OFF', '');
saveConfig();
}
toggle() {
if (this.enabled) {
this.disable();
} else {
this.enable();
}
refreshHUD();
}
onTick() {
if (!this.enabled) return;
try {
if (this.tickHandler) {
this.tickHandler(this);
}
} catch (error) {
this.setStatus(
'ERR',
String(error)
);
}
}
onRender() {
if (!this.enabled) return;
try {
if (this.renderHandler) {
this.renderHandler(this);
}
} catch (error) {
this.setStatus(
'ERR',
String(error)
);
}
}
}
// =========================================================
// ENGINE BRIDGE
// =========================================================
const Engine = {
lastScan: 0,
scanInterval: 250,
scan() {
const current = now();
if (
current - this.lastScan <
this.scanInterval
) {
return;
}
this.lastScan = current;
Client.app =
window.app || null;
if (!Client.app) {
Client.gameDetected = false;
Client.engine = null;
Client.player = null;
Client.world = null;
Client.store = null;
Client.lastStatus =
'Waiting for window.app';
return null;
}
let gameState = null;
let store = null;
try {
const vnode =
Client.app?._vnode;
const component =
vnode?.component;
const provides =
component
?.appContext
?.provides;
if (provides) {
const symbols =
Object.getOwnPropertySymbols(
provides
);
const symbol =
symbols.find(
item => {
try {
return !!provides[item]?._s;
} catch (_) {
return false;
}
}
);
if (symbol) {
store =
provides[symbol]._s;
}
}
if (store?.get) {
gameState =
store.get('gameState');
}
} catch (_) {}
const world =
gameState?.gameWorld ||
gameState?.world ||
null;
const player =
world?.player ||
gameState?.player ||
null;
Client.store = store;
Client.world = world;
Client.player = player;
Client.engine = {
gameState,
world,
player
};
Client.gameDetected =
!!gameState ||
!!world ||
!!player;
Client.lastStatus =
Client.gameDetected
? 'SkyWars engine connected'
: 'Engine found, waiting for player';
return Client.engine;
},
getGameState() {
this.scan();
return Client.engine?.gameState || null;
},
getWorld() {
this.scan();
return Client.world;
},
getPlayer() {
this.scan();
return Client.player;
},
getPosition() {
const player =
this.getPlayer();
return (
player?.position ||
player?.pos ||
player?.transform?.position ||
null
);
},
getVelocity() {
const player =
this.getPlayer();
return (
player?.velocity ||
player?.physics?.velocity ||
player?.motion ||
null
);
},
getCollision() {
const player =
this.getPlayer();
return (
player?.collision ||
player?.physics?.collision ||
null
);
},
getHealth() {
const player =
this.getPlayer();
return num(
firstDefined(
player?.health,
player?.hp,
player?.stats?.health
),
0
);
},
getEntities() {
const world =
this.getWorld();
const candidates = [
world?.entities,
world?.players,
world?.mobs,
world?.actors,
world?.objects
];
for (const value of candidates) {
if (Array.isArray(value)) {
return value;
}
if (
value &&
typeof value.values ===
'function'
) {
return Array.from(
value.values()
);
}
}
return [];
},
getJumpSpeed() {
const velocity =
this.getVelocity();
if (!velocity) return undefined;
return firstDefined(
velocity.jumpSpeed,
velocity.jumpVelocity,
velocity.jumpPower
);
},
setJumpSpeed(value) {
const velocity =
this.getVelocity();
if (!velocity) return false;
let changed = false;
if (
'jumpSpeed' in velocity
) {
velocity.jumpSpeed = value;
changed = true;
}
if (
'jumpVelocity' in velocity
) {
velocity.jumpVelocity = value;
changed = true;
}
if (
'jumpPower' in velocity
) {
velocity.jumpPower = value;
changed = true;
}
return changed;
},
getHorizontalVelocity() {
const velocity =
this.getVelocity();
if (!velocity) return null;
const vector =
velocity.velVec3 ||
velocity.vector ||
velocity;
return {
x: num(vector.x),
y: num(vector.y),
z: num(vector.z)
};
},
scaleHorizontalVelocity(
multiplier
) {
const velocity =
this.getVelocity();
if (!velocity) return false;
const vector =
velocity.velVec3 ||
velocity.vector ||
velocity;
if (
!Number.isFinite(vector.x) ||
!Number.isFinite(vector.z)
) {
return false;
}
vector.x *= multiplier;
vector.z *= multiplier;
return true;
},
getGameMode() {
const state =
this.getGameState();
return String(
firstDefined(
state?.mode,
state?.gameMode,
state?.gameType,
'unknown'
)
);
},
isSkyWars() {
const mode =
this.getGameMode();
return mode
.toLowerCase()
.includes('sky') ||
Client.gameDetected;
},
getPlayerName() {
const player =
this.getPlayer();
return String(
firstDefined(
player?.name,
player?.username,
player?.displayName,
'Player'
)
);
}
};
// =========================================================
// STATE
// =========================================================
const State = {
originalJumpSpeed: null,
fpsFrames: 0,
fpsLast: now(),
fps: 0,
canvasFilter: ''
};
// =========================================================
// MODULES
// =========================================================
const EngineScanner = new Module(
'Engine Scanner',
'Diagnostics',
'Checks the SkyWars engine continuously.',
{
defaultEnabled: true
}
);
EngineScanner.onTick = function () {
Engine.scan();
this.setStatus(
Client.gameDetected
? 'ON'
: 'WAIT',
Client.lastStatus
);
};
const PlayerInspector = new Module(
'Player Inspector',
'Diagnostics',
'Checks player position, velocity and collision.',
{}
);
PlayerInspector.onRender = function () {
if (!Client.gameDetected) {
this.setStatus(
'WAIT',
'Player unavailable'
);
return;
}
const parts = [];
if (Engine.getPosition()) {
parts.push('POS');
}
if (Engine.getVelocity()) {
parts.push('VEL');
}
if (Engine.getCollision()) {
parts.push('COL');
}
this.setStatus(
'ON',
parts.join(' + ') || 'PLAYER'
);
};
const EntityScanner = new Module(
'Entity Scanner',
'Diagnostics',
'Counts entities exposed by the game runtime.',
{}
);
EntityScanner.onRender = function () {
const entities =
Engine.getEntities();
this.setStatus(
Client.gameDetected
? 'ON'
: 'WAIT',
`Entities: ${entities.length}`
);
};
const SkyWarsReady = new Module(
'SkyWars Ready',
'SkyWars',
'Shows when a compatible SkyWars player object is detected.',
{
defaultEnabled: true
}
);
SkyWarsReady.onRender = function () {
const node =
document.getElementById(
'vip-ready'
);
if (!node) return;
node.textContent =
Client.gameDetected
? 'READY'
: 'WAITING';
node.style.color =
Client.gameDetected
? '#00ff8c'
: '#ffaa00';
};
const Crosshair = new Module(
'Crosshair',
'Visuals',
'Adds a simple client-side crosshair.',
{
defaultEnabled: true
}
);
Crosshair.onEnable = function () {
const node =
document.getElementById(
'vip-crosshair'
);
if (node) {
node.style.display = 'block';
}
};
Crosshair.onDisable = function () {
const node =
document.getElementById(
'vip-crosshair'
);
if (node) {
node.style.display = 'none';
}
};
const Fullbright = new Module(
'Fullbright',
'Visuals',
'Brightens the game canvas locally.',
{}
);
Fullbright.onEnable = function () {
applyCanvasFilter();
};
Fullbright.onDisable = function () {
applyCanvasFilter();
};
const SaturationBoost = new Module(
'Saturation Boost',
'Visuals',
'Improves color visibility locally.',
{}
);
SaturationBoost.onEnable = function () {
applyCanvasFilter();
};
SaturationBoost.onDisable = function () {
applyCanvasFilter();
};
function applyCanvasFilter() {
const canvas =
getCanvas();
if (!canvas) return;
const filters = [];
if (Fullbright.enabled) {
filters.push(
'brightness(1.5)'
);
}
if (SaturationBoost.enabled) {
filters.push(
'saturate(1.35)'
);
}
canvas.style.filter =
filters.join(' ') ||
State.canvasFilter ||
'';
}
const FPSCounter = new Module(
'FPS Counter',
'HUD',
'Displays live browser FPS.',
{}
);
FPSCounter.onRender = function () {
const current = now();
State.fpsFrames++;
if (
current - State.fpsLast >=
500
) {
State.fps =
State.fpsFrames /
(
(current - State.fpsLast) /
1000
);
State.fpsFrames = 0;
State.fpsLast = current;
}
const node =
document.getElementById(
'vip-hud-fps'
);
if (node) {
node.textContent =
`FPS: ${Math.round(State.fps)}`;
}
};
const Coordinates = new Module(
'Coordinates',
'HUD',
'Displays your current coordinates.',
{}
);
Coordinates.onRender = function () {
const node =
document.getElementById(
'vip-hud-coords'
);
if (!node) return;
const position =
Engine.getPosition();
if (!position) {
node.textContent =
'X: ? Y: ? Z: ?';
return;
}
node.textContent =
`X: ${num(position.x).toFixed(1)} ` +
`Y: ${num(position.y).toFixed(1)} ` +
`Z: ${num(position.z).toFixed(1)}`;
};
const HealthHUD = new Module(
'Health HUD',
'HUD',
'Displays the health value exposed by the game.',
{}
);
HealthHUD.onRender = function () {
const node =
document.getElementById(
'vip-hud-health'
);
if (node) {
node.textContent =
`HP: ${Engine.getHealth().toFixed(0)}`;
}
};
const PlayerNameHUD = new Module(
'Player Name',
'SkyWars',
'Displays the detected player name.',
{}
);
PlayerNameHUD.onRender = function () {
const node =
document.getElementById(
'vip-hud-name'
);
if (node) {
node.textContent =
`NAME: ${Engine.getPlayerName()}`;
}
};
const HighJump = new Module(
'High Jump',
'Movement',
'Uses the exposed jump speed field when available.',
{
settings: {
jumpSpeed: 15
}
}
);
HighJump.onEnable = function () {
const jump =
Engine.getJumpSpeed();
if (
Number.isFinite(jump) &&
State.originalJumpSpeed === null
) {
State.originalJumpSpeed = jump;
}
const changed =
Engine.setJumpSpeed(
this.settings.jumpSpeed
);
this.setStatus(
changed
? 'ON'
: 'WAIT',
changed
? `Jump: ${this.settings.jumpSpeed}`
: 'Jump field unavailable'
);
};
HighJump.onTick = function () {
if (!Client.gameDetected) return;
Engine.setJumpSpeed(
this.settings.jumpSpeed
);
};
HighJump.onDisable = function () {
if (
State.originalJumpSpeed !== null
) {
Engine.setJumpSpeed(
State.originalJumpSpeed
);
}
};
const Speed = new Module(
'Speed',
'Movement',
'Scales exposed horizontal velocity when available.',
{
settings: {
multiplier: 1.2
}
}
);
Speed.onTick = function () {
if (!Client.gameDetected) {
this.setStatus(
'WAIT',
'Waiting for player'
);
return;
}
const velocity =
Engine.getHorizontalVelocity();
if (!velocity) {
this.setStatus(
'WAIT',
'Velocity unavailable'
);
return;
}
const changed =
Engine.scaleHorizontalVelocity(
this.settings.multiplier
);
this.setStatus(
changed
? 'ON'
: 'WAIT',
changed
? `${this.settings.multiplier}x`
: 'Velocity unavailable'
);
};
const PerformanceMode = new Module(
'Performance Mode',
'Utility',
'Reduces extra visual processing by the client overlay.',
{}
);
PerformanceMode.onEnable = function () {
document.documentElement
.dataset.vipPerformance = '1';
};
PerformanceMode.onDisable = function () {
delete document.documentElement
.dataset.vipPerformance;
};
const AntiBlur = new Module(
'Anti Blur',
'Utility',
'Keeps the client UI crisp.',
{
defaultEnabled: true
}
);
// =========================================================
// UI
// =========================================================
const STYLE = `
#vip-client-gui {
position:fixed;
top:50%;
left:50%;
transform:translate(-50%,-50%);
width:min(900px,94vw);
height:min(600px,88vh);
display:none;
z-index:2147483646;
overflow:hidden;
background:rgba(8,9,14,.97);
color:#fff;
border:1px solid rgba(255,0,120,.8);
border-radius:16px;
box-shadow:
0 0 40px rgba(255,0,120,.25),
0 20px 80px rgba(0,0,0,.65);
font-family:Arial,Helvetica,sans-serif;
}
#vip-header {
height:70px;
display:flex;
align-items:center;
justify-content:space-between;
padding:0 20px;
background:
linear-gradient(
90deg,
#ff0055,
#8d00ff,
#00d4ff
);
}
#vip-title {
font-size:20px;
font-weight:900;
}
#vip-engine-status {
padding:6px 10px;
border-radius:999px;
background:rgba(0,0,0,.25);
font-size:10px;
font-weight:800;
}
#vip-layout {
display:flex;
height:calc(100% - 70px);
}
#vip-sidebar {
width:180px;
padding:12px;
background:rgba(0,0,0,.32);
overflow-y:auto;
}
.vip-tab {
padding:12px;
margin-bottom:6px;
border-radius:10px;
cursor:pointer;
color:#aaa;
font-size:13px;
font-weight:800;
}
.vip-tab:hover {
background:rgba(255,0,120,.12);
color:white;
}
.vip-tab.active {
background:
linear-gradient(
90deg,
rgba(255,0,85,.35),
rgba(140,0,255,.22)
);
color:white;
}
#vip-main {
flex:1;
min-width:0;
padding:16px;
overflow:auto;
}
.vip-grid {
display:none;
grid-template-columns:
repeat(2,minmax(0,1fr));
gap:12px;
}
.vip-grid.active {
display:grid;
}
.vip-card {
position:relative;
min-height:110px;
padding:14px;
border:1px solid rgba(255,255,255,.08);
border-radius:12px;
background:
linear-gradient(
145deg,
rgba(25,25,36,.95),
rgba(13,13,19,.95)
);
cursor:pointer;
transition:.15s;
}
.vip-card:hover {
transform:translateY(-2px);
border-color:
rgba(255,255,255,.25);
}
.vip-card.enabled {
border-color:#ff0055;
box-shadow:
0 0 18px rgba(255,0,85,.15);
}
.vip-card.waiting {
border-color:#ffaa00;
}
.vip-card.error {
border-color:#ff3030;
}
.vip-card-title {
width:70%;
margin-bottom:6px;
font-size:14px;
font-weight:900;
}
.vip-card-desc {
color:#858592;
font-size:11px;
line-height:1.4;
}
.vip-status {
position:absolute;
right:12px;
top:12px;
padding:4px 7px;
border-radius:999px;
background:#272733;
color:#888;
font-size:9px;
font-weight:900;
}
.vip-card.enabled .vip-status {
background:#ff0055;
color:white;
}
.vip-card.waiting .vip-status {
background:#8a5a00;
color:white;
}
.vip-card.error .vip-status {
background:#b00020;
color:white;
}
.vip-reason {
position:absolute;
right:12px;
bottom:10px;
max-width:60%;
color:#666;
font-size:8px;
text-align:right;
}
#vip-hud {
position:fixed;
top:12px;
left:12px;
z-index:2147483640;
display:none;
min-width:150px;
padding:10px 12px;
border:1px solid rgba(255,0,100,.4);
border-radius:10px;
background:rgba(8,8,14,.72);
color:white;
font:11px/1.5 monospace;
pointer-events:none;
}
#vip-crosshair {
position:fixed;
left:50%;
top:50%;
width:20px;
height:20px;
transform:translate(-50%,-50%);
z-index:2147483639;
display:none;
pointer-events:none;
}
#vip-crosshair::before,
#vip-crosshair::after {
content:"";
position:absolute;
left:50%;
top:50%;
background:#fff;
}
#vip-crosshair::before {
width:20px;
height:2px;
transform:translate(-50%,-50%);
}
#vip-crosshair::after {
width:2px;
height:20px;
transform:translate(-50%,-50%);
}
@media(max-width:700px) {
#vip-layout {
flex-direction:column;
}
#vip-sidebar {
width:100%;
display:flex;
overflow-x:auto;
}
.vip-tab {
min-width:110px;
margin-right:6px;
}
.vip-grid {
grid-template-columns:1fr;
}
}
`;
function buildHUD() {
if (
document.getElementById(
'vip-hud'
)
) {
return;
}
const hud =
document.createElement('div');
hud.id = 'vip-hud';
hud.innerHTML = `
<div id="vip-hud-fps">
FPS: 0
</div>
<div id="vip-hud-coords">
X: ? Y: ? Z: ?
</div>
<div id="vip-hud-health">
HP: ?
</div>
<div id="vip-hud-name">
NAME: ?
</div>
<div id="vip-ready">
WAITING
</div>
`;
document.body.appendChild(
hud
);
const crosshair =
document.createElement(
'div'
);
crosshair.id =
'vip-crosshair';
document.body.appendChild(
crosshair
);
}
function buildUI() {
if (
Client.uiBuilt ||
!document.body ||
!document.head
) {
return;
}
const style =
document.createElement(
'style'
);
style.id =
'vip-client-style';
style.textContent =
STYLE;
document.head.appendChild(
style
);
buildHUD();
const menu =
document.createElement(
'div'
);
menu.id =
'vip-client-gui';
const tabs =
Client.categories.map(
(category, index) => `
<div
class="vip-tab ${index === 0 ? 'active' : ''}"
data-category="${escapeHtml(category)}"
>
${escapeHtml(category)}
</div>
`
).join('');
const grids =
Client.categories.map(
(category, index) => {
const modules =
Client.modules
.filter(
module =>
module.category ===
category
)
.map(
module => `
<div
class="vip-card ${
module.enabled
? 'enabled'
: ''
}"
data-mod="${escapeHtml(module.name)}"
>
<div class="vip-card-title">
${escapeHtml(module.name)}
</div>
<div class="vip-card-desc">
${escapeHtml(module.description)}
</div>
<div class="vip-status">
${
module.enabled
? 'ON'
: 'OFF'
}
</div>
<div class="vip-reason">
${escapeHtml(module.reason)}
</div>
</div>
`
)
.join('');
return `
<section
class="vip-grid ${
index === 0
? 'active'
: ''
}"
data-grid="${escapeHtml(category)}"
>
${modules}
</section>
`;
}
).join('');
menu.innerHTML = `
<div id="vip-header">
<div id="vip-title">
${escapeHtml(Client.name)}
</div>
<div id="vip-engine-status">
WAITING FOR GAME
</div>
</div>
<div id="vip-layout">
<aside id="vip-sidebar">
${tabs}
</aside>
<main id="vip-main">
${grids}
</main>
</div>
`;
document.body.appendChild(
menu
);
setupTabs(menu);
setupModules(menu);
Client.uiBuilt = true;
refreshHUD();
}
function setupTabs(menu) {
menu.querySelectorAll(
'.vip-tab'
).forEach(tab => {
tab.addEventListener(
'click',
() => {
menu.querySelectorAll(
'.vip-tab'
).forEach(
item =>
item.classList.remove(
'active'
)
);
menu.querySelectorAll(
'.vip-grid'
).forEach(
grid =>
grid.classList.remove(
'active'
)
);
tab.classList.add(
'active'
);
const target =
menu.querySelector(
`[data-grid="${cssEscape(
tab.dataset.category
)}"]`
);
if (target) {
target.classList.add(
'active'
);
}
}
);
});
}
function setupModules(menu) {
menu.querySelectorAll(
'.vip-card'
).forEach(card => {
card.addEventListener(
'click',
() => {
const name =
card.dataset.mod;
const module =
Client.modules.find(
item =>
item.name ===
name
);
if (!module) return;
module.toggle();
}
);
});
}
function refreshHUD() {
const hud =
document.getElementById(
'vip-hud'
);
const crosshair =
document.getElementById(
'vip-crosshair'
);
if (hud) {
hud.style.display =
(
FPSCounter.enabled ||
Coordinates.enabled ||
HealthHUD.enabled ||
PlayerNameHUD.enabled ||
SkyWarsReady.enabled
)
? 'block'
: 'none';
}
if (crosshair) {
crosshair.style.display =
Crosshair.enabled
? 'block'
: 'none';
}
}
function refreshStatus() {
const node =
document.getElementById(
'vip-engine-status'
);
if (!node) return;
node.textContent =
Client.gameDetected
? 'SKYWARS CONNECTED'
: 'WAITING FOR GAME';
}
// =========================================================
// MENU KEY
// =========================================================
function toggleMenu(force) {
const menu =
document.getElementById(
'vip-client-gui'
);
if (!menu) return;
Client.menuOpen =
force === undefined
? !Client.menuOpen
: !!force;
menu.style.display =
Client.menuOpen
? 'block'
: 'none';
}
window.addEventListener(
'keydown',
event => {
const isComma =
event.key === ',' ||
event.code === 'Comma';
if (
isComma &&
!event.repeat
) {
toggleMenu();
event.preventDefault();
event.stopPropagation();
}
if (
event.key === 'Escape' &&
Client.menuOpen
) {
toggleMenu(false);
}
},
true
);
// =========================================================
// MAIN LOOP
// =========================================================
function gameLoop() {
Client.raf =
requestAnimationFrame(
gameLoop
);
Engine.scan();
for (
const module
of Client.modules
) {
module.onTick();
module.onRender();
}
refreshStatus();
refreshHUD();
const canvas =
getCanvas();
if (canvas) {
if (
Fullbright.enabled ||
SaturationBoost.enabled
) {
applyCanvasFilter();
}
}
}
// =========================================================
// DOM READY
// =========================================================
function init() {
log(
'Starting ' +
VERSION
);
loadConfig();
const start =
() => {
try {
buildUI();
for (
const module
of Client.modules
) {
if (
module.enabled
) {
module.setStatus(
Client.gameDetected
? 'ON'
: 'WAIT',
Client.gameDetected
? 'Active'
: 'Waiting for engine'
);
}
}
} catch (error) {
warn(
'UI initialization error:',
error
);
}
};
if (
document.readyState ===
'loading'
) {
document.addEventListener(
'DOMContentLoaded',
start,
{ once: true }
);
} else {
start();
}
window.MinefunVIP = {
version: VERSION,
client: Client,
engine: Engine,
modules: Client.modules,
openMenu() {
toggleMenu(true);
},
closeMenu() {
toggleMenu(false);
},
toggle(name) {
const module =
Client.modules.find(
item =>
item.name === name
);
if (!module) {
return false;
}
module.toggle();
return module.enabled;
},
scan() {
return Engine.scan();
}
};
gameLoop();
log(
"Loaded. Press ',' to open."
);
Client.ready = true;
}
init();
})();