Wsamiaw docs / Scripting
Scripting
Wsamiaw embeds a JavaScript engine (Rhino). Each *.js file under
config/Wsa/scripts/ runs at boot, listens to engine events, and can register its own
ClickGUI modules with settings, keybinds, Cloud/Local sync, render drawing and packets.
Trust boundary. Scripts are not fully sandboxed — they can send packets and toggle modules. Only run code you wrote or fully trust.
Folder & Cloud / Local
config/Wsa/scripts/YourScript.js
In-game: Cloud tab → Scripts → Cloud / Local toggle, or chat with .script.
| Tab | What it does |
|---|---|
| Cloud | Browse community scripts. Apply runs + saves locally. Del removes your uploads. Download counts on cards. |
| Local | Files on disk. Apply loads and runs. Del removes the file. |
Quick start
- Create
config/Wsa/scripts/hello.js(see below) - In-game:
.script reload— loads all scripts - ClickGUI → your module appears under its category → enable
hello
var m = modules.register({
name: "HelloMod",
category: "Misc",
description: "Says hi",
settings: [
{name: "Range", type: "number", value: 3.0, min: 1.0, max: 6.0}
],
onEnable: function() { client.print("HelloMod on"); },
onDisable: function() { client.print("HelloMod off"); },
onTick: function(e) {
var aura = client.mod("KillAura");
if (aura !== null && aura.isEnabled()) {
chat("aura is on, range " + m.settingNum("Range"));
}
}
});
Script modules
modules.register(desc) creates a real cheat module: it shows in ClickGUI, HUD/ArrayList, keybinds and configs. Returns the module object.
| Field | Type | Notes |
|---|---|---|
name | string, required | Shown in ClickGUI/HUD |
category | string | Combat / Movement / Render / Player / Misc / Settings (default Misc) |
description | string | Tooltip text |
bind | int | Keycode, 0 = none |
settings | array | See setting types below |
onEnable / onDisable | function | Toggle callbacks |
onTick / onUpdate / onPacket / onRender2D / onRender3D | function(e) | Only while the module is enabled |
onAttack / onKey / onStrafe / onJump / onKnockback / onWorld / onClick / onRightClick / onPost / onHitBlock / onMove / onSafeWalk / onWindowClick | function(e) | Only while enabled. Global names are the lowercase forms: attack, key, strafe, and the rest |
Runtime: m.settingNum(name), m.settingBool(name), m.settingStr(name),
m.settingMode(name) (the label, e.g. "Fast"), m.settingOptions(name),
m.setSetting(name, value) (a mode accepts the index or the label),
m.isEnabled(), m.setEnabled(b).
modules.list() returns script-module names, modules.get(name) returns the module.
Setting names ignore case, spaces, and -.
Always use the typed getters — plain setting() returns a Java wrapper. Compare Java values with == / != (or String(x)), never === / !==.
Setting types
| type | Fields | Example |
|---|---|---|
bool | value | {name:"Fast", type:"bool", value:true} |
number | value, min, max | {name:"Range", type:"number", value:3.0, min:1.0, max:6.0} |
int | value, min, max | {name:"Count", type:"int", value:2, min:0, max:10} |
mode | value, options[] | {name:"Mode", type:"mode", value:0, options:["A","B"]} |
color | value (ARGB int) | {name:"Tint", type:"color", value:0xFF7C5CFF} |
text | value | {name:"Label", type:"text", value:"hi"} |
Event hooks
Global listeners (run even when no module is enabled): events.on(name, fn).
The name is lowercased. Module fields such as onTick run only while that module is enabled.
Compare e.getType() with String(e.getType()) == "PRE", not ===.
| Event | Type | Members |
|---|---|---|
update | PRE / POST | getYaw, getPitch, getNewYaw, getNewPitch, setRotation(yaw, pitch, priority) on PRE. Higher priority wins |
tick | PRE / POST | Cancellable. Timers and once-per-tick work. Do not draw |
packet | SEND / RECEIVE | getPacket(), setPacket, setCancelled(true). Test with instanceof |
render2d | — | getPartialTicks(). Screen-space render.* |
render3d | — | getPartialTicks(). blockBox, entityBox, line3d |
attack | — | getTarget(), setCancelled(true) |
key | — | getKey() LWJGL code |
strafe | — | get/setStrafe, get/setForward, get/setFriction |
knockback | — | get/setX, Y, Z. Setters also cancel vanilla velocity |
safewalk | — | isSafeWalk(), setSafeWalk(bool) |
windowclick | — | getWindowsId, getSlotId, getMouseButtonClicked, getMode, cancellable |
jump, world, click, rightclick, post, hitblock, move | — | Cancellable where noted in the reference. move has no fields |
events.on("packet", function(e) {
if (e.getType().toString() === "RECEIVE") {
var p = e.getPacket();
if (p instanceof Packages.net.minecraft.network.play.server.S02PacketChat) {
chat("chat packet seen");
}
}
});
Globals
| Name | What it is |
|---|---|
mc | Minecraft instance — mc.thePlayer, mc.theWorld, mc.gameSettings, … |
chat(msg) / client.say(msg) / player.say(msg) | Send a chat line to the server. Other players see it |
client.print(msg) | Local chat only. &c color codes work. Nothing is sent |
client.mod(name) | Any module (isEnabled(), setEnabled(b)) or null. Case-insensitive |
client.modules() | Every module name |
client.fps() / client.ping() / client.inGame() | FPS, tab-list ping (-1 if unknown), whether a world is open |
client.getScriptName() | This file's name without .js |
player.* / world.* / inventory.* / util.* / theme.* | Safe helpers. Empty or zero when you are not in a world. See the sections below |
modules.register(desc) / modules.get(name) / modules.list() | Script modules (see above) |
events.on(name, fn) | Global hooks. See the event table |
Packages.* | Full Java access, e.g. new Packages.net.minecraft.network.play.client.C01PacketChatMessage("hi") |
player
Reads return 0, "", or false on the main menu. distance and distanceTo return -1 when they cannot measure. y() is the feet.
| Call | Meaning |
|---|---|
inGame() name() | World open, and your in-game name |
x() y() z() renderX(partial) renderY renderZ | Feet position. The render* forms interpolate with e.getPartialTicks() |
motionX() motionY() motionZ() yaw() pitch() | Velocity and look |
health() maxHealth() absorption() food() armor() air() hurtTime() | 20 health is full. Food is 0–20. Air is 300 when full. hurtTime counts down after a hit |
onGround() sprinting() sneaking() | Movement flags |
heldSlot() heldItem() setSlot(0–8) | Hotbar index, registry id of the held stack ("" if empty). setSlot does not send C09 |
distance(x,y,z) distanceTo(name) | Blocks. -1 if not in game or the player is not loaded |
swing() jump() say(text) | Swing animation, vanilla jump, server chat |
world
| Call | Meaning |
|---|---|
loaded() time() dimension() | World time in ticks. Dimension 0 overworld, -1 nether, 1 end |
players() playerCount() playersNear(range) | Other players only. You are not in the list |
entity(name) | The player entity, or null. Pass it to render.entityBox |
block(x,y,z) air(x,y,z) | Registry id such as minecraft:stone. Coordinates are block coordinates |
inventory
Slots 0–8 hotbar, 9–35 main inventory, 36–39 armor (boots, leggings, chest, helmet).
| Call | Meaning |
|---|---|
item(slot) count(slot) size() | Registry id, stack size, inventory size |
find(id) findHotbar(id) total(id) | First slot or -1. id may be minecraft:ender_pearl or ender_pearl. total sums stack sizes |
var slot = inventory.findHotbar("ender_pearl");
if (slot != -1) player.setSlot(slot);
util
| Call | Meaning |
|---|---|
rgba(r,g,b,a) rgb(r,g,b) | ARGB int, channels 0–255. This is the color format render expects |
clamp(v,min,max) lerp(a,b,t) wrapDegrees(deg) | wrapDegrees returns a value in [-180, 180) |
ms() | Current time in milliseconds |
timer() | New stopwatch. elapsed(), hasPassed(ms), reset() |
render API
Call only during render2d / render3d. Colors are ARGB integers.
| Method | Notes |
|---|---|
render.rect(x1,y1,x2,y2,color) | Filled rectangle. Two corners, not x/y/width/height |
render.rounded(x,y,w,h,radius,color) | Rounded rectangle. This one is x, y, width, height |
render.outline(x1,y1,x2,y2,width,fill,line) | Filled rect plus a border. Corners, like rect |
render.line(x1,y1,x2,y2,width,color) | Screen-space line |
render.circle(x,y,radius,color) | Filled circle |
render.text(s,x,y,color) | Vanilla font with shadow |
render.textNoShadow(s,x,y,color) | Vanilla font, no shadow |
render.centerText(s,cx,y,color) | Horizontally centered text |
render.textWidth(s) | Pixel width for layout |
render.pill(x,y,w,h,bg,accent,text,textColor) | ArrayList-style pill row with accent bar |
render.image(path,x,y,w,h) | Draw classpath/resource image, e.g. assets/wsamiaw/logo.png |
render.push(x,y,scale,rotationDeg) / render.pop() | Transform stack for custom animations (scale + rotate around point) |
render.screenWidth() / render.screenHeight() | Scaled screen size for HUD layout |
render.time(), render.sin(v), render.cos(v) | Animation helpers (seconds, radians) |
render.blockBox(x,y,z,argb) render.blockOutline(x,y,z,argb,width) | World cube at a block. Call from render3d |
render.entityBox(entity,argb,width) | Wire box. Pass world.entity(name). Null draws nothing |
render.line3d(x1,y1,z1,x2,y2,z2,argb,width) | World-space line |
Custom HUD element
var hud = modules.register({
name: "MyHud", category: "Render",
settings: [
{name: "Scale", type: "number", value: 1.0, min: 0.5, max: 2.0}
],
onRender2D: function(e) {
var s = hud.settingNum("Scale");
var w = 120 * s, h = 18 * s;
var x = render.screenWidth() - w - 6, y = 40;
var a = 0.5 + 0.5 * render.sin(render.time() * 2.0);
var bg = 0xB0101014, accent = 0xFF7C5CFF;
render.pill(x, y, w, h, bg, accent, "MyHud " + Math.round(a * 100), 0xFFFFFFFF);
}
});
theme
Reads and writes the current theme. Color and metric changes are pushed to modules immediately. saveCurrent() writes current.json. save(name) also stores a named file.
| Call | Meaning |
|---|---|
list() current() load(name) reload() save(name) saveCurrent() | Theme files live in config/Wsa/themes. load returns false if the file is missing |
getBgAlpha() setBgAlpha(0..1) | ArrayList plate alpha |
getColor(key) setColor(key, value) | Value is an ARGB int or "#RRGGBB" / "#AARRGGBB" |
getMetric(key) setMetric(key, n) | radius 2–20, panelW 50–600, headerH 10–80, rowH 10–60, gap 0–30, fontSize |
getHudNumber / setHudNumber | arrayTextScale 1–2, arrayBgAlpha / bgAlpha 0–1, pillAlpha 0–1 |
getHudFlag / setHudFlag | arrayAccentBar (accentBar), arrayShadow (shadow) |
Color keys: bg, header, accent, accentHover, text, muted, switchOn, switchOff, arrayBg, panelBorder, panelHighlight, hoverBg. Unknown setColor keys are ignored. Unknown getColor returns white.
Packets
Inspect/cancel via the packet event; send via mc + Packages:
events.on("packet", function(e) {
var p = e.getPacket();
if (p instanceof Packages.net.minecraft.network.play.server.S02PacketChat) {
var text = p.getChatComponent().getUnformattedText();
if (text.indexOf("Victory") !== -1) chat("gg");
}
});
var C01 = Packages.net.minecraft.network.play.client.C01PacketChatMessage;
mc.getNetHandler().addToSendQueue(new C01("hello"));
mc.getNetHandler().addToSendQueue(
new Packages.net.minecraft.network.play.client.C03PacketPlayer(true));
Serverbound: C01 chat, C02 use entity, C03 player, C07 dig, C08 place, C09 held item, C0A swing, C0B action, C0D close, C0E click, C0F transaction, C10 creative, C13 abilities, C16 status. Clientbound: S02 chat, S04 equipment, S06 health, S08 pos look, S12 velocity, S13 destroy, S14 rel move, S18 teleport, S23 block change, S27 explosion, S29 sound, S2A particles, S45 title, S48 resource pack, …
Commands
| Command | Action |
|---|---|
.script list | Loaded scripts + ON/OFF |
.script reload | Reload all scripts |
.script load <name> | Load one file |
.script unload <name> | Unload (removes its modules) |
.script eval <js...> | Run a snippet immediately |
Aliases: .scripts, .js
Troubleshooting
When something breaks, check chat for [script] lines and run .script list (load errors) or .script folder (path).
| Symptom | Likely cause | Fix |
|---|---|---|
load failed: syntax error | ES6+ syntax | Use var and function only; reload after save. |
| Handler never runs | Module disabled | Enable the script module, or use events.on for global listeners. |
getType() === "PRE" false | Java wrapper | String(e.getType()) == "PRE" with ==. |
| HUD invisible | Wrong event | Draw in onRender2D; guard with player.inGame(). |
| Colors wrong / negative | 32-bit int | Use util.rgba(r,g,b,a) for ARGB. |
| Game freezes | Infinite loop in tick | No busy loops in onTick; use util.timer(). |
eval missing APIs | Isolated scope | Only mc exists in eval — use a .js file. |
New helpers: events.once, events.off, client.server(), client.scriptsFolder(), world.solid/replaceable, util.distance/randomInt, .script folder.
Security
Trust boundary. Scripts are not sandboxed — through Packages they can touch any Java/Minecraft API, send packets and toggle modules. Only run code you wrote or fully trust. A throwing handler is reported in local chat and the script keeps running; unload it with .script unload.
chat(), client.say(), and player.say() are visible to the server. client.print() stays on your client. When you are not in a world, player, world, and inventory return empty values instead of throwing. mc.thePlayer does not — check it, or use player.inGame().
Examples
These are documentation samples. Copy one into config/Wsa/scripts/ and run .script reload. They are not shipped inside the client.
Billiards
Drag behind the cue ball and release. Enabling the module frees the cursor. Esc closes the table.
// Billiards — drag behind the cue ball and release to shoot.
// Enable the module. Esc, or disabling it, closes the table.
var game = modules.register({
name: "Billiards",
category: "Render",
description: "Drag behind the cue ball, release to shoot",
onEnable: function() { ui.show(); rack(); },
onDisable: function() { ui.close(); }
});
var balls = [];
var pocketed = 0;
var inHand = false;
var dragging = false;
var ox = 0, oy = 0, fw = 0, fh = 0;
var lastMs = 0;
var BR = 7;
function rack() {
balls = [];
pocketed = 0;
inHand = false;
dragging = false;
lastMs = util.ms();
var box = table();
ox = box.x; oy = box.y; fw = box.w; fh = box.h;
var colors = [
util.rgb(240, 210, 60),
util.rgb(40, 90, 200),
util.rgb(190, 40, 40),
util.rgb(120, 40, 160),
util.rgb(230, 120, 30),
util.rgb(20, 20, 20)
];
balls.push({x: box.x + box.w * 0.28, y: box.y + box.h * 0.5, vx: 0, vy: 0, color: util.rgb(245, 245, 245), cue: true, alive: true});
var i, row, col, n = 0;
var startX = box.x + box.w * 0.68;
var startY = box.y + box.h * 0.5;
for (row = 0; row < 3; row++) {
for (col = 0; col <= row; col++) {
balls.push({
x: startX + row * (BR * 2 + 1),
y: startY + (col - row / 2) * (BR * 2 + 1),
vx: 0, vy: 0,
color: colors[n % colors.length],
cue: false,
alive: true
});
n++;
}
}
}
function table() {
var sw = render.screenWidth();
var sh = render.screenHeight();
var w = Math.min(540, sw - 80);
var h = Math.min(w * 0.56, sh - 90);
return {x: (sw - w) / 2, y: (sh - h) / 2 + 6, w: w, h: h};
}
function fit() {
var box = table();
if (fw < 1) {
ox = box.x; oy = box.y; fw = box.w; fh = box.h;
return box;
}
if (Math.abs(box.w - fw) > 1 || Math.abs(box.h - fh) > 1) {
var i;
for (i = 0; i < balls.length; i++) {
var b = balls[i];
var u = (b.x - ox) / fw;
var v = (b.y - oy) / fh;
b.x = box.x + u * box.w;
b.y = box.y + v * box.h;
}
} else {
var dx = box.x - ox;
var dy = box.y - oy;
var j;
for (j = 0; j < balls.length; j++) {
balls[j].x += dx;
balls[j].y += dy;
}
}
ox = box.x; oy = box.y; fw = box.w; fh = box.h;
return box;
}
function pockets(box) {
var r = BR * 1.85;
var x = box.x, y = box.y, w = box.w, h = box.h;
return [
{x: x, y: y}, {x: x + w / 2, y: y}, {x: x + w, y: y},
{x: x, y: y + h}, {x: x + w / 2, y: y + h}, {x: x + w, y: y + h}
];
}
function speed(b) {
return Math.sqrt(b.vx * b.vx + b.vy * b.vy);
}
function asleep() {
var i;
for (i = 0; i < balls.length; i++) {
if (balls[i].alive && speed(balls[i]) > 14) return false;
}
return true;
}
function cue() {
var i;
for (i = 0; i < balls.length; i++) if (balls[i].cue && balls[i].alive) return balls[i];
return null;
}
function step(dt) {
var box = {x: ox, y: oy, w: fw, h: fh};
var holes = pockets(box);
var sub = 8;
var h = dt / sub;
var s, i, j;
for (s = 0; s < sub; s++) {
for (i = 0; i < balls.length; i++) {
var b = balls[i];
if (!b.alive) continue;
b.x += b.vx * h;
b.y += b.vy * h;
var damp = Math.exp(-1.7 * h);
b.vx *= damp;
b.vy *= damp;
if (speed(b) < 8) { b.vx = 0; b.vy = 0; }
if (b.x < box.x + BR) { b.x = box.x + BR; b.vx = Math.abs(b.vx) * 0.86; }
if (b.x > box.x + box.w - BR) { b.x = box.x + box.w - BR; b.vx = -Math.abs(b.vx) * 0.86; }
if (b.y < box.y + BR) { b.y = box.y + BR; b.vy = Math.abs(b.vy) * 0.86; }
if (b.y > box.y + box.h - BR) { b.y = box.y + box.h - BR; b.vy = -Math.abs(b.vy) * 0.86; }
}
for (i = 0; i < balls.length; i++) {
for (j = i + 1; j < balls.length; j++) {
var a = balls[i], c = balls[j];
if (!a.alive || !c.alive) continue;
var dx = c.x - a.x, dy = c.y - a.y;
var dist = Math.sqrt(dx * dx + dy * dy);
var min = BR * 2;
if (dist >= min || dist < 0.001) continue;
var nx = dx / dist, ny = dy / dist;
var overlap = (min - dist) / 2;
a.x -= nx * overlap; a.y -= ny * overlap;
c.x += nx * overlap; c.y += ny * overlap;
var rel = (a.vx - c.vx) * nx + (a.vy - c.vy) * ny;
if (rel > 0) {
a.vx -= rel * nx; a.vy -= rel * ny;
c.vx += rel * nx; c.vy += rel * ny;
}
}
}
for (i = 0; i < balls.length; i++) {
var ball = balls[i];
if (!ball.alive) continue;
var p;
for (p = 0; p < holes.length; p++) {
var hx = ball.x - holes[p].x, hy = ball.y - holes[p].y;
if (hx * hx + hy * hy < (BR * 1.55) * (BR * 1.55)) {
ball.alive = false;
ball.vx = 0; ball.vy = 0;
if (ball.cue) inHand = true;
else pocketed++;
break;
}
}
}
}
}
function shoot() {
var c = cue();
if (c == null) return;
var dx = c.x - input.mouseX();
var dy = c.y - input.mouseY();
var len = Math.sqrt(dx * dx + dy * dy);
if (len < 6) return;
var power = Math.min(len, 150) / 150 * 780;
c.vx = dx / len * power;
c.vy = dy / len * power;
}
function inside(box, x, y) {
return x > box.x + BR && y > box.y + BR && x < box.x + box.w - BR && y < box.y + box.h - BR;
}
events.on("guiclose", function() {
if (game.isEnabled()) game.setEnabled(false);
});
events.on("mouse", function(e) {
if (!game.isEnabled() || !ui.isOpen() || e.button != 0) return;
var box = table();
if (e.pressed) {
if (input.hover(box.x + box.w - 62, box.y - 22, 62, 16)) { rack(); return; }
if (inHand && inside(box, e.x, e.y)) {
var c = cue();
if (c != null) { c.alive = true; c.x = e.x; c.y = e.y; c.vx = 0; c.vy = 0; inHand = false; }
return;
}
if (asleep() && cue() != null) dragging = true;
} else if (dragging) {
shoot();
dragging = false;
}
});
events.on("render2d", function() {
if (!game.isEnabled()) return;
var now = util.ms();
var dt = (now - lastMs) / 1000;
lastMs = now;
if (dt > 0.05) dt = 0.05;
if (dt < 0) dt = 0;
if (!dragging && !inHand) step(dt);
var box = fit();
var holes = pockets(box);
render.rounded(box.x - 16, box.y - 28, box.w + 32, box.h + 44, 16, util.rgba(18, 16, 14, 210));
render.rounded(box.x - 8, box.y - 8, box.w + 16, box.h + 16, 12, util.rgba(92, 58, 32, 255));
render.rounded(box.x, box.y, box.w, box.h, 8, util.rgba(18, 92, 58, 255));
var p;
for (p = 0; p < holes.length; p++) {
render.circle(holes[p].x, holes[p].y, BR * 1.7, util.rgba(8, 8, 10, 255));
}
var i;
for (i = 0; i < balls.length; i++) {
var b = balls[i];
if (!b.alive) continue;
render.circle(b.x + 1.2, b.y + 1.6, BR, util.rgba(0, 0, 0, 70));
render.circle(b.x, b.y, BR, b.color);
render.circle(b.x - 2, b.y - 2, BR * 0.28, util.rgba(255, 255, 255, 90));
}
var c = cue();
if (dragging && c != null) {
var mx = input.mouseX(), my = input.mouseY();
var dx = c.x - mx, dy = c.y - my;
var len = Math.sqrt(dx * dx + dy * dy);
if (len > 1) {
var ux = (mx - c.x) / len, uy = (my - c.y) / len;
var pull = Math.min(len, 150);
render.line(c.x - ux * BR, c.y - uy * BR, c.x - ux * 90, c.y - uy * 90, 1.2, util.rgba(255, 255, 255, 90));
render.line(c.x + ux * (BR + 3), c.y + uy * (BR + 3), c.x + ux * (BR + 28 + pull * 0.35), c.y + uy * (BR + 28 + pull * 0.35), 3, util.rgb(196, 150, 90));
render.rounded(box.x, box.y + box.h + 10, box.w * (pull / 150), 4, 2, util.rgb(230, 200, 90));
}
}
var label = inHand ? "click the felt to place the cue" : (asleep() ? "drag behind the cue, release to shoot" : "rolling");
render.text(label, box.x, box.y - 20, util.rgb(235, 230, 220));
render.rounded(box.x + box.w - 62, box.y - 22, 62, 16, 5, input.hover(box.x + box.w - 62, box.y - 22, 62, 16) ? util.rgba(255, 255, 255, 40) : util.rgba(0, 0, 0, 80));
render.text("reset", box.x + box.w - 50, box.y - 18, util.rgb(255, 255, 255));
render.text(pocketed + " pocketed", box.x + box.w - 130, box.y + box.h + 16, util.rgb(210, 205, 190));
});
Keystrokes
WASD, space, mouse buttons, and CPS. Each key eases in instead of popping.
// Keystrokes — WASD, space, mouse buttons, and left-click CPS.
// The keys ease in and out instead of popping.
var hud = modules.register({
name: "Keystrokes",
category: "Render",
description: "WASD, mouse buttons, and CPS",
settings: [
{name: "X", type: "number", value: 12, min: 0, max: 1000},
{name: "Y", type: "number", value: 80, min: 0, max: 1000},
{name: "Scale", type: "number", value: 1, min: 0.6, max: 1.8}
]
});
var press = {W: 0, A: 0, S: 0, D: 0, SPACE: 0, LMB: 0, RMB: 0};
var clicks = [];
var lastMs = 0;
events.on("mouse", function(e) {
if (!hud.isEnabled() || e.button != 0 || !e.pressed) return;
clicks.push(util.ms());
});
function fade(name, down, dt) {
var target = down ? 1 : 0;
var speed = down ? 18 : 12;
press[name] = press[name] + (target - press[name]) * Math.min(1, dt * speed);
}
function keyBox(x, y, w, h, label, amount) {
var bg = util.rgba(12, 12, 16, 150 + amount * 70);
var fg = amount > 0.45 ? util.rgb(255, 255, 255) : util.rgb(176, 176, 186);
render.rounded(x, y, w, h, 5, bg);
if (amount > 0.04) {
render.rounded(x, y, 2, h, 1, util.rgba(124, 92, 255, amount));
}
render.centerText(label, x + w / 2, y + (h - 8) / 2, fg);
}
events.on("render2d", function() {
if (!hud.isEnabled()) return;
var now = util.ms();
var dt = lastMs == 0 ? 0.016 : (now - lastMs) / 1000;
lastMs = now;
if (dt > 0.05) dt = 0.05;
if (dt < 0) dt = 0;
var next = [];
var i;
for (i = 0; i < clicks.length; i++) if (now - clicks[i] < 1000) next.push(clicks[i]);
clicks = next;
fade("W", input.keyDown(input.key("W")), dt);
fade("A", input.keyDown(input.key("A")), dt);
fade("S", input.keyDown(input.key("S")), dt);
fade("D", input.keyDown(input.key("D")), dt);
fade("SPACE", input.keyDown(input.key("SPACE")), dt);
fade("LMB", input.mouseDown(0), dt);
fade("RMB", input.mouseDown(1), dt);
var s = hud.settingNum("Scale");
var x = hud.settingNum("X");
var y = hud.settingNum("Y");
var u = 22 * s;
var g = 3 * s;
keyBox(x + u + g, y, u, u, "W", press.W);
keyBox(x, y + u + g, u, u, "A", press.A);
keyBox(x + u + g, y + u + g, u, u, "S", press.S);
keyBox(x + (u + g) * 2, y + u + g, u, u, "D", press.D);
keyBox(x, y + (u + g) * 2, u * 3 + g * 2, u * 0.7, "space", press.SPACE);
var row = y + (u + g) * 2 + u * 0.7 + g;
var half = (u * 3 + g * 2 - g) / 2;
keyBox(x, row, half, u * 0.85, "LMB", press.LMB);
keyBox(x + half + g, row, half, u * 0.85, "RMB", press.RMB);
render.text(clicks.length + " CPS", x, row + u * 0.85 + 4, util.rgb(210, 210, 220));
});
Armor
Durability bars for boots, leggings, chest, and helmet. The bar shifts from green toward red as the piece wears down.
// Armor — durability for boots, leggings, chest, and helmet.
// The bar goes from green to red as the piece wears down.
var hud = modules.register({
name: "ArmorStatus",
category: "Render",
description: "Armor durability bars",
settings: [
{name: "X", type: "number", value: 8, min: 0, max: 1000},
{name: "Y", type: "number", value: 180, min: 0, max: 1000}
]
});
var LABELS = ["Boots", "Legs", "Chest", "Helm"];
var SLOTS = [36, 37, 38, 39];
events.on("render2d", function() {
if (!hud.isEnabled() || !player.inGame()) return;
var x = hud.settingNum("X");
var y = hud.settingNum("Y");
var i;
var shown = 0;
for (i = 0; i < SLOTS.length; i++) {
var max = inventory.maxDamage(SLOTS[i]);
if (max <= 0) continue;
var left = max - inventory.damage(SLOTS[i]);
if (left < 0) left = 0;
var frac = left / max;
var row = y + shown * 16;
var name = inventory.displayName(SLOTS[i]);
if (name == "") name = LABELS[i];
var color = util.rgb((1 - frac) * 220, frac * 200, 70);
render.rounded(x, row, 108, 14, 4, util.rgba(12, 12, 16, 160));
render.rounded(x + 2, row + 10, 104 * frac, 2, 1, color);
render.text(name, x + 4, row + 1, util.rgb(235, 235, 240));
render.text(Math.round(frac * 100) + "%", x + 78, row + 1, color);
shown++;
}
if (shown == 0) {
render.text("no armor", x, y, util.rgb(160, 160, 170));
}
});
Session
Session clock, facing, coordinates, ping, fps, hits taken, and nearby players.
// Session — clock, facing, coordinates, ping, and how many hits you have taken.
var hud = modules.register({
name: "Session",
category: "Render",
description: "Session clock, coords, facing, hits taken",
settings: [
{name: "X", type: "number", value: 8, min: 0, max: 1000},
{name: "Y", type: "number", value: 28, min: 0, max: 1000}
]
});
var clock = util.timer();
var hits = 0;
var hurting = false;
function facing() {
var yaw = player.yaw() % 360;
if (yaw < 0) yaw += 360;
var names = ["S", "SW", "W", "NW", "N", "NE", "E", "SE"];
var index = Math.floor((yaw + 22.5) / 45) % 8;
return names[index];
}
function clockText() {
var sec = Math.floor(clock.elapsed() / 1000);
var m = Math.floor(sec / 60);
var s = sec % 60;
var mm = m < 10 ? "0" + m : "" + m;
var ss = s < 10 ? "0" + s : "" + s;
return mm + ":" + ss;
}
events.on("render2d", function() {
if (!hud.isEnabled()) return;
var hurt = player.hurtTime() > 0;
if (hurt && !hurting) hits++;
hurting = hurt;
var x = hud.settingNum("X");
var y = hud.settingNum("Y");
var lines = [
"session " + clockText(),
player.inGame() ? (facing() + " " + player.x().toFixed(1) + " " + player.y().toFixed(1) + " " + player.z().toFixed(1)) : "not in a world",
"ping " + client.ping() + " fps " + client.fps(),
"hits taken " + hits + " nearby " + (player.inGame() ? world.playerCount() : 0)
];
var width = 0;
var i;
for (i = 0; i < lines.length; i++) width = Math.max(width, render.textWidth(lines[i]));
render.rounded(x, y, width + 14, lines.length * 11 + 8, 6, util.rgba(14, 14, 18, 170));
for (i = 0; i < lines.length; i++) {
render.text(lines[i], x + 7, y + 5 + i * 11, i == 0 ? theme.getColor("accent") : util.rgb(230, 230, 235));
}
});
Quick menu
Clickable module list. Type to filter, scroll to move, click a row to toggle. Esc closes it.
// QuickMenu — a clickable module list. Type to filter, scroll to move, click to toggle.
// Enable the module. Esc closes it.
var menu = modules.register({
name: "QuickMenu",
category: "Render",
description: "Click a module to toggle it",
onEnable: function() { ui.show(); },
onDisable: function() { ui.close(); }
});
var query = "";
var scroll = 0;
var ROW = 16;
var VISIBLE = 12;
events.on("guiclose", function() {
if (menu.isEnabled()) menu.setEnabled(false);
});
function shown() {
var names = client.modules();
var out = [];
var q = query.toLowerCase();
var i;
for (i = 0; i < names.length; i++) {
var name = String(names[i]);
if (q == "" || name.toLowerCase().indexOf(q) != -1) out.push(name);
}
return out;
}
events.on("guikey", function(e) {
if (!menu.isEnabled()) return;
if (e.code == 14) {
if (query.length > 0) query = query.substring(0, query.length - 1);
scroll = 0;
return;
}
var ch = String(e.character);
if (ch.length != 1) return;
var code = ch.charCodeAt(0);
if (code < 32 || code > 126) return;
if (query.length < 20) query += ch;
scroll = 0;
});
events.on("mouse", function(e) {
if (!menu.isEnabled() || !ui.isOpen()) return;
var rows = shown();
if (e.button == -1) {
scroll -= e.wheel > 0 ? 1 : -1;
if (scroll < 0) scroll = 0;
var max = rows.length - VISIBLE;
if (max < 0) max = 0;
if (scroll > max) scroll = max;
return;
}
if (e.button != 0 || !e.pressed) return;
var box = panel();
var i;
for (i = 0; i < VISIBLE && scroll + i < rows.length; i++) {
var ry = box.y + 28 + i * ROW;
if (e.x >= box.x + 6 && e.x <= box.x + box.w - 6 && e.y >= ry && e.y <= ry + ROW - 2) {
var mod = client.mod(rows[scroll + i]);
if (mod != null && rows[scroll + i] != "QuickMenu") mod.setEnabled(!mod.isEnabled());
return;
}
}
});
function panel() {
var sw = render.screenWidth();
var sh = render.screenHeight();
var w = 220;
var h = 28 + VISIBLE * ROW + 8;
return {x: (sw - w) / 2, y: (sh - h) / 2, w: w, h: h};
}
events.on("render2d", function() {
if (!menu.isEnabled()) return;
var box = panel();
var rows = shown();
var max = rows.length - VISIBLE;
if (max < 0) max = 0;
if (scroll > max) scroll = max;
render.rounded(box.x, box.y, box.w, box.h, 10, util.rgba(14, 14, 18, 210));
var title = query == "" ? "modules" : query;
render.text(title, box.x + 10, box.y + 8, theme.getColor("accent"));
render.text(rows.length + "", box.x + box.w - 22, box.y + 8, util.rgb(160, 160, 170));
var i;
for (i = 0; i < VISIBLE && scroll + i < rows.length; i++) {
var name = rows[scroll + i];
var ry = box.y + 28 + i * ROW;
var mod = client.mod(name);
var on = mod != null && mod.isEnabled();
var hot = input.hover(box.x + 6, ry, box.w - 12, ROW - 2);
if (hot || on) {
render.rounded(box.x + 6, ry, box.w - 12, ROW - 2, 4, on ? util.rgba(124, 92, 255, hot ? 70 : 40) : util.rgba(255, 255, 255, 18));
}
render.text(name, box.x + 12, ry + 3, on ? util.rgb(255, 255, 255) : util.rgb(186, 186, 196));
}
});
AutoGG
events.on("packet", function(e) {
if (e.getType().toString() !== "RECEIVE") return;
var p = e.getPacket();
var S02 = Packages.net.minecraft.network.play.server.S02PacketChat;
if (p instanceof S02) {
if (p.getChatComponent().getUnformattedText().indexOf("Victory") !== -1) chat("gg");
}
});
Toggle HUD
var m = modules.register({
name: "HudToggle", category: "Render",
onEnable: function() { client.mod("HUD").setEnabled(true); },
onDisable: function() { client.mod("HUD").setEnabled(false); }
});
Aim readout
events.on("render2d", function(e) {
var p = mc.thePlayer;
if (p !== null) render.text("yaw " + p.rotationYaw.toFixed(1), 4, 4, 0xFFFFFFFF);
});