Creating scripts with AI

If you want to use AI chatbots to help you create scripts, simply click the ‘Copy’ button on the right side of this page. The AI will automatically understand the instructions and figure out how OpenJS works. Or you can un collapse "LLM-CODE", copy the contents and paste it into your AI-Chat manually.

LLM-CODE
# OpenJS Scripting Documentation (Condensed)

## Core Concepts

OpenJS is a Minecraft server plugin that allows you to write JavaScript scripts to modify server behavior. Scripts are placed in `plugins/OpenJS/scripts/` and automatically load when changed.

## Basic Script Example

```javascript
log.info("Hello World!")
```

## Essential Global APIs

### `log`
- `log.info(message)` - Log informational message
- `log.warn(message)` - Log warning
- `log.error(message)` - Log error

### `task` (Scheduling)
- `task.spawn(function)` - Run function asynchronously
- `task.main(function)` - Run on main thread (Bukkit)
- `task.entitySchedule(entity, function)` - Run on entity thread (Folia)
- `task.delay(seconds, function)` - Execute after delay
- `task.repeat(delay, period, function)` - Repeating task
- `task.wait(seconds)` - Pause execution
- `task.cancel(taskId)` - Cancel scheduled task

### `script` Object
- `script.Name` - Script filename
- `script.RelativePath` - Relative path from scripts folder
- `script.File` - Java File object

### Event Handling
```javascript
// Register event listener
const listener = registerEvent("org.bukkit.event.player.PlayerJoinEvent", function(event) {
    const player = event.getPlayer();
    player.sendMessage("Welcome!");
});

// Unregister event
unregisterEvent(listener);
```

### Java Integration
```javascript
// Import Java classes
const Bukkit = importClass("org.bukkit.Bukkit");
const Material = importClass("org.bukkit.Material");

// Import external JAR libraries (place in plugins/OpenJS/Libs/)
const MyLib = importLib("my-library.jar");
```

### Script Dependencies
```javascript
// Require another script (runs in same environment)
const result = requireScript("other.js");

// Load/Unload scripts dynamically
LoadScript("script.js");  // Waits for loading
UnloadScript("script.js"); // Waits for unloading
```

### Commands
```javascript
// Create custom command
addCommand("mycommand", {
    onCommand: function(sender, args) {
        // Convert Java array to JS array
        args = toArray(args);
        sender.sendMessage("Command executed!");
    },
    onTabComplete: function(sender, args) {
        // Return Java List for tab completion
        return toJavaList(["option1", "option2"]);
    }
}, "my.permission"); // Optional permission

// Remove any command
removeCommand("help");
```

### Shared Data Between Scripts
```javascript
// Set shared value
setShared("key", "value");

// Get shared value
const value = getShared("key");
```

### Persistent Storage (DiskApi)
```javascript
// Load/save data files
DiskApi.loadFile("data.json", false, false); // sync, not global
DiskApi.setVar("data.json", "key", "value", false);
const value = DiskApi.getVar("data.json", "key", "default", false);
DiskApi.saveFile("data.json", false, false);
```

## Key Services

### FileManager
```javascript
const fileManager = Services.get("FileManager");
fileManager.createFile("config.json");
const exists = fileManager.fileExists("config.json");
const content = fileManager.read("config.json");
fileManager.write("config.json", "{}");
```

### InventoryApi
```javascript
const invApi = Services.get("InventoryApi");
const item = invApi.createItem({
    id: "minecraft:diamond",
    name: "§bExample Item",
    lore: ["Line 1", "Line 2"],
    amount: 1
});

const menu = invApi.constructInventory("single", "§8Menu");
menu.setSlot(0, item);
menu.show(player);
menu.onLeftClick(function(player, slot, event) {
    event.setCancelled(true);
});
```

### PlaceholderApi
```javascript
const phApi = Services.get("PlaceholderApi");

// Register custom placeholder
phApi.registerPlaceholder("myprefix", {
    onRequest: function(player, params) {
        return "Value: " + params;
    }
});
// Usage: %openjs_myprefix_something%

// Parse placeholders
const parsed = phApi.parseString(player, "Hello %player_name%!");
```

