| Method | Description |
|---|---|
api.registerCommand(name, executor) | Register simple command |
api.registerCommand(name, desc, usage, executor) | Register command with description |
api.registerCommand(name, desc, usage, executor, completer) | Register command with tab completion |
š Getting Started
Installation
Requirements
- Minecraft Server: Paper 26.1 or higher (recommended: Paper)
- Java: Version 25 or higher
- Minecraft Version: 26.1
- Download the latest release
- Place the JAR file in your server's
plugins/folder - Start or restart your server
- Create JS plugins in
plugins/MC-JS/js-plugins/
Your First Plugin
Create a new file in plugins/MC-JS/js-plugins/ with a .js extension:
var pluginInfo = {
name: "My First Plugin",
version: "1.0.0",
author: "YourName",
description: "My awesome first plugin!"
};
var mcjsVersion = api.getMCJSVersion();
logger.info("Running on MC-JS " + mcjsVersion);
function onEnable() {
logger.info("My plugin is enabled!");
api.registerCommand("hello", "Say hello", "/hello", function(sender, args) {
api.sendMessage(sender, "&aHello from JavaScript!");
return true;
});
api.registerEvent("player.PlayerJoinEvent", function(event) {
var player = event.getPlayer();
api.sendMessage(player, "&6Welcome to the server!");
});
}
function onDisable() {
logger.info("My plugin is disabled!");
}
this.onEnable = onEnable;
this.onDisable = onDisable;
this.pluginInfo = pluginInfo;
/jsreload or restart the server, then test with /hello
š Complete API Reference
api- Complete JS API wrapperserver- Minecraft server instanceplugin- Main plugin instancelogger- Plugin logger (logger.info(), logger.warning(), etc.)scheduler- Server schedulerBukkit- Bukkit API access
š¬ Command Registration
Simple Command
api.registerCommand("command", function(sender, args) {
api.sendMessage(sender, "Command executed!");
return true;
});
Command with Description and Usage
api.registerCommand("command", "Description", "/command [args]",
function(sender, args) {
if (args.length > 0) {
api.sendMessage(sender, "You said: " + args[0]);
} else {
api.sendMessage(sender, "&cUsage: /command <message>");
}
return true;
}
);
Command with Tab Completion
api.registerCommand("command", "Description", "/command [player]",
function(sender, args) {
var target = api.getPlayer(args[0]);
if (target) {
api.sendMessage(sender, "Found player: " + target.getName());
}
return true;
},
function(sender, args) {
if (args.length === 1) {
return api.getPlayerNames();
}
return [];
}
);
š® Event Registration
Basic Event
api.registerEvent("player.PlayerJoinEvent", function(event) {
var player = event.getPlayer();
api.sendMessage(player, "&aWelcome to the server!");
});
Event with Priority
api.registerEvent("block.BlockBreakEvent", function(event) {
var player = event.getPlayer();
var block = event.getBlock();
event.setCancelled(true);
api.sendMessage(player, "&cYou cannot break blocks here!");
}, "HIGH");
Available Event Packages
| Package | Examples |
|---|---|
player.* |
PlayerJoinEvent, PlayerQuitEvent, PlayerDeathEvent |
block.* |
BlockBreakEvent, BlockPlaceEvent, BlockClickEvent |
entity.* |
EntityDamageEvent, EntitySpawnEvent |
inventory.* |
InventoryClickEvent, InventoryCloseEvent |
server.* |
ServerLoadEvent, PluginEnableEvent |
ā° Task Scheduling
Delayed Task
api.runTaskLater(100, function() {
logger.info("This runs after 5 seconds");
api.broadcast("&a5 seconds have passed!");
});
Repeating Task
var task = api.runTaskTimer(0, 1200, function() {
var playerCount = api.getOnlinePlayers().size();
logger.info("Server has " + playerCount + " player(s) online");
});
api.runTaskLater(6000, function() {
api.cancelTask(task);
logger.info("Task cancelled after 5 minutes");
});
Async Task
api.runTaskAsync(function() {
var response = api.httpGet("https://api.example.com/data");
logger.info("Fetched data: " + response);
api.runTask(function() {
api.broadcast("&aData fetched successfully!");
});
});
| Method | Description |
|---|---|
api.runTask(task) |
Run task on next tick |
api.runTaskLater(delay, task) |
Run task after delay (in ticks) |
api.runTaskTimer(delay, period, task) |
Run repeating task |
api.runTaskAsync(task) |
Run task asynchronously |
api.runTaskLaterAsync(delay, task) |
Run delayed async task |
api.cancelTask(task) |
Cancel a running task |
š¤ Player Management
Get Players
var player = api.getPlayer("PlayerName");
if (player) {
api.sendMessage(player, "Hello!");
}
var exactPlayer = api.getPlayerExact("ExactPlayerName");
var allPlayers = api.getOnlinePlayers();
for (var i = 0; i < allPlayers.length; i++) {
var p = allPlayers[i];
logger.info("Online: " + p.getName());
}
Send Messages
api.sendMessage(player, "&aHello &bWorld!");
api.broadcast("&6Server announcement!");
api.broadcast("&cAdmin message!", "admin.message");
api.sendTitle(player, "&aWelcome!", "&eEnjoy your stay!", 10, 70, 20);
api.sendActionBar(player, "&bYou are in the spawn area!");
Player Properties
api.setHealth(player, 20.0);
var health = api.getHealth(player);
var maxHealth = api.getMaxHealth(player);
api.setFoodLevel(player, 20);
var food = api.getFoodLevel(player);
api.setSaturation(player, 5.0);
api.clearInventory(player);
api.setGameMode(player, GameMode.CREATIVE);
var gamemode = api.getGameMode(player);
var location = api.createLocation(world, 100, 64, 200);
api.teleport(player, location);
api.setLevel(player, 10);
api.setExp(player, 0.5);
api.giveExp(player, 100);
š¦ Inventory & Items
Create Inventory
var inv = api.createInventory(null, 27, "&6My Custom GUI");
var chest = api.createInventory(null, InventoryType.CHEST, "&bChest Menu");
var customInv = api.createCustomInventory(27, "&6Custom GUI");
var gui = api.createCustomInventory(3, "&bMy Menu", true);
GUI Builder Pattern (Recommended)
var gui = api.createGUI("&6My Custom Menu", 3);
var item1 = api.createItemStack(api.getMaterial("DIAMOND"), 1);
item1 = api.setItemDisplayName(item1, "&bDiamond Option");
gui.setItem(10, item1, function(event) {
event.setCancelled(true);
api.sendMessage(event.getWhoClicked(), "&aYou clicked the diamond!");
});
var item2 = api.createItemStack(api.getMaterial("EMERALD"), 1);
item2 = api.setItemDisplayName(item2, "&aEmerald Option");
gui.setItem(16, item2, function(event) {
event.setCancelled(true);
api.sendMessage(event.getWhoClicked(), "&aYou clicked the emerald!");
});
var background = api.createItemStack(api.getMaterial("GRAY_STAINED_GLASS_PANE"), 1);
background = api.setItemDisplayName(background, " ");
gui.fillBorders(background);
gui.setBackground(background);
gui.setAllowItemRemoval(false);
gui.onClick(function(event) {
var slot = event.getSlot();
});
gui.onClose(function(event) {
var player = event.getPlayer();
api.sendMessage(player, "&7You closed the menu");
});
var inventory = gui.buildAndOpen(player);
var inv = gui.build();
player.openInventory(inv);
Create Items with Enchantments
var sword = api.createItemStack(api.getMaterial("DIAMOND_SWORD"), 1);
sword = api.setItemDisplayName(sword, "&b&lMagic Sword");
api.addEnchantment(sword, "SHARPNESS", 5);
api.addEnchantment(sword, "FIRE_ASPECT", 2);
api.addEnchantment(sword, "UNBREAKING", 3);
if (api.hasEnchantment(sword, "SHARPNESS")) {
var level = api.getEnchantmentLevel(sword, "SHARPNESS");
logger.info("Sword has Sharpness level " + level);
}
var enchantments = api.getEnchantments(sword);
for (var enchantName in enchantments) {
logger.info(enchantName + ": " + enchantments[enchantName]);
}
api.removeEnchantment(sword, "FIRE_ASPECT");
sword = api.setItemLore(sword, [
"&7This is a special diamond",
"&7given by the JS plugin!",
"&eRight-click to use"
]);
api.giveItem(player, diamond);
api.setInventoryItem(inv, 0, diamond);
api.fillInventory(inv, diamond);
api.fillInventoryRange(inv, diamond, 0, 8);
Inventory Events
api.registerInventoryClick(inv, function(event) {
event.setCancelled(true);
var slot = event.getSlot();
var player = event.getWhoClicked();
api.sendMessage(player, "&aYou clicked slot " + slot);
if (slot === 10) {
api.giveItem(player, api.createItemStack(api.getMaterial("DIAMOND"), 5));
}
});
api.registerInventoryClose(inv, function(event) {
var player = event.getPlayer();
api.sendMessage(player, "&7You closed the inventory");
});
Custom Inventory Holder
var holder = api.createInventoryHolder();
holder.setData("menuType", "shop");
holder.setData("player", player);
var inv = api.createInventoryWithHolder(holder, 27, "&6Shop Menu");
var invHolder = api.getInventoryHolder(inv);
if (invHolder) {
var menuType = invHolder.getData("menuType");
var storedPlayer = invHolder.getData("player");
}
if (api.isCustomInventory(inv)) {
}
var slotHandler = api.getSlotClickHandler(inv, 10);
var globalHandler = api.getGlobalClickHandler(inv);
šļø Database Operations
Create Table
api.createTable("mydb", "players", {
"id": "INTEGER PRIMARY KEY AUTOINCREMENT",
"name": "TEXT NOT NULL",
"level": "INTEGER DEFAULT 1",
"coins": "INTEGER DEFAULT 0",
"last_seen": "INTEGER"
});
Insert Data
api.insertData("mydb", "players", {
"name": "PlayerName",
"level": 10,
"coins": 1000,
"last_seen": api.getCurrentTimeMillis()
});
Update Data
api.updateData("mydb", "players",
{ "level": 20, "coins": 2000 },
"name = 'PlayerName'"
);
Query Data
var results = api.querySQL("mydb",
"SELECT * FROM players WHERE level > 5"
);
for (var i = 0; i < results.length; i++) {
var row = results[i];
logger.info("Player: " + row.name + ", Level: " + row.level);
}
Delete Data
api.deleteData("mydb", "players", "last_seen < " + (api.getCurrentTimeMillis() - 86400000));
var count = api.countRows("mydb", "players");
var activeCount = api.countRows("mydb", "players", "last_seen > " + (api.getCurrentTimeMillis() - 86400000));
š World & Block Management
World Operations
var world = api.getWorld("world");
var allWorlds = api.getWorlds();
api.setWorldTime(world, 6000);
var time = api.getWorldTime(world);
api.setStorm(world, true);
api.setThundering(world, true);
var hasStorm = api.hasStorm(world);
var isThundering = api.isThundering(world);
var border = api.getWorldBorder(world);
api.setWorldBorderSize(world, 1000);
api.setWorldBorderCenter(world, 0, 0);
Block Operations
var block = api.getBlock(location);
var blockType = api.getBlockType(location);
api.setBlockType(location, api.getMaterial("DIAMOND_BLOCK"));
api.breakBlock(location);
api.breakBlock(location, false);
var block = api.getBlockAt(world, 100, 64, 200);
var blocks = api.getBlocksInRadius(centerLocation, 5.0);
for (var i = 0; i < blocks.length; i++) {
logger.info("Block: " + blocks[i].getType().name());
}
Explosions & Lightning
api.createExplosion(location, 5.0);
api.createExplosion(location, 5.0, true);
api.strikeLightning(location);
api.strikeLightningEffect(location);
šÆ Entity Management
Spawn Entities
var zombie = api.spawnEntity(location, "ZOMBIE");
var creeper = api.spawnEntity(location, EntityType.CREEPER);
api.setEntityCustomName(zombie, "&cCustom Zombie");
api.setEntityGlowing(zombie, true);
api.setEntityGravity(zombie, false);
api.setEntityInvulnerable(zombie, true);
api.removeEntity(zombie);
š File Operations
YAML Files
var data = {
"server": {
"name": "My Server",
"maxPlayers": 100
},
"settings": {
"pvp": true,
"spawnProtection": true
}
};
api.saveYamlFile("config", data);
var config = api.loadYamlFile("config");
var serverName = config.get("server").get("name");
var serverName2 = config.get("server").get("name");
var bansData = api.loadYamlFile("bansystem_bans");
var bansList = bansData.get("bans");
var nextId = bansData.get("nextId");
var bans = [];
if (bansList instanceof java.util.List) {
for (var i = 0; i < bansList.size(); i++) {
var banObj = bansList.get(i);
var ban = {};
if (banObj instanceof java.util.Map) {
var keys = banObj.keySet().toArray();
for (var j = 0; j < keys.length; j++) {
var key = keys[j];
ban[key] = banObj.get(key);
}
}
bans.push(ban);
}
}
JSON Files
var jsonData = {
"players": ["Player1", "Player2"],
"timestamp": api.getCurrentTimeMillis()
};
api.saveJsonFile("data", JSON.stringify(jsonData, null, 2));
var json = api.loadJsonFile("data");
var data = JSON.parse(json);
Text Files
api.saveTextFile("log", "Line 1\nLine 2\nLine 3");
var content = api.loadTextFile("log");
logger.info("File content: " + content);
Config System
var config = api.getPluginConfig("myplugin");
var setting = api.getPluginConfigValue("myplugin", "setting", "default");
api.setPluginConfigValue("myplugin", "setting", "new value");
api.savePluginConfig("myplugin", {
"setting1": "value1",
"setting2": "value2"
});
ā±ļø Cooldown System
Basic Cooldown
var name = pluginInfo.name;
var scope = "command";
if (api.systems.claimCooldown(name, scope, player.getName(), 5)) {
api.sendMessage(player, "&aCommand ready!");
} else {
var remaining = api.systems.cooldownRemaining(name, scope, player.getName());
api.sendMessage(player, "&cCooldown: " + Math.ceil(remaining) + " seconds");
}
š° Economy & Systems
Vault Economy
if (api.vault.isAvailable()) {
var balance = api.vault.balance(player);
api.sendMessage(player, "&aBalance: " + api.vault.format(balance));
var result = api.vault.deposit(player, 1000.0);
if (result.isSuccess()) {
api.sendMessage(player, "&aDeposited!");
}
}
Persistent Data
var name = pluginInfo.name;
var scope = "stats";
api.systems.writeData(name, scope, "kills-" + player.getName(), JSON.stringify({"kills": 10}));
var data = api.systems.readData(name, scope, "kills-" + player.getName(), "{}");
api.systems.deleteData(name, scope, "kills-" + player.getName());
š” Complete Examples
Example 1: Welcome Plugin
var pluginInfo = {
name: "Welcome Plugin",
version: "1.0.0",
author: "YourName"
};
function onEnable() {
api.registerEvent("player.PlayerJoinEvent", function(event) {
var player = event.getPlayer();
api.sendMessage(player, "&6Welcome to the server, &b" + player.getName() + "&6!");
api.sendTitle(player, "&aWelcome!", "&eEnjoy your stay!", 10, 70, 20);
api.playSound(player, "ENTITY_PLAYER_LEVELUP", 1.0, 1.0);
api.runTaskLater(20, function() {
var bread = api.createItemStack(api.getMaterial("BREAD"), 5);
var sword = api.createItemStack(api.getMaterial("WOODEN_SWORD"), 1);
api.giveItem(player, bread);
api.giveItem(player, sword);
api.sendMessage(player, "&aYou received a welcome kit!");
});
});
}
this.onEnable = onEnable;
this.pluginInfo = pluginInfo;
Example 2: Stats Plugin with Database
var pluginInfo = {
name: "Stats Plugin",
version: "1.0.0"
};
function onEnable() {
api.createTable("stats", "player_stats", {
"player_name": "TEXT PRIMARY KEY",
"kills": "INTEGER DEFAULT 0",
"deaths": "INTEGER DEFAULT 0",
"playtime": "INTEGER DEFAULT 0"
});
api.registerCommand("stats", "View your stats", "/stats [player]",
function(sender, args) {
var targetName = args.length > 0 ? args[0] : sender.getName();
var results = api.querySQL("stats",
"SELECT * FROM player_stats WHERE player_name = '" + targetName + "'");
if (results.length > 0) {
var stats = results[0];
api.sendMessage(sender, "&6=== Stats for " + targetName + " ===");
api.sendMessage(sender, "&eKills: &a" + stats.kills);
api.sendMessage(sender, "&eDeaths: &c" + stats.deaths);
api.sendMessage(sender, "&ePlaytime: &b" + Math.floor(stats.playtime / 3600) + " hours");
} else {
api.sendMessage(sender, "&cNo stats found for " + targetName);
}
return true;
},
function(sender, args) {
return api.getPlayerNames();
}
);
api.registerEvent("entity.PlayerDeathEvent", function(event) {
var killer = event.getEntity().getKiller();
var victim = event.getEntity();
if (killer) {
var killerStats = api.querySQL("stats",
"SELECT kills FROM player_stats WHERE player_name = '" + killer.getName() + "'");
if (killerStats.length > 0) {
api.updateData("stats", "player_stats",
{ "kills": killerStats[0].kills + 1 },
"player_name = '" + killer.getName() + "'");
} else {
api.insertData("stats", "player_stats", {
"player_name": killer.getName(),
"kills": 1,
"deaths": 0
});
}
}
var victimStats = api.querySQL("stats",
"SELECT deaths FROM player_stats WHERE player_name = '" + victim.getName() + "'");
if (victimStats.length > 0) {
api.updateData("stats", "player_stats",
{ "deaths": victimStats[0].deaths + 1 },
"player_name = '" + victim.getName() + "'");
} else {
api.insertData("stats", "player_stats", {
"player_name": victim.getName(),
"kills": 0,
"deaths": 1
});
}
});
}
this.onEnable = onEnable;
this.pluginInfo = pluginInfo;
Example 3: Custom GUI Menu (Old Method)
var pluginInfo = {
name: "Menu Plugin",
version: "1.0.0"
};
function onEnable() {
api.registerCommand("menu", "Open custom menu", "/menu", function(sender, args) {
if (!(sender instanceof Player)) {
api.sendMessage(sender, "&cOnly players can use this command!");
return false;
}
var player = sender;
var inv = api.createInventory(null, 27, "&6Custom Menu");
var item1 = api.createItemStack(api.getMaterial("DIAMOND"), 1);
item1 = api.setItemDisplayName(item1, "&bOption 1");
item1 = api.setItemLore(item1, ["&7Click to get diamonds!"]);
api.setInventoryItem(inv, 10, item1);
var item2 = api.createItemStack(api.getMaterial("EMERALD"), 1);
item2 = api.setItemDisplayName(item2, "&aOption 2");
item2 = api.setItemLore(item2, ["&7Click to get emeralds!"]);
api.setInventoryItem(inv, 16, item2);
var close = api.createItemStack(api.getMaterial("BARRIER"), 1);
close = api.setItemDisplayName(close, "&cClose Menu");
api.setInventoryItem(inv, 22, close);
api.registerInventoryClick(inv, function(event) {
event.setCancelled(true);
var slot = event.getSlot();
if (slot === 10) {
api.sendMessage(player, "&aYou clicked Option 1!");
api.giveItem(player, api.createItemStack(api.getMaterial("DIAMOND"), 5));
} else if (slot === 16) {
api.sendMessage(player, "&aYou clicked Option 2!");
api.giveItem(player, api.createItemStack(api.getMaterial("EMERALD"), 5));
} else if (slot === 22) {
player.closeInventory();
}
});
player.openInventory(inv);
return true;
});
}
this.onEnable = onEnable;
this.pluginInfo = pluginInfo;
Example 4: GUI Builder Pattern (Recommended)
var pluginInfo = {
name: "Shop Plugin",
version: "1.0.0"
};
function onEnable() {
api.registerCommand("shop", "Open shop", "/shop", function(sender, args) {
if (!(sender instanceof Player)) {
api.sendMessage(sender, "&cOnly players can use this command!");
return false;
}
var player = sender;
var gui = api.createGUI("&6&lShop Menu", 3);
var bg = api.createItemStack(api.getMaterial("GRAY_STAINED_GLASS_PANE"), 1);
bg = api.setItemDisplayName(bg, " ");
gui.fillBorders(bg);
gui.setBackground(bg);
var sword = api.createItemStack(api.getMaterial("DIAMOND_SWORD"), 1);
sword = api.setItemDisplayName(sword, "&bDiamond Sword");
sword = api.setItemLore(sword, [
"&7Price: &a100 Coins",
"&7Click to purchase!"
]);
gui.setItem(10, sword, function(event) {
event.setCancelled(true);
api.sendMessage(player, "&aYou purchased a Diamond Sword!");
api.giveItem(player, sword);
});
var apple = api.createItemStack(api.getMaterial("GOLDEN_APPLE"), 1);
apple = api.setItemDisplayName(apple, "&eGolden Apple");
apple = api.setItemLore(apple, [
"&7Price: &a50 Coins",
"&7Click to purchase!"
]);
gui.setItem(13, apple, function(event) {
event.setCancelled(true);
api.sendMessage(player, "&aYou purchased a Golden Apple!");
api.giveItem(player, apple);
});
var book = api.createItemStack(api.getMaterial("ENCHANTED_BOOK"), 1);
book = api.setItemDisplayName(book, "&dEnchanted Book");
book = api.setItemLore(book, [
"&7Price: &a200 Coins",
"&7Click to purchase!"
]);
gui.setItem(16, book, function(event) {
event.setCancelled(true);
api.sendMessage(player, "&aYou purchased an Enchanted Book!");
api.giveItem(player, book);
});
var close = api.createItemStack(api.getMaterial("BARRIER"), 1);
close = api.setItemDisplayName(close, "&cClose Shop");
gui.setItem(22, close, function(event) {
event.setCancelled(true);
player.closeInventory();
});
gui.onClick(function(event) {
});
gui.onClose(function(event) {
api.sendMessage(player, "&7Shop closed. Come back soon!");
});
gui.buildAndOpen(player);
return true;
});
}
this.onEnable = onEnable;
this.pluginInfo = pluginInfo;
Example 4: Advanced Cooldown System
var pluginInfo = {
name: "Cooldown Example",
version: "1.0.0"
};
function onEnable() {
api.registerCommand("heal", "Heal yourself", "/heal", function(sender, args) {
if (!(sender instanceof Player)) {
api.sendMessage(sender, "&cOnly players can use this!");
return false;
}
var player = sender;
var name = pluginInfo.name;
var scope = "heal";
if (!api.systems.claimCooldown(name, scope, player.getName(), 30)) {
var remaining = api.systems.cooldownRemaining(name, scope, player.getName());
api.sendMessage(player, "&cCooldown: " + Math.ceil(remaining) + " seconds");
return false;
}
api.setHealth(player, api.getMaxHealth(player));
api.setFoodLevel(player, 20);
api.sendMessage(player, "&aYou have been healed!");
return true;
});
}
this.onEnable = onEnable;
this.pluginInfo = pluginInfo;
Example 5: Vault Economy
var pluginInfo = {
name: "Economy Example",
version: "1.0.0"
};
function onEnable() {
api.registerCommand("balance", "Check your balance", "/balance", function(sender, args) {
var player = sender;
if (!(player instanceof Player)) {
api.sendMessage(sender, "&cOnly players can use this!");
return false;
}
if (!api.vault.isAvailable()) {
api.sendMessage(player, "&cNo economy plugin found!");
return false;
}
var balance = api.vault.balance(player);
api.sendMessage(player, "&6Your balance: &e" + api.vault.format(balance));
return true;
});
api.registerCommand("pay", "Pay another player", "/pay ", function(sender, args) {
var player = sender;
if (!(player instanceof Player)) {
api.sendMessage(sender, "&cOnly players can use this!");
return false;
}
if (args.length < 2) {
api.sendMessage(player, "&cUsage: /pay <player> <amount>");
return false;
}
var target = api.getPlayer(args[0]);
var amount = Number(args[1]);
var result = api.vault.transfer(player, target, amount);
if (result.isSuccess()) {
api.sendMessage(player, "&aYou paid &e" + api.vault.format(amount) + " &ato " + target.getName());
api.sendMessage(target, "&aYou received &e" + api.vault.format(amount) + " &afrom " + player.getName());
} else {
api.sendMessage(player, "&cPayment failed: " + result.getError());
}
return true;
});
}
this.onEnable = onEnable;
this.pluginInfo = pluginInfo;
Example 6: World Protection System
var pluginInfo = {
name: "World Protection",
version: "1.0.0"
};
var protectedRegions = [];
function onEnable() {
var spawn = api.getWorlds()[0].getSpawnLocation();
protectedRegions.push({
center: spawn,
radius: 50
});
api.registerEvent("block.BlockBreakEvent", function(event) {
var player = event.getPlayer();
var block = event.getBlock();
if (isInProtectedRegion(block.getLocation())) {
if (!api.hasPermission(player, "protection.bypass")) {
event.setCancelled(true);
api.sendMessage(player, "&cYou cannot break blocks in the protected area!");
api.playSound(player, "ENTITY_VILLAGER_NO", 1.0, 1.0);
}
}
});
api.registerEvent("block.BlockPlaceEvent", function(event) {
var player = event.getPlayer();
var block = event.getBlock();
if (isInProtectedRegion(block.getLocation())) {
if (!api.hasPermission(player, "protection.bypass")) {
event.setCancelled(true);
api.sendMessage(player, "&cYou cannot place blocks in the protected area!");
}
}
});
api.registerEvent("player.PlayerMoveEvent", function(event) {
var player = event.getPlayer();
if (isInProtectedRegion(player.getLocation())) {
api.sendActionBar(player, "&cā Protected Area");
}
});
}
function isInProtectedRegion(location) {
for (var i = 0; i < protectedRegions.length; i++) {
var region = protectedRegions[i];
var distance = api.getDistance(location, region.center);
if (distance <= region.radius) {
return true;
}
}
return false;
}
this.onEnable = onEnable;
this.pluginInfo = pluginInfo;
š Complete API Reference
All Available Methods
This is a comprehensive list of all API methods available in MC-JS. Click on a category to expand:
ā”Command Methods (3 methods)
ā¼šÆEvent Methods (6 methods)
ā¼| Method | Description |
|---|---|
api.registerEvent(eventClassName, handler) | Register event by string name |
api.registerEvent(eventClass, handler, priority) | Register event with priority |
api.registerInventoryClick(inv, handler) | Register inventory click handler |
api.registerInventoryClose(inv, handler) | Register inventory close handler |
api.createCustomInventory(size, title) | Create custom inventory |
api.createGUI(title, rows) | Create GUI builder |
ā±ļøTask Methods (8 methods)
ā¼| Method | Description |
|---|---|
api.runTask(task) | Run task on next tick |
api.runTaskLater(delay, task) | Run task after delay (ticks) |
api.runTaskTimer(delay, period, task) | Run repeating task |
api.runTaskAsync(task) | Run async task |
api.runTaskLaterAsync(delay, task) | Run delayed async task |
api.runTaskSafe(task, onError) | Run task with error handler |
api.runTaskAsyncSafe(task, onError) | Run async task with error handler |
api.cancelTask(task) | Cancel running task |
š¤Player Methods (30+ methods)
ā¼| Method | Description |
|---|---|
api.getPlayer(name) | Get player by name |
api.getPlayerExact(name) | Get player by exact name |
api.getOnlinePlayers() | Get all online players |
api.getPlayerNames() | Get list of online player names |
api.sendMessage(sender, message) | Send message |
api.sendTitle(player, title, subtitle) | Send title |
api.sendActionBar(player, message) | Send action bar |
api.broadcast(message) | Broadcast to all |
api.broadcast(message, permission) | Broadcast with permission |
api.setHealth(player, health) | Set player health |
api.getHealth(player) | Get player health |
api.getMaxHealth(player) | Get max health |
api.setFoodLevel(player, level) | Set food level |
api.getFoodLevel(player) | Get food level |
api.setSaturation(player, saturation) | Set saturation |
api.getSaturation(player) | Get saturation |
api.clearInventory(player) | Clear player inventory (including armor) |
api.damage(player, damage) | Damage player |
api.setExp(player, exp) | Set experience (0.0-1.0) |
api.getExp(player) | Get experience (0.0-1.0) |
api.setLevel(player, level) | Set level |
api.getLevel(player) | Get level |
api.giveExp(player, amount) | Give experience points |
api.setGameMode(player, mode) | Set game mode |
api.getGameMode(player) | Get game mode |
api.teleport(player, location) | Teleport player |
api.teleport(entity, location) | Teleport entity |
api.getPlayerByUUID(uuid) | Get player by UUID |
api.getOfflinePlayer(name) | Get offline player |
api.getOfflinePlayerByUUID(uuid) | Get offline player by UUID |
api.isPlayerOnline(name/player) | Check if player is online |
api.kickPlayer(player, reason) | Kick player |
api.banPlayer(name, reason) | Ban player |
api.unbanPlayer(name) | Unban player |
api.isBanned(name) | Check if banned |
api.addToWhitelist(name) | Add to whitelist |
api.removeFromWhitelist(name) | Remove from whitelist |
api.isWhitelisted(name) | Check if whitelisted |
api.setWhitelistEnabled(enabled) | Enable/disable whitelist |
api.isWhitelistEnabled() | Check if whitelist enabled |
api.generateOfflineUUID(name) | Generate UUID for offline player |
Permission Methods
| Method | Description |
|---|---|
api.hasPermission(sender, permission) | Check permission (CommandSender) |
api.hasPermission(player, permission) | Check permission (Player) |
api.addPermission(player, permission) | Add permission to player |
api.removePermission(player, permission) | Remove permission from player |
api.isOp(player) | Check if player is OP |
api.setOp(player, op) | Set player OP status |
Player Data Methods
| Method | Description |
|---|---|
api.setPlayerMetadata(player, key, value) | Set player metadata |
api.getPlayerMetadata(player, key) | Get player metadata |
api.hasPlayerMetadata(player, key) | Check if player has metadata |
api.removePlayerMetadata(player, key) | Remove player metadata |
š¦Inventory & GUI Methods (20+ methods)
ā¼Basic Inventory Methods
| Method | Description |
|---|---|
api.createInventory(holder, size, title) | Create inventory |
api.createCustomInventory(size, title) | Create custom inventory (simplified) |
api.createCustomInventory(rows, title, useRows) | Create custom inventory by rows |
api.createGUI(title, rows) | Create GUI builder (recommended) |
api.createInventoryHolder() | Create custom inventory holder |
api.createInventoryWithHolder(holder, size, title) | Create inventory with custom holder |
api.getInventoryHolder(inv) | Get holder from inventory |
api.isCustomInventory(inv) | Check if custom inventory |
api.getSlotClickHandler(inv, slot) | Get slot-specific click handler |
api.getGlobalClickHandler(inv) | Get global click handler |
api.setInventoryItem(inv, slot, item) | Set item in slot |
GUI Builder Methods
| Method | Description |
|---|---|
gui.setItem(slot, item) | Set item at slot |
gui.setItem(slot, item, handler) | Set item with click handler |
gui.setItems(startSlot, endSlot, item) | Set items in range |
gui.fill(item) | Fill entire inventory |
gui.fillBorders(item) | Fill borders only |
gui.setBackground(item) | Set background for empty slots |
gui.onClick(handler) | Set global click handler |
gui.onClose(handler) | Set close handler |
gui.setAllowItemRemoval(allow) | Allow/prevent items from being removed from GUI (default: false) |
gui.build() | Build and return inventory |
gui.buildAndOpen(player) | Build and open for player |
Custom Inventory Holder Methods
| Method | Description |
|---|---|
holder.setData(key, value) | Store custom data |
holder.getData(key) | Get custom data |
holder.getAllData() | Get all custom data |
holder.removeData(key) | Remove custom data |
holder.clearData() | Clear all custom data |
Custom Inventory Management
| Method | Description |
|---|---|
api.updateInventoryItem(inv, slot, item) | Update item in custom inventory |
api.getInventoryItem(inv, slot) | Get item from custom inventory |
api.clearInventory(inventory) | Clear custom inventory (GUI) |
api.refreshInventory(inv) | Refresh/rebuild custom inventory |
api.isInventorySlotEmpty(inv, slot) | Check if slot is empty |
api.getFirstEmptySlot(inv) | Get first empty slot |
api.addItemToInventory(inv, item) | Add item to inventory |
api.removeItemFromInventory(inv, item) | Remove item from inventory |
api.inventoryContains(inv, item) | Check if inventory contains item |
api.inventoryContainsAtLeast(inv, item, amount) | Check if inventory has at least amount |
āļøItem Methods (15+ methods)
ā¼| Method | Description |
|---|---|
api.setInventoryItem(inv, slot, item) | Set item in slot |
api.getInventoryItem(inv, slot) | Get item from slot |
api.fillInventory(inv, item) | Fill entire inventory |
api.fillInventoryRange(inv, item, start, end) | Fill inventory range |
api.createItemStack(material, amount) | Create item stack |
api.setItemDisplayName(item, name) | Set item display name |
api.setItemLore(item, lore) | Set item lore |
api.giveItem(player, item) | Give item to player |
api.getItemInMainHand(player) | Get item in main hand |
api.setItemInMainHand(player, item) | Set item in main hand |
api.getItemInOffHand(player) | Get item in off hand |
api.setItemInOffHand(player, item) | Set item in off hand |
api.getItemMeta(item) | Get item meta |
api.setItemMeta(item, meta) | Set item meta |
Enchantment Methods
| Method | Description |
|---|---|
api.addEnchantment(item, name, level) | Add enchantment to item |
api.removeEnchantment(item, name) | Remove enchantment from item |
api.hasEnchantment(item, name) | Check if item has enchantment |
api.getEnchantmentLevel(item, name) | Get enchantment level |
api.getEnchantments(item) | Get all enchantments (returns Map) |
š¾Database Methods (7 methods)
ā¼| Method | Description |
|---|---|
api.createTable(dbName, tableName, columns) | Create database table |
api.insertData(dbName, tableName, data) | Insert data |
api.updateData(dbName, tableName, data, where) | Update data |
api.deleteData(dbName, tableName, where) | Delete data |
api.querySQL(dbName, sql) | Query database |
api.countRows(dbName, tableName) | Count rows |
api.executeSQL(dbName, sql) | Execute SQL |
šFile Methods (9 methods)
ā¼| Method | Description |
|---|---|
api.saveYamlFile(fileName, data) | Save YAML file (data as Map/Object) |
api.loadYamlFile(fileName) | Load YAML file (returns Java Map, use .get() to access values) |
api.saveJsonFile(fileName, content) | Save JSON file |
api.loadJsonFile(fileName) | Load JSON file (returns JSON string) |
api.saveTextFile(fileName, content) | Save text file |
api.loadTextFile(fileName) | Load text file (returns string) |
Important: loadYamlFile returns a Java Map object. Use .get(key) to access values. Arrays are returned as Java List objects. Use instanceof java.util.List to check and convert to JavaScript arrays if needed. See the YAML Files section above for examples.
āļøConfig Methods (4 methods)
ā¼| Method | Description |
|---|---|
api.getPluginConfig(pluginName) | Get plugin config |
api.savePluginConfig(pluginName, data) | Save plugin config |
api.getPluginConfigValue(pluginName, path) | Get config value |
api.setPluginConfigValue(pluginName, path, value) | Set config value |
ā³Cooldown & Systems Methods (9 methods)
ā¼| Method | Description |
|---|---|
api.systems.claimCooldown(name, scope, key, seconds) | Claim a cooldown (true if freshly claimed) |
api.systems.cooldownRemaining(name, scope, key) | Get remaining seconds |
api.systems.writeData(name, scope, key, json) | Store JSON data (survives restarts) |
api.systems.readData(name, scope, key, fallback) | Read JSON data |
api.systems.deleteData(name, scope, key) | Delete data |
api.systems.changeNumber(name, scope, key, delta) | Change a stored number |
api.systems.grantKit(name, player, key, seconds, items) | Grant an item kit with cooldown |
api.systems.purchase(name, player, currency, cost, item) | Purchase an item |
api.systems.createMenu(title, rows) | Create an interactive menu with buttons |
Vault Economy Methods
| Method | Description |
|---|---|
api.vault.isAvailable() | Check if a Vault economy is present |
api.vault.balance(player) | Get player balance |
api.vault.has(player, amount) | Check if the player has enough money |
api.vault.deposit(player, amount) | Add money to balance |
api.vault.withdraw(player, amount) | Remove money from balance |
api.vault.transfer(from, to, amount) | Transfer money between players |
api.vault.purchase(player, cost, item) | Buy an item with balance check |
api.vault.format(amount) | Format money amount |
Particle & Sound Methods
| Method | Description |
|---|---|
api.spawnParticle(loc, particle, count) | Spawn particles |
api.spawnParticle(loc, particleName, count, ...) | Spawn particles (string) |
api.playSound(loc, sound, volume, pitch) | Play sound at location |
api.playSound(player, sound, volume, pitch) | Play sound for player |
api.playSound(loc, soundName, volume, pitch) | Play sound (string) |
šWorld & Block Methods (20+ methods)
ā¼| Method | Description |
|---|---|
api.getWorld(name) | Get world by name |
api.getWorlds() | Get all worlds |
api.getWorldNames() | Get world names |
api.getWorldTime(world) | Get world time |
api.setWorldTime(world, time) | Set world time |
api.hasStorm(world) | Check if storming |
api.setStorm(world, storm) | Set storm |
api.isThundering(world) | Check if thundering |
api.setThundering(world, thundering) | Set thundering |
api.getBlock(location) | Get block |
api.getBlockType(location) | Get block type |
api.setBlockType(location, material) | Set block type |
api.breakBlock(location) | Break block |
api.breakBlock(location, dropItems) | Break block with drop option |
api.getBlocksInRadius(center, radius) | Get blocks in radius |
api.createExplosion(location, power) | Create explosion |
api.createExplosion(location, power, setFire) | Create explosion with fire |
api.strikeLightning(location) | Strike lightning |
api.strikeLightningEffect(location) | Strike lightning effect |
World Management Methods
| Method | Description |
|---|---|
api.setWorldDifficulty(world, difficulty) | Set world difficulty (PEACEFUL, EASY, NORMAL, HARD) |
api.getWorldDifficulty(world) | Get world difficulty |
api.setWorldPVP(world, pvp) | Enable/disable PvP |
api.isWorldPVP(world) | Check if PvP enabled |
api.setWorldSpawnLocation(world, location) | Set world spawn location |
api.getWorldSpawnLocation(world) | Get world spawn location |
api.setWorldKeepSpawnInMemory(world, keepLoaded) | Keep spawn in memory |
api.isWorldKeepSpawnInMemory(world) | Check if spawn kept in memory |
api.setWorldAutoSave(world, autoSave) | Enable/disable auto-save |
api.isWorldAutoSave(world) | Check if auto-save enabled |
api.getWorldEnvironment(world) | Get world environment |
api.getWorldSeed(world) | Get world seed |
š¾Entity Methods (15+ methods)
ā¼| Method | Description |
|---|---|
api.spawnEntity(location, type) | Spawn entity |
api.spawnEntity(location, typeName) | Spawn entity (string) |
api.getNearbyEntities(location, x, y, z) | Get nearby entities |
api.setEntityCustomName(entity, name) | Set entity name |
api.setEntityGlowing(entity, glowing) | Set glowing |
api.setEntityGravity(entity, gravity) | Set gravity |
api.setEntityInvulnerable(entity, invulnerable) | Set invulnerable |
api.setEntityAI(entity, ai) | Enable/disable AI |
api.hasEntityAI(entity) | Check if entity has AI |
api.setEntitySilent(entity, silent) | Set entity silent |
api.isEntitySilent(entity) | Check if entity is silent |
api.setEntityCollidable(entity, collidable) | Set entity collidable |
api.isEntityCollidable(entity) | Check if entity is collidable |
api.getEntityLocation(entity) | Get entity location |
api.teleportEntity(entity, location) | Teleport entity to location |
api.teleportEntity(entity, target) | Teleport entity to target entity |
api.removeEntity(entity) | Remove entity |
Scoreboard Methods
| Method | Description |
|---|---|
api.getMainScoreboard() | Get main scoreboard |
api.createScoreboard() | Create new scoreboard |
api.getTeam(scoreboard, name) | Get team |
api.createTeam(scoreboard, name) | Create team |
api.getObjective(scoreboard, name) | Get objective |
api.createObjective(scoreboard, name, criteria, displayName) | Create objective |
Potion Effect Methods
| Method | Description |
|---|---|
api.createPotionEffect(type, duration, amplifier) | Create potion effect |
api.createPotionEffect(type, duration, amplifier, ambient) | Create potion effect with ambient |
Location & Vector Methods
| Method | Description |
|---|---|
api.createLocation(world, x, y, z) | Create location |
api.createLocation(world, x, y, z, yaw, pitch) | Create location with rotation |
api.createVector(x, y, z) | Create vector |
api.getDistance(loc1, loc2) | Get distance between locations |
api.getDistanceSquared(loc1, loc2) | Get squared distance |
api.getMidpoint(loc1, loc2) | Get midpoint between locations |
Material Methods
| Method | Description |
|---|---|
api.getMaterial(name) | Get material by name |
api.isBlock(material) | Check if material is block |
api.isItem(material) | Check if material is item |
World Border Methods
| Method | Description |
|---|---|
api.getWorldBorder(world) | Get world border |
api.setWorldBorderSize(world, size) | Set world border size |
api.setWorldBorderCenter(world, x, z) | Set world border center |
Advancement Methods
| Method | Description |
|---|---|
api.grantAdvancement(player, key) | Grant advancement |
api.revokeAdvancement(player, key) | Revoke advancement |
Server & Plugin Methods
| Method | Description |
|---|---|
api.getMCJSVersion() | Get MC-JS plugin version |
api.getServerVersion() | Get server version |
api.getBukkitVersion() | Get Bukkit version |
api.getMaxPlayers() | Get max players |
api.getMotd() | Get MOTD |
api.isPluginEnabled(name) | Check if plugin enabled |
api.getPlugin(name) | Get plugin |
api.hasEconomy() | Check if economy available |
Logging Methods
| Method | Description |
|---|---|
api.logInfo(message) | Log info message |
api.logWarning(message) | Log warning message |
api.logError(message) | Log error message |
Random Methods
| Method | Description |
|---|---|
api.randomInt(min, max) | Random integer |
api.randomDouble(min, max) | Random double |
api.randomBoolean() | Random boolean |
String Utility Methods
| Method | Description |
|---|---|
api.format(format, ...args) | Format string |
api.join(delimiter, ...elements) | Join strings |
Utility Methods
| Method | Description |
|---|---|
api.colorize(text) | Colorize text |
api.stripColor(text) | Strip colors |
api.format(format, ...args) | Format string |
api.round(value, places) | Round number |
api.clamp(value, min, max) | Clamp value |
api.md5(input) | MD5 hash |
api.sha256(input) | SHA256 hash |
api.base64Encode(input) | Base64 encode |
api.base64Decode(input) | Base64 decode |
api.urlEncode(input) | URL encode |
api.urlDecode(input) | URL decode |
api.getCurrentTimeMillis() | Get current time (milliseconds) |
api.getCurrentTime() | Get current time (seconds) |
api.formatDate(timestamp) | Format date |
api.formatDate(timestamp, pattern) | Format date with pattern |
api.parseDate(dateString) | Parse date |
api.parseDate(dateString, pattern) | Parse date with pattern |
api.executeCommand(command) | Execute console command |
api.httpGet(url) | HTTP GET request |
api.httpPost(url, data) | HTTP POST request |
Validation Methods
| Method | Description |
|---|---|
api.isValidPlayer(player) | Check if valid online player |
api.isValidLocation(location) | Check if valid location |
api.isValidWorld(world) | Check if valid world |
api.isValidItemStack(item) | Check if valid item stack |
api.isValidEntity(entity) | Check if valid entity |
api.isValidInventory(inventory) | Check if valid inventory |
File Existence Methods
| Method | Description |
|---|---|
api.yamlFileExists(fileName) | Check if YAML file exists |
api.jsonFileExists(fileName) | Check if JSON file exists |
api.textFileExists(fileName) | Check if text file exists |
api.deleteYamlFile(fileName) | Delete YAML file |
api.deleteJsonFile(fileName) | Delete JSON file |
api.deleteTextFile(fileName) | Delete text file |
Database Methods (Additional)
| Method | Description |
|---|---|
api.countRows(dbName, tableName) | Count rows in table |
api.countRows(dbName, tableName, where) | Count rows with condition |
api.updateData(dbName, tableName, data, where) | Update data |
api.deleteData(dbName, tableName, where) | Delete data |
š§ Advanced Topics
Systems & Cooldowns
var name = pluginInfo.name;
// Persistent per-player cooldowns
var scope = "vote";
if (api.systems.claimCooldown(name, scope, player.getName(), 300)) {
api.sendMessage(player, "&aYou can vote again!");
} else {
var remaining = api.systems.cooldownRemaining(name, scope, player.getName());
api.sendMessage(player, "&cVote again in " + Math.ceil(remaining / 60) + " minutes");
}
// Storable data + counters
api.systems.writeData(name, "stats", "deaths-" + player.getName(),
JSON.stringify({"deaths": 3}));
api.systems.changeNumber(name, "stats", "deaths-" + player.getName(), 1);
Permissions & Player Management
if (api.hasPermission(player, "myplugin.use")) {
}
api.addPermission(player, "myplugin.vip");
api.removePermission(player, "myplugin.vip");
if (api.isOp(player)) {
api.sendMessage(player, "You are OP!");
}
api.setOp(player, true);
api.setPlayerMetadata(player, "lastLogin", api.getCurrentTimeMillis());
var lastLogin = api.getPlayerMetadata(player, "lastLogin");
if (api.hasPlayerMetadata(player, "lastLogin")) {
logger.info("Last login: " + lastLogin);
}
api.addToWhitelist("PlayerName");
api.removeFromWhitelist("PlayerName");
if (api.isWhitelisted("PlayerName")) {
logger.info("Player is whitelisted");
}
api.setWhitelistEnabled(true);
Particles & Sounds
api.spawnParticle(location, "FIREWORK", 10, 0.5, 0.5, 0.5, 0.1);
api.spawnParticle(location, Particle.FLAME, 5, 0, 0, 0);
api.playSound(location, "ENTITY_PLAYER_LEVELUP", 1.0, 1.0);
api.playSound(player, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 0.5, 1.5);
api.registerEvent("player.PlayerMoveEvent", function(event) {
var player = event.getPlayer();
if (player.isSprinting()) {
api.spawnParticle(player.getLocation(), "CLOUD", 3, 0, 0, 0);
}
});
Entity Manipulation
var zombie = api.spawnEntity(location, "ZOMBIE");
api.setEntityCustomName(zombie, "&cBoss Zombie");
api.setEntityGlowing(zombie, true);
api.setEntityGravity(zombie, false);
api.setEntityInvulnerable(zombie, true);
api.setEntityAI(zombie, false);
if (!api.hasEntityAI(zombie)) {
logger.info("Zombie has no AI");
}
api.setEntitySilent(zombie, true);
api.setEntityCollidable(zombie, false);
var targetLocation = api.createLocation(world, 100, 64, 200);
api.teleportEntity(zombie, targetLocation);
api.teleportEntity(zombie, player);
var entityLoc = api.getEntityLocation(zombie);
api.removeEntity(zombie);
World Management
api.setWorldDifficulty(world, "HARD");
var difficulty = api.getWorldDifficulty(world);
api.setWorldPVP(world, true);
if (api.isWorldPVP(world)) {
logger.info("PvP is enabled");
}
var spawnLoc = api.createLocation(world, 0, 64, 0);
api.setWorldSpawnLocation(world, spawnLoc);
var currentSpawn = api.getWorldSpawnLocation(world);
api.setWorldAutoSave(world, false);
if (!api.isWorldAutoSave(world)) {
logger.info("Auto-save disabled");
}
var environment = api.getWorldEnvironment(world);
var seed = api.getWorldSeed(world);
logger.info("World: " + world.getName() + ", Seed: " + seed);
Validation & Error Handling
var player = api.getPlayer("PlayerName");
if (api.isValidPlayer(player)) {
api.sendMessage(player, "Hello!");
} else {
logger.warning("Player not found or offline");
}
var location = api.createLocation(world, 0, 64, 0);
if (api.isValidLocation(location)) {
api.teleport(player, location);
}
var item = api.getItemInMainHand(player);
if (api.isValidItemStack(item)) {
api.addEnchantment(item, "SHARPNESS", 1);
}
api.runTaskAsyncSafe(function() {
var data = api.loadYamlFile("data");
}, function(error) {
logger.severe("Error in async task: " + error);
});
HTTP Requests
api.runTaskAsync(function() {
var response = api.httpGet("https://api.example.com/data");
logger.info("Response: " + response);
var data = JSON.parse(response);
api.runTask(function() {
api.broadcast("&aData fetched: " + data.message);
});
});
api.runTaskAsync(function() {
var jsonData = JSON.stringify({
"player": "PlayerName",
"action": "join"
});
var response = api.httpPost("https://api.example.com/log", jsonData);
logger.info("POST response: " + response);
});
Utility Methods
var colored = api.colorize("&aHello &bWorld");
var stripped = api.stripColor(colored);
var formatted = api.format("Hello %s! You have %d items.", "Player", 5);
var rounded = api.round(3.14159, 2);
var clamped = api.clamp(150, 0, 100);
var encoded = api.base64Encode("Hello World");
var decoded = api.base64Decode(encoded);
var md5 = api.md5("text");
var sha256 = api.sha256("text");
var now = api.getCurrentTimeMillis();
var formatted = api.formatDate(now);
var customFormat = api.formatDate(now, "dd.MM.yyyy HH:mm");
var parsed = api.parseDate("2024-01-01 12:00:00");
var distance = api.getDistance(loc1, loc2);
var midpoint = api.getMidpoint(loc1, loc2);
- Always wrap code in try-catch blocks for error handling
- Use async tasks for HTTP requests and heavy operations
- Clean up resources (cancel tasks, close connections) in onDisable
- Use cooldowns to prevent spam
- Cache frequently accessed data
⨠Best Practices
Error Handling
api.registerCommand("risky", "Risky command", "/risky", function(sender, args) {
try {
var player = api.getPlayer(args[0]);
if (!player) {
api.sendMessage(sender, "&cPlayer not found!");
return false;
}
player.teleport(someLocation);
api.sendMessage(sender, "&aSuccess!");
return true;
} catch (e) {
logger.severe("Error in risky command: " + e);
api.sendMessage(sender, "&cAn error occurred!");
return false;
}
});
api.registerEvent("player.PlayerJoinEvent", function(event) {
try {
var player = event.getPlayer();
} catch (e) {
logger.severe("Error in PlayerJoinEvent: " + e);
}
});
Performance Optimization
api.runTaskTimer(0, 1, function() {
var players = api.getOnlinePlayers();
for (var i = 0; i < players.length; i++) {
}
});
var cachedPlayers = [];
api.runTaskTimer(0, 20, function() {
cachedPlayers = api.getOnlinePlayers();
for (var i = 0; i < cachedPlayers.length; i++) {
}
});
api.runTaskAsync(function() {
var data = api.httpGet("https://api.example.com/heavy");
api.runTask(function() {
api.broadcast("Data loaded!");
});
});
var task = api.runTaskTimer(0, 20, function() {
});
api.cancelTask(task);
Code Organization
var pluginInfo = {
name: "My Plugin",
version: "1.0.0"
};
var config = {
enabled: true,
cooldown: 5000
};
var playerData = {};
function formatMessage(player, message) {
return "&7[" + player.getName() + "] &f" + message;
}
function hasPermission(player, perm) {
return api.hasPermission(player, "myplugin." + perm);
}
function onEnable() {
logger.info("Loading " + pluginInfo.name + " v" + pluginInfo.version);
initializeDatabase();
registerCommands();
registerEvents();
logger.info(pluginInfo.name + " enabled!");
}
function onDisable() {
saveData();
logger.info(pluginInfo.name + " disabled!");
}
this.onEnable = onEnable;
this.onDisable = onDisable;
this.pluginInfo = pluginInfo;
Player Safety Checks
api.registerEvent("player.PlayerQuitEvent", function(event) {
var player = event.getPlayer();
var playerName = player.getName();
savePlayerData(playerName);
});
function giveReward(playerName) {
var player = api.getPlayer(playerName);
if (!player) {
logger.warning("Player " + playerName + " is not online!");
return false;
}
api.giveItem(player, reward);
return true;
}
api.registerCommand("playeronly", "Player only command", "/playeronly", function(sender, args) {
if (!(sender instanceof Player)) {
api.sendMessage(sender, "&cThis command can only be used by players!");
return false;
}
var player = sender;
player.teleport(location);
return true;
});
š§ Troubleshooting
Common Issues & Solutions
Plugin not loading
- Check file extension: Must be
.js - Check syntax: Use a JavaScript validator
- Check console: Look for error messages
- Check onEnable: Function must be defined and exported
- Check file location: Must be in
plugins/MC-JS/js-plugins/
Events not firing
- Check event name: Use format
player.PlayerJoinEvent - Check registration: Must be in
onEnable - Check handler: Function must accept event parameter
- Check console: Look for registration errors
- Try reload: Use
/jsreload <plugin>
Commands not working
- Check registration: Must be in
onEnable - Check return value: Must return
trueorfalse - Check permissions: Use
api.hasPermission() - Check console: Look for JavaScript errors
- Try reload: Use
/jsreload <plugin>
Player is null errors
- Always check:
if (player) { ... } - Use instanceof:
if (sender instanceof Player) - Check online status:
api.getPlayer(name)returns null if offline - Handle offline players: Use
server.getOfflinePlayer()for UUID
Database errors
- Check table exists: Use
api.createTable()first - Check data types: Match column types
- Check NOT NULL: Provide values for required fields
- Check SQL syntax: Use proper SQL in queries
- Check file permissions: Database files need write access
Performance issues
- Avoid heavy operations: Use async tasks
- Cache data: Don't query database every tick
- Cancel tasks: Clean up repeating tasks
- Limit operations: Don't process all players every tick
- Use cooldowns: Prevent spam
Debug Mode
Enable debug mode in config.yml to see detailed logging:
settings:
debug-mode: true
This will show:
- Event registration details
- Event execution logs
- Plugin loading information
- Command execution details
Common Error Messages
"ReferenceError: X is not defined"
Solution: Check if the variable/class is available. Use instanceof Player instead of checking for undefined properties.
"Cannot read property 'X' of null"
Solution: Always check if objects exist before accessing properties:
var player = api.getPlayer(name);
if (player) {
player.teleport(location);
}
"SQLiteException: NOT NULL constraint failed"
Solution: Ensure all required fields are provided when inserting data:
api.insertData("db", "table", {
"required_field": value,
"optional_field": value || null
});
"Events being called multiple times"
Solution: This is fixed in MC-JS - events are only dispatched once per event instance, even if multiple plugins register the same event.
ā Frequently Asked Questions
General Questions
Q: Can I use ES6+ features?
A: Yes! MC-JS uses Rhino with ES6 support. You can use arrow functions, let/const, template literals, etc.
Q: How do I reload my plugin?
A: Use /jsreload <plugin-name> or /jsreload to reload all plugins.
Q: Can I use npm packages?
A: No, MC-JS uses Rhino which doesn't support Node.js modules. Use the built-in API instead.
Q: How do I check if a player is online?
A: Use api.getPlayer(name) - it returns null if the player is offline.
Q: Can I access Bukkit API directly?
A: Yes! The server object gives you access to the Bukkit Server instance. Also, Bukkit classes like Player, Material, etc. are available.
Q: How do I handle offline players?
A: Use server.getOfflinePlayer(name) to get UUID and other data for offline players.
Q: Can multiple plugins register the same event?
A: Yes! Each plugin's handler will be called. MC-JS ensures events are only dispatched once per event instance.
Q: How do I create a config file?
A: Use api.getPluginConfig(pluginName) and api.savePluginConfig(pluginName, data).
Q: Can I use async/await?
A: No, but you can use api.runTaskAsync() for asynchronous operations.
Q: How do I prevent command spam?
A: Use the cooldown system: api.systems.claimCooldown(pluginInfo.name, "command", playerName, 5)
š Common Code Snippets
Player Utilities
function isPlayerOnline(name) {
return api.getPlayer(name) !== null;
}
function getPlayerSafe(name) {
var player = api.getPlayer(name);
if (!player) {
logger.warning("Player " + name + " is not online!");
return null;
}
return player;
}
function getPlayerUUID(name) {
var player = api.getPlayer(name);
if (player) {
return player.getUniqueId().toString();
}
try {
var offline = server.getOfflinePlayer(name);
return offline.getUniqueId().toString();
} catch (e) {
return null;
}
}
Command Patterns
api.registerCommand("admin", "Admin command", "/admin", function(sender, args) {
if (!api.hasPermission(sender, "myplugin.admin")) {
api.sendMessage(sender, "&cNo permission!");
return false;
}
if (!(sender instanceof Player)) {
api.sendMessage(sender, "&cPlayers only!");
return false;
}
return true;
});
api.registerCommand("cooldown", "Cooldown command", "/cooldown", function(sender, args) {
if (!(sender instanceof Player)) return false;
var player = sender;
var playerName = player.getName();
var scope = "cooldown";
if (!api.systems.claimCooldown(pluginInfo.name, scope, playerName, 5)) {
var remaining = api.systems.cooldownRemaining(pluginInfo.name, scope, playerName);
api.sendMessage(player, "&cCooldown: " + Math.ceil(remaining) + "s");
return false;
}
api.sendMessage(player, "&aCommand executed!");
return true;
});
Data Storage Patterns
var playerData = {};
function savePlayerData(playerName) {
try {
api.saveYamlFile("players/" + playerName, playerData[playerName] || {});
} catch (e) {
logger.severe("Error saving data for " + playerName + ": " + e);
}
}
function loadPlayerData(playerName) {
try {
var data = api.loadYamlFile("players/" + playerName);
if (data) {
var playerObj = {};
if (data instanceof java.util.Map) {
var keys = data.keySet().toArray();
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var value = data.get(key);
if (value instanceof java.util.Map) {
var nestedObj = {};
var nestedKeys = value.keySet().toArray();
for (var j = 0; j < nestedKeys.length; j++) {
nestedObj[nestedKeys[j]] = value.get(nestedKeys[j]);
}
playerObj[key] = nestedObj;
} else {
playerObj[key] = value;
}
}
}
playerData[playerName] = playerObj;
}
} catch (e) {
logger.warning("No data found for " + playerName);
playerData[playerName] = {};
}
}
api.registerEvent("player.PlayerQuitEvent", function(event) {
var player = event.getPlayer();
savePlayerData(player.getName());
delete playerData[player.getName()];
});
GUI Patterns
function openMenu(player) {
var gui = api.createGUI("&6Menu", 3);
var bg = api.createItemStack(api.getMaterial("GRAY_STAINED_GLASS_PANE"), 1);
bg = api.setItemDisplayName(bg, " ");
gui.fillBorders(bg);
var item1 = api.createItemStack(api.getMaterial("DIAMOND"), 1);
item1 = api.setItemDisplayName(item1, "&bOption 1");
gui.setItem(10, item1, function(event) {
event.setCancelled(true);
api.sendMessage(player, "&aYou clicked Option 1!");
});
gui.buildAndOpen(player);
}
var guiData = {};
function openShop(player) {
var gui = api.createGUI("&6Shop", 3);
var playerName = player.getName();
guiData[playerName] = {
page: 1,
category: "weapons"
};
var inv = gui.build();
var holder = api.getInventoryHolder(inv);
if (holder) {
holder.setData("player", playerName);
holder.setData("page", 1);
}
player.openInventory(inv);
}