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.

TabWhat it does
CloudBrowse community scripts. Apply runs + saves locally. Del removes your uploads. Download counts on cards.
LocalFiles on disk. Apply loads and runs. Del removes the file.

Quick start

  1. Create config/Wsa/scripts/hello.js (see below)
  2. In-game: .script reload — loads all scripts
  3. 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.

FieldTypeNotes
namestring, requiredShown in ClickGUI/HUD
categorystringCombat / Movement / Render / Player / Misc / Settings (default Misc)
descriptionstringTooltip text
bindintKeycode, 0 = none
settingsarraySee setting types below
onEnable / onDisablefunctionToggle callbacks
onTick / onUpdate / onPacket / onRender2D / onRender3Dfunction(e)Only while the module is enabled
onAttack / onKey / onStrafe / onJump / onKnockback / onWorld / onClick / onRightClick / onPost / onHitBlock / onMove / onSafeWalk / onWindowClickfunction(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

typeFieldsExample
boolvalue{name:"Fast", type:"bool", value:true}
numbervalue, min, max{name:"Range", type:"number", value:3.0, min:1.0, max:6.0}
intvalue, min, max{name:"Count", type:"int", value:2, min:0, max:10}
modevalue, options[]{name:"Mode", type:"mode", value:0, options:["A","B"]}
colorvalue (ARGB int){name:"Tint", type:"color", value:0xFF7C5CFF}
textvalue{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 ===.

EventTypeMembers
updatePRE / POSTgetYaw, getPitch, getNewYaw, getNewPitch, setRotation(yaw, pitch, priority) on PRE. Higher priority wins
tickPRE / POSTCancellable. Timers and once-per-tick work. Do not draw
packetSEND / RECEIVEgetPacket(), 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

NameWhat it is
mcMinecraft 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.

CallMeaning
inGame() name()World open, and your in-game name
x() y() z() renderX(partial) renderY renderZFeet 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

CallMeaning
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).

CallMeaning
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

CallMeaning
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.

MethodNotes
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.

CallMeaning
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 / setHudNumberarrayTextScale 1–2, arrayBgAlpha / bgAlpha 0–1, pillAlpha 0–1
getHudFlag / setHudFlagarrayAccentBar (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

CommandAction
.script listLoaded scripts + ON/OFF
.script reloadReload 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).

SymptomLikely causeFix
load failed: syntax errorES6+ syntaxUse var and function only; reload after save.
Handler never runsModule disabledEnable the script module, or use events.on for global listeners.
getType() === "PRE" falseJava wrapperString(e.getType()) == "PRE" with ==.
HUD invisibleWrong eventDraw in onRender2D; guard with player.inGame().
Colors wrong / negative32-bit intUse util.rgba(r,g,b,a) for ARGB.
Game freezesInfinite loop in tickNo busy loops in onTick; use util.timer().
eval missing APIsIsolated scopeOnly 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);
});