### ProtocolLib (Packet Manipulation)
```javascript
const protocol = Services.get("ProtocolLib");
const listener = protocol.registerListener("NORMAL", {
    onSend: function(event) {
        const packet = event.getPacket();
        // Modify packet
    }
}, ["Play.Server.BLOCK_CHANGE"]);
```

## Important Notes

1. **Script Location**: `plugins/OpenJS/scripts/`
2. **File Naming**: Scripts in folders named `main.js` or `Main.js` auto-load
3. **JavaScript Version**: ECMAScript 6.0
4. **Thread Safety**: Use `task.main()` for Bukkit API calls
5. **Permissions**: `openjs.use` for all commands
6. **Auto-reload**: Scripts reload when modified (configurable)

## Quick Start Pattern

```javascript
// 1. Log startup
log.info("Script loaded: " + script.Name);

// 2. Register events
registerEvent("org.bukkit.event.player.PlayerJoinEvent", function(event) {
    event.getPlayer().sendMessage("Welcome!");
});

// 3. Add commands if needed
addCommand("test", {
    onCommand: function(sender) {
        sender.sendMessage("Test command!");
    }
});

// 4. Cleanup on unload
task.bindToUnload(function() {
    log.info("Script unloaded");
});
```

## Common Server Compatibility
- Bukkit, Folia, Paper, Purpur, Spigot
- For Folia: Use `task.entitySchedule()` instead of `task.main()`

This condensed guide contains all essential APIs and patterns needed to create functional OpenJS scripts.
Example script (spawns bait which animals/entities will follow if they it that):
const ProtocolLib = Services.get("ProtocolLib");

var activeBaits = [];
var fakeIds = [];
var soundCoordinates = [];

const Bukkit = org.bukkit.Bukkit;
const dispatch = Bukkit.dispatchCommand;
const ItemStack = org.bukkit.inventory.ItemStack
const NamespacedKey = org.bukkit.NamespacedKey
const PersistentDataType = org.bukkit.persistence.PersistentDataType
const console = Bukkit.getConsoleSender();
const server = Bukkit.getServer();
const baitIndicator = "isBait";

const ArmorStand = org.bukkit.entity.ArmorStand;
const FileName = "BaitData"
const BaitsKey = "Baits";
const pickUpDistance = 3; // Blocks
const IdLenght = 16; 
const respawnLenght = 32;
DiskApi.loadFile(FileName, false, false);

function RunCommand(command) {
    task.main(function() {
        dispatch(console, command);
    });
}

function getEntityById(id) {
    for (const world of server.getWorlds()) {
        for (const entity of world.getEntities()) {
            if (entity.getEntityId() === id) return entity;
        }
    }
    return null;
}

function ArrayContains(Array, Value) {
    for (let i in Array) {
        if (Array[i] == Value) {
            return true
        }
    }
    return false
}

function GetStoredBaits() {
    let raw = DiskApi.getVar(FileName, "baitsData", "");

    return raw ? raw.split("|") : [];
}

function calculateDistance(loc1, loc2) {
    return loc1.distance(loc2);
}

function StoreBait(itemID) {
    let raw = DiskApi.getVar(FileName, "baitsData", "");
    const parts = raw ? raw.split("|") : [];

    if (!ArrayContains(parts, itemID)) {
        parts.push(itemID);
    }

    DiskApi.setVar(FileName, "baitsData", parts.join("|"));
}

function UnstoreBait(itemID) {
    let raw = DiskApi.getVar(FileName, "baitsData", "");
    const parts = raw ? raw.split("|") : [];

    const filtered = parts.filter(p => p !== itemID);
    DiskApi.setVar(FileName, "baitsData", filtered.join("|"));
}

function isFakePlayer(entity) {
    if (!entity) return false;
    return fakeIds[entity.getName()];
}

function getEntityID(entity) {
    var type = entity.getType().name().toLowerCase();
    var customName = entity.getCustomName();

    if (customName) {
        return customName.replace(type+"_", "");
    }
}

