Getting Started
What is a DeathClient JavaScript plugin?
A DeathClient plugin is a .js file executed by DeathClient's
built-in JavaScript runtime. Plugins can register mods, settings, local
commands, HUD modules, event handlers, runtime models, client-side entities,
runtime items, textures, storage, timers, sounds, and player/world actions.
The JavaScript API is exposed as window.DeathClient.
The current bridge identifies itself as JavaScript bridge version
1.5.0 and API version 3.0.0.
dc.getAllMods(),
dc.pickResource(), remote resource fetch helpers, or
dc.storage.clear().
Your first plugin
const dc = window.DeathClient;
dc.createMod({
name: "Hello World",
displayName: "Hello World",
description: "My first DeathClient plugin",
category: "PLAYER",
isCheat: false,
onEnable: function() {
dc.chat("§aHello from my plugin!");
},
onUpdate: function() {
// Called by DeathClient's normal mod update path.
}
});
Basic plugin workflow
- Get the API with
const dc = window.DeathClient;. - Register one or more mods with
dc.createMod(). - Add settings, callbacks, commands, or other APIs as needed.
- Use client-side APIs such as
dc.chat(),dc.player,dc.storage, and the advanced runtime systems.
JavaScript Basics
Only normal JavaScript is required for the core API.
Variables
let coins = 10;
let playerName = "Steve";
let enabled = true;
Conditions
if (dc.player.health < 5) {
dc.chat("§cLow health!");
}
Functions
function sayHello(name) {
dc.chat("Hello " + name);
}
sayHello("Steve");
Loops
for (let i = 0; i < 5; i++) {
dc.chat("Count: " + i);
}
Objects
const config = {
damage: 10,
enabled: true,
mode: "normal"
};
dc.log(config.mode);
Useful operators
| Operator | Example | Meaning |
|---|---|---|
=== | x === 10 | Exactly equal. |
!== | x !== 10 | Not equal. |
> | x > 10 | Greater than. |
< | x < 10 | Less than. |
&& | a && b | Both conditions must be true. |
|| | a || b | At least one condition is true. |
! | !enabled | Invert a boolean. |
Plugin Structure
A single plugin file can contain multiple mods, HUDs, commands, global events, settings, runtime assets, and helper functions.
const dc = window.DeathClient;
// Shared state
const state = {
count: 0
};
// Main mod
dc.createMod({
name: "Example",
description: "Example plugin",
category: "PLAYER",
settings: [],
onEnable: function(settings) {},
onDisable: function(settings) {},
onUpdate: function(settings) {},
onChat: function(message) {}
});
// Local command
dc.createCommand({
name: "example",
prefix: ".",
execute: function(args) {}
});
name, not command,
when passing the object to dc.createCommand().
Mod Registration CORE
dc.createMod(config)
| Property | Type | Description |
|---|---|---|
name | String | Required internal mod name. |
displayName | String | Optional GUI display name. Defaults to name. |
description | String | Description shown for the mod. |
category | String | Common categories include PLAYER, MOVEMENT, COMBAT, RENDER, WORLD, HUD. |
isCheat | Boolean | Marks the module as a cheat in the mod system. |
settings | Array | Settings created with dc.createSetting(). |
onEnable | Function | Runs when the Java-side module is enabled. |
onDisable | Function | Runs when the Java-side module is disabled. |
onUpdate | Function | Called from the Java mod update path. |
onRender2D | Function | Called from the 2D rendering path when wired by the client. |
onChat | Function | Receives chat text delivered to the JS mod. |
Example
dc.createMod({
name: "Welcome",
displayName: "Welcome",
description: "Shows a message when enabled.",
category: "PLAYER",
isCheat: false,
onEnable: function() {
dc.chat("§aWelcome!");
},
onDisable: function() {
dc.chat("§cGoodbye!");
}
});
Settings CORE
Settings are serialized into the mod registration payload and synchronized into
the mod's settingsCache.
Toggle / Boolean
const enabled = dc.createSetting(
"Toggle",
"Enabled",
true
);
Slider / Number
const delay = dc.createSetting(
"Slider",
"Delay",
50,
0,
1000,
1
);
Mode
const mode = dc.createSetting(
"Mode",
"Mode",
"Normal",
["Normal", "Aggressive", "Passive"]
);
String
const message = dc.createSetting(
"String",
"Message",
"Hello!"
);
Complete example
dc.createMod({
name: "Message Mod",
settings: [
dc.createSetting("Toggle", "Spam", false),
dc.createSetting("Slider", "Delay", 1000, 100, 5000, 100),
dc.createSetting("Mode", "Style",
"Friendly",
["Friendly", "Funny", "Serious"]
),
dc.createSetting("String", "Message", "Hello!")
],
onUpdate: function(settings) {
if (!settings["Spam"].value) {
return;
}
const delay = settings["Delay"].value;
const style = settings["Style"].value;
const message = settings["Message"].value;
// Plugin logic here.
}
});
Commands CURRENT
DeathClient commands are local client commands. They are intercepted before ordinary chat handling when the typed message begins with the command prefix.
dc.registerCommand(name, prefix, execute)
dc.registerCommand(
"hello",
".",
function(args) {
dc.chat("§aHello!");
dc.chat("Arguments: §f" + args);
}
);
dc.createCommand(config)
This is the object-style equivalent.
dc.createCommand({
name: "hello",
prefix: ".",
execute: function(args) {
dc.chat("§aHello " + (args || "world"));
}
});
Typing:
.hello test something
passes this string to the callback:
args === "test something"
Command with multiple arguments
dc.createCommand({
name: "teleport",
prefix: ".",
execute: function(args) {
const parts = String(args || "").trim().split(/\s+/);
if (parts.length < 3) {
dc.chat("§cUsage: .teleport <x> <y> <z>");
return;
}
const x = Number(parts[0]);
const y = Number(parts[1]);
const z = Number(parts[2]);
if (!Number.isFinite(x) ||
!Number.isFinite(y) ||
!Number.isFinite(z)) {
dc.chat("§cInvalid coordinates.");
return;
}
dc.player.x = x;
dc.player.y = y;
dc.player.z = z;
}
});
Unregistering the JavaScript callback
dc.unregisterCommand("hello");
"." responds to .hello.
Callbacks CORE
| Callback | Purpose |
|---|---|
onEnable(settings) | Runs when the mod is enabled. |
onDisable(settings) | Runs when the mod is disabled. |
onUpdate(settings) | Runs from the normal mod update path. |
onRender2D(settings) | Runs from the 2D render path when used by the client. |
onChat(message) | Receives incoming chat text. |
HUD Mods CORE
dc.createHudMod(config)
dc.createHudMod({
name: "My HUD",
displayName: "My HUD",
description: "A custom HUD element",
category: "HUD",
width: 120,
height: 24,
onRender2D: function() {
// HUD position is exposed through this.x / this.y / this.scale.
}
});
| HUD property | Description |
|---|---|
this.x | Current X position. |
this.y | Current Y position. |
this.scale | Current HUD scale. |
drawString()
helper.
Chat API CORE
| API | Description |
|---|---|
dc.chat(message) | Displays local client-side chat text. It is not sent to the server. |
dc.sendChat(message) | Sends chat text through the normal client send-chat path. |
dc.sendCommand(command) | Sends a slash command. A leading / is added automatically. |
dc.chat("§aLocal message");
dc.sendChat("hello server");
dc.sendCommand("spawn");
dc.sendCommand("/spawn");
Mod Control CORE
| API | Description |
|---|---|
dc.enableMod(name) | Requests that a mod be enabled. |
dc.disableMod(name) | Requests that a mod be disabled. |
dc.toggleMod(name) | Toggles a mod. |
dc.isEnabled(name) | Reads the JavaScript-side toggle state. |
dc.getMods() | Returns names from the JavaScript mod registry. |
dc.getMod(name) | Returns the JavaScript mod object or null. |
dc.createCommand({
name: "flight",
prefix: ".",
execute: function() {
if (dc.isEnabled("Fly")) {
dc.disableMod("Fly");
dc.chat("§cFly disabled.");
} else {
dc.enableMod("Fly");
dc.chat("§aFly enabled.");
}
}
});
Player & World CORE
Player properties
| Property | Read | Write |
|---|---|---|
dc.player.x | Yes | Yes |
dc.player.y | Yes | Yes |
dc.player.z | Yes | Yes |
dc.player.motionX | Yes | Yes |
dc.player.motionY | Yes | Yes |
dc.player.motionZ | Yes | Yes |
dc.player.yaw | Yes | Yes |
dc.player.pitch | Yes | Yes |
dc.player.name | Yes | No |
dc.player.health | Yes | No |
dc.player.maxHealth | Yes | No |
dc.player.onGround | Yes | No |
Jump
dc.player.jump();
Movement
dc.player.motionX = 1.0;
dc.player.motionY = 0.0;
dc.player.motionZ = 0.0;
Rotation
dc.player.yaw += 45;
dc.player.pitch = 10;
World properties
| Property | Read | Write |
|---|---|---|
dc.world.time | Yes | Yes |
dc.world.raining | Yes | No |
dc.world.time = 6000;
Events CORE
dc.on(event, callback)
dc.on("chat_receive", function(data) {
dc.chat("Received: " + data.message);
});
dc.off(event, callback)
function handleChat(data) {
dc.log(data.message);
}
dc.on("chat_receive", handleChat);
dc.off("chat_receive", handleChat);
dc.once(event, callback)
dc.once("chat_receive", function(data) {
dc.chat("This callback runs once.");
});
dc.emit(event, data)
Plugins can emit local JavaScript events to listeners registered through the same JavaScript event registry.
dc.on("my_event", function(data) {
dc.log("Value: " + data.value);
});
dc.emit("my_event", {
value: 42
});
Event names used by the current system
| Event | Payload | Description |
|---|---|---|
tick | State object | Client tick event when emitted by the Java side. |
chat_receive | { message } | Incoming chat text. |
mod_enable | Module data | Module enable event when emitted. |
mod_disable | Module data | Module disable event when emitted. |
| Custom names | Any value | Usable entirely within the JavaScript event system. |
dc.on(), dc.off(), dc.once(), and
dc.emit() themselves are part of the bridge.
Persistent Storage CORE
The current bridge exposes browser local-storage persistence under
dc.storage.
Save
dc.storage.set("coins", 250);
Objects and arrays
dc.storage.set("settings", {
price: 10,
enabled: true,
modes: ["A", "B", "C"]
});
Load
const coins = dc.storage.get("coins", 0);
dc.chat("Coins: " + coins);
Remove
dc.storage.remove("coins");
| API | Purpose |
|---|---|
dc.storage.get(key, fallback) | Reads JSON data, returning the fallback when absent or invalid. |
dc.storage.set(key, value) | Serializes and stores a value. |
dc.storage.remove(key) | Removes a stored key. |
dc.storage.clear().
Remove keys individually with dc.storage.remove().
In-Memory Resources CORE
The current bridge provides an in-memory resource cache. It does not expose the older remote fetch helpers.
| API | Description |
|---|---|
dc.resources.set(id, value) | Stores a value in the JavaScript resource cache and returns it. |
dc.resources.get(id) | Returns the cached value or undefined. |
dc.resources.has(id) | Returns whether the cache contains the ID. |
dc.resources.remove(id) | Deletes the cached ID. |
dc.resources.set("score", 100);
const score = dc.resources.get("score");
if (dc.resources.has("score")) {
dc.chat("Score: " + score);
}
dc.resources.remove("score");
fetchText(), fetchJSON(),
fetchBlob(), image(), or pickResource() under
dc.resources.
Timers CORE
Timeout
const id = dc.setTimeout(function() {
dc.chat("Two seconds passed.");
}, 2000);
dc.clearTimeout(id);
Interval
const id = dc.setInterval(function() {
dc.chat("Repeating...");
}, 1000);
dc.clearInterval(id);
| API | Description |
|---|---|
dc.setTimeout(fn, ms) | Runs a function once. |
dc.clearTimeout(id) | Cancels a timeout. |
dc.setInterval(fn, ms) | Runs a function repeatedly. |
dc.clearInterval(id) | Cancels an interval. |
Audio & Titles CORE
Sound
dc.playSound(
"random.orb",
1.0,
1.0
);
| Parameter | Description |
|---|---|
soundName | Sound resource identifier. |
volume | Volume. Defaults to 1. |
pitch | Pitch. Defaults to 1. |
Title
dc.showTitle(
"§cWARNING",
"§7Something happened!"
);
Debugging CORE
| API | Description |
|---|---|
dc.log(message) | Writes a normal console log. |
dc.warn(message) | Writes a warning console log. |
dc.error(message) | Writes an error console log. |
dc.log("Plugin started");
dc.warn("Something may be wrong");
dc.error("Something failed");
Runtime Models ADVANCED
The current bridge exposes runtime model registration through
dc.models.register(). Models are supplied as JSON strings.
dc.models.register(id, json)
const model = {
texture_size: [64, 32],
elements: [
{
from: [-4, 0, -3],
to: [ 4, 10, 3]
},
{
from: [-3, 10, -3],
to: [ 3, 16, 3]
}
]
};
dc.models.register(
"beast",
JSON.stringify(model)
);
Alias
dc.entities.registerModel(
"beast",
JSON.stringify(model)
);
The alias above forwards to the same model registration queue.
Model structure
| Field | Description |
|---|---|
texture_size | Texture width and height. |
elements | Array of cuboid model elements. |
from | Minimum corner of the cuboid. |
to | Maximum corner of the cuboid. |
faces | Optional per-face texture/UV information supported by the runtime parser. |
rotation | Optional rotation information for an element. |
origin | Optional rotation point for a rotated element. |
Runtime Entities ADVANCED
The bridge exposes a runtime entity system built around registered entity configurations and queued Java-side spawning/removal/query operations.
dc.entities.create(config)
The canonical creation API is an alias of dc.entities.register().
const e = dc.entities.create({
id: "beast",
displayName: "Death Beast",
width: 1.0,
height: 2.0,
health: 100,
damage: 8,
speed: 0.30,
gravity: true,
ai: true,
model: "beast",
texture: "beast"
});
Entity configuration
| Field | Default | Description |
|---|---|---|
id | Required | Unique entity identifier within the plugin. |
displayName | id | Display name. |
width | 0.8 | Entity width. |
height | 1.8 | Entity height. |
health | 20 | Maximum/runtime health configuration. |
damage | 2 | Configured damage value. |
speed | 0.2 | Configured movement speed. |
gravity | true | Whether the runtime entity uses gravity. |
ai | true | Whether runtime AI is requested. |
model | id | Runtime model identifier. |
texture | id | Runtime texture identifier. |
Spawn
dc.entities.spawn(
e,
dc.player.x + 5,
dc.player.y,
dc.player.z + 5
);
Equivalent method on the returned entity configuration:
e.spawn(
dc.player.x + 5,
dc.player.y,
dc.player.z + 5
);
Get an entity
const entity = dc.entities.get(nativeEntityId);
if (entity) {
dc.chat("Found runtime entity.");
}
Remove an entity
dc.entities.remove(entity);
or:
dc.entities.remove(nativeEntityId);
An entity configuration also exposes:
e.remove();
Entity tick callback
dc.entities.onTick(entity, function(runtimeEntity) {
dc.log("Runtime entity tick");
});
Or through the entity object:
e.onTick(function(runtimeEntity) {
dc.log("Ticking " + runtimeEntity.id);
});
Nearby entity query
const nearby = dc.entities.nearby(
dc.player.x,
dc.player.y,
dc.player.z,
16
);
Alias:
const nearby = dc.entities.getNearby(
dc.player.x,
dc.player.y,
dc.player.z,
16
);
Runtime Textures ADVANCED
Runtime textures are loaded from an image URL and converted into ARGB pixel data for the Java-side runtime texture system.
dc.entities.registerTexture(id, url, callback)
dc.entities.registerTexture(
"beast",
"https://example.com/beast.png",
function(error, success) {
if (error) {
dc.error(String(error));
return;
}
dc.chat("§aEntity texture submitted.");
}
);
The browser loads the image asynchronously. The callback is invoked after the image is successfully decoded or after an image loading error.
Requirements
- The URL must resolve to an image the browser can load.
- The image is read through an HTML canvas.
- The final data is queued as width, height, and integer pixel values.
Typical runtime asset sequence
const model = {
texture_size: [64, 32],
elements: [
{ from: [-4, 0, -3], to: [4, 10, 3] }
]
};
dc.models.register(
"beast",
JSON.stringify(model)
);
dc.entities.registerTexture(
"beast",
"https://example.com/beast.png",
function(error) {
if (error) {
dc.error(error);
return;
}
const entity = dc.entities.create({
id: "beast",
displayName: "Death Beast",
model: "beast",
texture: "beast"
});
dc.entities.spawn(
entity,
dc.player.x + 5,
dc.player.y,
dc.player.z + 5
);
}
);
Runtime Items ADVANCED
The current bridge exposes a runtime item registry with item configuration, model registration, and texture registration.
dc.items.register(config)
const item = dc.items.register({
id: "death_blade",
name: "Death Blade",
maxStackSize: 1,
model: "death_blade",
texture: "death_blade"
});
| Field | Default | Description |
|---|---|---|
id | Required | Runtime item identifier. |
name | id | Item name. |
displayName | Used as fallback | Accepted as the name source. |
maxStackSize | 64 | Configured maximum stack size. |
model | id | Runtime item model identifier. |
texture | id | Runtime item texture identifier. |
Get an item
const item = dc.items.get("death_blade");
Register an item model
dc.items.registerModel(
"death_blade",
JSON.stringify(model)
);
Register an item texture
dc.items.registerTexture(
"death_blade",
"https://example.com/death_blade.png",
function(error, success) {
if (error) {
dc.error(error);
return;
}
dc.chat("§aItem texture submitted.");
}
);
Working Examples
Example: Health Alert
const dc = window.DeathClient;
dc.createMod({
name: "Health Alert",
description: "Warns when health is low.",
category: "PLAYER",
isCheat: false,
settings: [
dc.createSetting(
"Slider",
"Threshold",
5,
1,
20,
1
)
],
onUpdate: function(settings) {
const threshold = settings["Threshold"].value;
if (dc.player.health > 0 &&
dc.player.health <= threshold) {
dc.playSound("random.orb", 1.0, 1.0);
}
}
});
Example: Local command
const dc = window.DeathClient;
dc.createCommand({
name: "where",
prefix: ".",
execute: function() {
dc.chat(
"X: " + dc.player.x +
" Y: " + dc.player.y +
" Z: " + dc.player.z
);
}
});
Example: Persistent counter
const dc = window.DeathClient;
let count = dc.storage.get("count", 0);
dc.createMod({
name: "Counter",
onEnable: function() {
count++;
dc.storage.set("count", count);
dc.chat(
"§eLoaded count: §f" + count
);
}
});
Example: Runtime model + entity
const dc = window.DeathClient;
const model = {
texture_size: [64, 32],
elements: [
{ from: [-4, 0, -3], to: [4, 10, 3] },
{ from: [-3, 10, -3], to: [3, 16, 3] },
{ from: [-6, 3, -2], to: [-4, 12, 2] },
{ from: [4, 3, -2], to: [6, 12, 2] }
]
};
dc.createMod({
name: "Death Beast",
displayName: "Death Beast",
description: "Runtime entity example",
category: "WORLD",
isCheat: false,
onEnable: function() {
dc.models.register(
"beast",
JSON.stringify(model)
);
const entity = dc.entities.create({
id: "beast",
displayName: "Death Beast",
width: 1.0,
height: 2.0,
health: 100,
damage: 8,
speed: 0.30,
gravity: true,
ai: true,
model: "beast",
texture: "beast"
});
entity.onTick(function(runtimeEntity) {
dc.log("Death Beast tick");
});
dc.entities.spawn(
entity,
dc.player.x + 5,
dc.player.y,
dc.player.z + 5
);
}
});
Troubleshooting
My local command does nothing
Check all three parts:
dc.createCommand({
name: "test",
prefix: ".",
execute: function(args) {
dc.chat("Command fired: " + args);
}
});
Then type:
.test hello
The callback registration uses name. Using the older
command property with dc.createCommand() will not create
the expected command.
The API capability scanner says something is unavailable
That means the exact JavaScript property or function does not exist in the currently installed bridge. Check the exact spelling and namespace.
dc.entities exists but spawning fails
The entity JavaScript API is queue-based. The bridge can expose creation, spawning, removal, ticking, and queries while the Java-side runtime queue consumers are missing or incompatible. Check the Java entity manager/plugin manager integration.
Texture registration fails
Check the URL, image format, browser loading restrictions, and cross-origin access. The current bridge decodes the image through an HTML canvas before queueing its pixels.
Storage values disappear
Use dc.storage.set() and dc.storage.get() consistently.
Values are JSON serialized. Unsupported circular objects cannot be serialized.
A mod does not receive updates
Make sure the mod was registered successfully and the client-side mod manager is calling its update path. JavaScript callbacks are not a replacement for the Java mod lifecycle; they are invoked by it.