function getEntityByCustomName(customName) {
    for (const world of server.getWorlds()) {
        for (const entity of world.getEntities()) {
            const name = getEntityID(entity);
            if (name && name.equals(customName)) {
                return entity;
            }
        }
    }
    return null;
}

function getItemByUniqueID(uniqueID) {
    for (const world of server.getWorlds()) {
        for (const entity of world.getEntitiesByClass(Packages.org.bukkit.entity.Item.class)) {
            if (entity.getUniqueId().toString() === uniqueID) {
                return entity;
            }
        }
    }
    return null;
}

function setEntityID(entity, baitID) {
    var type = entity.getType().name().toLowerCase();
    entity.setCustomName(type + "_" + baitID);
}

function isFakeEntity(entity) {
    if (!entity) return false;
    var ID = getEntityID(entity);
    if (!ID) return false;
    return fakeIds[ID];
}

function markItemAsBait(item) {
    const meta = item.getItemMeta();
    meta.getPersistentDataContainer().set(
        NamespacedKey.minecraft("baititem"),
        PersistentDataType.STRING,
        "true"
    );
    item.setItemMeta(meta);
}

function isBaitItem(item) {
    if (!item || !item.hasItemMeta()) return false;
    const meta = item.getItemMeta();
    return meta.getPersistentDataContainer().has(
        NamespacedKey.minecraft("baititem"),
        PersistentDataType.STRING
    );
}

function isInventoryFull(player, stackableItem) {
    const inv = player.getInventory();
    const maxStack = stackableItem.getMaxStackSize();
    const type = stackableItem.getType();
    const meta = stackableItem.hasItemMeta() ? stackableItem.getItemMeta() : null;

    for (let i = 0; i < inv.getSize(); i++) {
        const item = inv.getItem(i);
        if (!item) return false;
        if (
            item.getType() === type &&
            item.getAmount() < maxStack &&
            (meta == null || (item.hasItemMeta() && item.getItemMeta().equals(meta)))
        ) {
            return false;
        }
    }

    return true;
}

function givePlayerBaitItem(player, material) {
    const item = new ItemStack(material, 1);
    var materialName = material.name();
    var constructedMatName = (materialName[0] + String(materialName).slice(1).toLowerCase()).replace("_", " ");
    var itemMeta = item.getItemMeta();
    itemMeta.setDisplayName("§6" + constructedMatName + "§7 §eBait§7");
    item.setItemMeta(itemMeta);
    markItemAsBait(item);
    if ( player.getInventory().addItem(item).isEmpty() ) {
        player.sendMessage("§6" + constructedMatName + "§7 §eBait§7 has been added to your inventory!")
        return true
    } else {
        return false
    }
}

function createPickupArmorStand(item, BaitID) {
  const loc = item.getLocation().clone();
  loc.setY(loc.getY() - 0.3);
  const stand = item.getWorld().spawn(loc, ArmorStand.class);

  setEntityID(stand, BaitID);
  stand.setInvisible(true);
  stand.setSmall(true);
  stand.setGravity(false);
  stand.setInvulnerable(true);
  stand.setCollidable(false);
  stand.setSilent(true);

  return stand;
}

ProtocolLib.registerListener("NORMAL", {
  onSend(event) {
    const packet = event.getPacket();
    const type = event.getPacketType().name();

    const entityId = packet.getIntegers().read(0);
    const entity = getEntityById(entityId);

    if (entity && isFakePlayer(entity)) {
        event.setCancelled(true);
    }
  }
}, ["Play.Server.SPAWN_ENTITY"]);

ProtocolLib.registerListener("NORMAL", {
    onSend(event) {
        const packet = event.getPacket();
        const entries = packet.getPlayerInfoDataLists().read(1);
        
        if (!entries || entries.isEmpty()) return;

        entries.removeIf(entry =>
            entry == null || fakeIds[entry.getProfile().getName()]
        );
        packet.getPlayerInfoDataLists().write(1, entries);
    }
}, ["Play.Server.PLAYER_INFO"]);

ProtocolLib.registerListener("NORMAL", {
    onSend(event) {
        const packet = event.getPacket();
        const soundData = packet.getIntegers();

        const x = soundData.read(0) / 8.0;
        const y = soundData.read(1) / 8.0;
        const z = soundData.read(2) / 8.0;

        for (const loc of soundCoordinates) {
            if ((Math.abs(loc.getX() - x) + Math.abs(loc.getY() - y) + Math.abs(loc.getZ() - z)) <= 0.4) {
                event.setCancelled(true);
                return;
            }
        }
    }
}, ["Play.Server.NAMED_SOUND_EFFECT"]);

function getBaitID(item) {
    return item.getUniqueId().toString().replace(/-/g, "").substring(0, IdLenght);
}

function UniqueToBaitID(uniqueId) {
    return uniqueId.toString().replace(/-/g, "").substring(0, IdLenght);
}

function spawnFakePlayer(Name, location, waitForPlayer) {
    const world = location.getWorld().getKey().toString();
    const x = location.getX();
    const y = location.getY();
    const z = location.getZ();

    RunCommand(`fp spawn ${Name} ${world} ${x} ${y} ${z}`);
    soundCoordinates.push(location)

    task.delay(0.5, function () {
        const index = soundCoordinates.indexOf(location);
        if (index !== -1) soundCoordinates.splice(index, 1);
    });

    if (waitForPlayer) {
        var fakeplayer = Bukkit.getPlayer(Name);

        if (!fakeplayer) {
            while (!fakeplayer) {
                task.wait(0.01);
                fakeplayer = Bukkit.getPlayer(Name);
            }
        }

        task.main(function() {
            fakeplayer.teleport(location)
        })

        return fakeplayer
    }
}

function updateFakePlayer(fakeplayer, material) {
    return task.main(function () {
            fakeplayer.setCollidable(false);
            fakeplayer.setSilent(true);
            fakeplayer.setGameMode(org.bukkit.GameMode.CREATIVE);
            fakeplayer.setWalkSpeed(0);
            fakeplayer.setFlySpeed(0);
            fakeplayer.setFlying(true);
    
            const inv = fakeplayer.getInventory();
            inv.setItemInMainHand(new ItemStack(material));
        })
}

function dropBait(item, player) {
    var BaitID = getBaitID(item);
    var armorStand = createPickupArmorStand(item, BaitID);
    var material = item.getItemStack().getType();
    var materialName = material.name();
    var constructedMatName = (materialName[0] + String(materialName).slice(1).toLowerCase()).replace("_", " ");
    var baitData = {};
    
    baitData["id"] = BaitID;
    baitData["storeID"] = StoreBait(item.getUniqueId().toString());
    baitData["item"] = item;
    baitData["armorStand"] = armorStand;
    baitData["tasks"] = [];
    fakeIds[BaitID] = true; // anything spawned with this ID is a bait

    item.setPickupDelay(9999999);
    item.setCustomName("§6" + constructedMatName + "§7 §eBait§7");
    item.setCustomNameVisible(true);
    item.setUnlimitedLifetime(true);

    task.spawn(function () {
        baitData["SpawnLocation"] = item.getLocation()
        var fakeplayer = spawnFakePlayer(BaitID, baitData.SpawnLocation, true);

        baitData["fakeplayer"] = fakeplayer;
        baitData.tasks.push(updateFakePlayer(fakeplayer, material))

        baitData.tasks.push(task.spawn(function() {
            while (true) {
                task.wait(0.1)
                if (baitData && baitData.SpawnLocation) {
                    task.main(function () {
                        armorStand.teleport(item.getLocation().clone().add(0, -0.7, 0));

                        if (calculateDistance(baitData.SpawnLocation, fakeplayer.getLocation()) >= respawnLenght ) {
                            fakeplayer.setHealth(0);
                            task.spawn(function() {
                                let itemLocation = item.getLocation()
                                baitData.SpawnLocation = itemLocation
                                fakeplayer = spawnFakePlayer(BaitID, itemLocation, true)
                                baitData.fakeplayer = fakeplayer;
                                updateFakePlayer(fakeplayer, material)
                            })
                        } else {
                            fakeplayer.teleport(item.getLocation().clone().add(0, -1, 0));
                        }

                    })
                }
            }
        }));

        activeBaits[BaitID] = baitData;
    })
}

function removebait(baitID) {
    var baitData = activeBaits[baitID];

    if (!baitData) return;

    for (let i = 0; i < baitData.tasks.length; i++) {
      task.cancel(baitData.tasks[i]);
    }

    UnstoreBait(baitData.storeID);

    baitData.item.remove();
    baitData.armorStand.remove();
    baitData.fakeplayer.setHealth(0);

    task.delay(0.5, function() {
        fakeIds[baitID] = null;
    })

    activeBaits[baitID] = null;
}

addCommand("bait", {
    onCommand: function(sender, args) {
        if (!sender.getLocation) {
            sender.sendMessage("§cOnly for players!.");
            return;
        }

        if (args.length < 1) {
            sender.sendMessage("§eUsage: /bait <item>");
            return;
        }

        const matName = args[0].toUpperCase();
        const material = org.bukkit.Material.matchMaterial(matName);

        if (!material || !material.isItem()) {
            sender.sendMessage("§cUnknown Item: " + matName);
            return;
        }

        const loc = sender.getLocation().clone().add(0, 1, 0);
        const world = sender.getWorld();

        var itemStack = new org.bukkit.inventory.ItemStack(material, 1);
        var item = world.dropItemNaturally(loc, itemStack);
        
        dropBait(item, sender);
        sender.sendMessage("§aDropped a bait with " + material.name());
    },

    onTabComplete: function(sender, args) {
        if (args.length === 1) {
            const prefix = args[0].toLowerCase();
            const matches = [];
            for (const mat of org.bukkit.Material.values()) {
                if (mat.isItem() && mat.name().toLowerCase().startsWith(prefix)) {
                    matches.push(mat.name().toLowerCase());
                }
            }
            return toJavaList(matches.slice(0, 40));
        }
        return toJavaList([]);
    }
});

registerEvent("org.bukkit.event.entity.EntityDamageEvent", function(event) {
    const entity = event.getEntity();
    if (isFakeEntity(entity)) {
        event.setCancelled(true);
    }
});

registerEvent("org.bukkit.event.player.PlayerInteractAtEntityEvent", function(event) {
    const entity = event.getRightClicked();
    if (isFakeEntity(entity)) {
        event.setCancelled(true);
        const player = event.getPlayer();
        const plrLoc = player.getLocation();
        const curLoc = entity.getLocation();
        if ( calculateDistance(curLoc, plrLoc) <= pickUpDistance ) {
            var baitID = getEntityID(entity)
            var baitData = activeBaits[baitID]
            var collectedItem = givePlayerBaitItem(player, baitData.item.getItemStack().getType())
            if (collectedItem) {
                removebait(baitID);
            } else {
                player.sendMessage("§cYour inventory is full");
            }
        }
    }
})

registerEvent("org.bukkit.event.player.PlayerDropItemEvent", (event) => {
    const rawItem = event.getItemDrop();
    const item = rawItem.getItemStack();
    if (isBaitItem(item)) {
        dropBait(rawItem)
    }
});

registerEvent("org.bukkit.event.entity.ItemDespawnEvent", (event) => {
    const rawItem = event.getEntity()
    const item = rawItem.getItemStack();
    if (isBaitItem(item)) {
        removebait(UniqueToBaitID(rawItem.getUniqueId().toString()))
    }
});

registerEvent("org.bukkit.event.player.PlayerJoinEvent", function (event) {
    const name = event.getPlayer().getName();
    if (fakeIds[name]) event.setJoinMessage(null);
});

registerEvent("org.bukkit.event.player.PlayerQuitEvent", function (event) {
    const name = event.getPlayer().getName();
    if (fakeIds[name]) event.setQuitMessage(null);
});

registerEvent("org.bukkit.event.entity.PlayerDeathEvent", function (event) {
    const name = event.getEntity().getName();
    if (fakeIds[name]) event.setDeathMessage(null);
});

registerEvent("org.bukkit.event.server.ServerCommandEvent", function (event) {
    const msg = event.getCommand();
    if (shouldSuppressMessage(msg)) event.setCancelled(true);
});

registerEvent("org.bukkit.event.server.BroadcastMessageEvent", function (event) {
    const msg = event.getMessage();
    if (shouldSuppressMessage(msg)) event.setMessage(null);
});

function shouldSuppressMessage(msg) {
    const words = msg.split(" ");
    for (let word of words) {
        if (word.length === IdLenght && fakeIds[word]) {
            return true;
        }
    }
    return false;
}

 
task.delay(1, function() { 
    task.main(function() {
        var baits = GetStoredBaits();
        for (let i in baits) { 
            var ItemID = baits[i];
            var item = getItemByUniqueID(ItemID);
            var baitID = UniqueToBaitID(ItemID);
            var armorStand = getEntityByCustomName(baitID);
            var fakePlayer = Bukkit.getPlayer(baitID);

            if (armorStand) {
                armorStand.remove();
            }

            if (fakePlayer) {
                fakePlayer.setHealth(0);
            }

            if (item) {
                dropBait(item)
            } else {
                log.info("Removed arbitary bait!")
                UnstoreBait(ItemID)
            }
        }
    })
})

Script example 2: [Nuke Menu]
// Nuke Menu System for OpenJS
const inventoryApi = Services.get("InventoryApi");
const permissionName = "openjs.nuke";
const spawnHeight = 50;

let activeNukes = [];

// [[ Create menu template ]]
const menuTemplate = inventoryApi.constructInventory("single", "§8Select Nuke Size");
const smallNukeItem = inventoryApi.createItem({
    id: "minecraft:creeper_head",
    name: "§a§lSmall Nuke",
    lore: [
        "§7Radius: §a5 blocks",
        "§7TNT Count: §a100",
        "§8Minor destruction",
        "",
        "§eClick to launch!"
    ]
});
const mediumNukeItem = inventoryApi.createItem({
    id: "minecraft:tnt",
    name: "§6§lMedium Nuke",
    lore: [
        "§7Radius: §610 blocks",
        "§7TNT Count: §6400",
        "§8Significant destruction",
        "",
        "§eClick to launch!"
    ]
});
const hugeNukeItem = inventoryApi.createItem({
    id: "minecraft:end_crystal",
    name: "§c§lHuge Nuke",
    lore: [
        "§7Radius: §c20 blocks",
        "§7TNT Count: §c1500",
        "§8Massive destruction",
        "§4§lWARNING: May cause lag!",
        "",
        "§eClick to launch!"
    ]
});
const infoItem = inventoryApi.createItem({
    id: "minecraft:paper",
    name: "§b§lNuke Information",
    lore: [
        "§7TNT will spawn §e" + spawnHeight + " blocks §7above you",
        "§7TNT only explodes §aon impact",
        "§7Each nuke size has different radius",
        "§7All TNT spawns instantly",
        "",
        "§c§lUse with caution!"
    ]
});
const closeItem = inventoryApi.createItem({
    id: "minecraft:barrier",
    name: "§c§lClose Menu",
    lore: ["§7Close this menu"]
});
const borderItem = inventoryApi.createItem({
    id: "minecraft:black_stained_glass_pane",
    name: " "
});

for(let i = 3; i <= 6; i++) {
    menuTemplate.setSlot(i, borderItem);
}

menuTemplate.setSlot(0, smallNukeItem);
menuTemplate.setSlot(1, mediumNukeItem);
menuTemplate.setSlot(2, hugeNukeItem);
menuTemplate.setSlot(7, infoItem);
menuTemplate.setSlot(8, closeItem);
// [[ Create menu template END ]]

// Utility function to clean up arrays
function cleanupArray(arr) {
    return arr.filter(item => item !== null && item !== undefined);
}

function arrayContains(arr, value) {
    return arr.indexOf(value) !== -1;
}

// Function to spawn TNT sphere
function spawnTntSphere(player, size) {
    task.entitySchedule(player, function() {
        const playerLoc = player.getLocation();
        const center = playerLoc.clone().add(0, spawnHeight, 0);
        const world = center.getWorld();
        
        // Set radius based on size
        let radius;
        let tntCount;
        
        switch(size) {
            case 'small':
                radius = 5;
                tntCount = 100;
                break;
            case 'medium':
                radius = 10;
                tntCount = 400;
                break;
            case 'huge':
                radius = 20;
                tntCount = 1500;
                break;
            default:
                radius = 5;
                tntCount = 100;
        }

        // Send message to player
        player.sendMessage("§6Launching " + size + " nuke! §e" + tntCount + " TNT blocks falling from the sky!");

        // Generate random points within sphere
        const tntEntities = [];
        const nukeId = Date.now();
        activeNukes.push(nukeId);

        // Spawn all TNT at once
        for(let i = 0; i < tntCount; i++) {
            task.spawn(function() {
                // Generate random point in sphere using spherical coordinates
                const r = Math.random() * radius;
                const theta = Math.random() * 2 * Math.PI;
                const phi = Math.random() * Math.PI;

                const x = r * Math.sin(phi) * Math.cos(theta);
                const y = r * Math.sin(phi) * Math.sin(theta);
                const z = r * Math.cos(phi);

                const tntLoc = center.clone().add(x, y, z);

                // Spawn falling TNT
                task.entitySchedule(player, function() {
                    const tnt = world.spawn(tntLoc, org.bukkit.entity.TNTPrimed.class);
                    tnt.setFuseTicks(200); // 10 seconds
                    tnt.setCustomName("NukeTNT_" + nukeId);
                    tnt.setCustomNameVisible(false);
                    tntEntities.push(tnt);

                    if (i === tntCount - 1) {

                        const monitorTaskId = task.repeat(0, 0.1, function() {
                            if(!arrayContains(activeNukes, nukeId)) {
                                task.cancel(monitorTaskId);
                                activeNukes = cleanupArray(activeNukes.filter(id => id !== nukeId));
                                return;
                            }
                            let isActive = false;
                        
                            for(let i = 0; i < tntEntities.length; i++) {
                                const entity = tntEntities[i];
                            
                                task.entitySchedule(player, function() {
                                    if (entity.isValid()) {
                                        if (entity.isOnGround() || entity.getVelocity().length() < 0.01) {
                                            entity.setFuseTicks(0);
                                            entity.setCustomName(null);
                                        } else {
                                            isActive = true;
                                        }
                                    }
                                
                                    if(i === tntEntities.length - 1) {
                                        if (!isActive) {
                                            player.sendMessage("§aNuke detonation complete!");
                                            activeNukes = cleanupArray(activeNukes.filter(id => id !== nukeId));
                                            task.cancel(monitorTaskId);
                                        }
                                    }
                                });
                            }
                        });

                    }
                });
            });
        }
    });
}

// Function to create and show the nuke menu
function showNukeMenu(player) { 
    const menu = menuTemplate.copy(); 

    menu.onLeftClick(function(player, slot, event) {
        event.setCancelled(true);
        menu.hide(player);

        switch(slot) {
            case 0: // Small nuke
                spawnTntSphere(player, 'small');
                break;
            case 1: // Medium nuke
                spawnTntSphere(player, 'medium');
                break;
            case 2: // Huge nuke
                spawnTntSphere(player, 'huge');
                break;
            case 8: // Close
                player.sendMessage("§7Nuke menu closed.");
                break;
        }
    });

    menu.onRightClick(function(_, _, event) {
        event.setCancelled(true);
    });

    menu.onItemPlaced(function(_, _, event) {
        event.setCancelled(true);
    });

    menu.onClosed(function() {
        menu.destroy();
    });

    menu.show(player);
}

// Register command
addCommand("nukeMenu", {
    onCommand: function(sender) {
        if(!(sender instanceof org.bukkit.entity.Player)) {
            sender.sendMessage("§cThis command can only be used by players!");
            return true;
        }
        
        const player = sender;
        
        if(!player.hasPermission(permissionName) && !player.isOp()) {
            player.sendMessage("§cYou don't have permission to use this command!");
            return true;
        }
        
        showNukeMenu(player);
        return true;
    }
}, permissionName);

task.bindToUnload(function() {
    activeNukes = [];
    log.info("Nuke menu system unloaded.");
});

log.info("Nuke menu system loaded! Use /nukeMenu to open the menu.");

Last updated

Was this helpful?