Lua Scripting Basics

Write custom behavior without recompiling

📁 File Location: Place your scripts in the scripts/ folder. main.lua is loaded automatically on server start.

Your First Script

Create scripts/main.lua:

-- scripts/main.lua
-- This runs when the server starts

print("Server started!")

-- Called for every event
function onEvent(event)
    if event.type == "PLAYER_JOIN" then
        print("Player joined: " .. event.player.name)
    end
end

MCX Global Object

The MCX object provides access to server functions:

FunctionDescriptionExample
MCX.broadcast(text) Send message to all players MCX.broadcast("Welcome!")
MCX.sendMessage(playerId, text) Send private message MCX.sendMessage("uuid123", "Hello")
MCX.getPlayer(id) Get player by ID local p = MCX.getPlayer(id)
MCX.getOnlinePlayers() Get all online players local players = MCX.getOnlinePlayers()
MCX.teleport(playerId, x, y, z) Teleport player MCX.teleport(id, 0, 64, 0)
MCX.getBalance(playerId) Get player's money local money = MCX.getBalance(id)
MCX.deposit(playerId, amount) Give money MCX.deposit(id, 100)
MCX.loadScene(name) Switch scene MCX.loadScene("arena")

Player Data

Player objects contain:

function onEvent(event)
    if event.type == "PLAYER_JOIN" then
        local player = event.player
        
        print("ID: " .. player.id)
        print("Name: " .. player.name)
        print("Scene: " .. player.scene)
        
        if player.position then
            print("X: " .. player.position.x)
            print("Y: " .. player.position.y)
            print("Z: " .. player.position.z)
        end
    end
end

Command Handler

Create custom commands:

function onEvent(event)
    if event.type == "CHAT_MESSAGE" then
        local player = event.player
        local msg = event.message
        
        -- Check for !command
        if msg:sub(1, 1) == "!" then
            local args = {}
            for arg in msg:gmatch("%S+") do
                table.insert(args, arg)
            end
            
            local cmd = args[1]:sub(2) -- Remove !
            
            if cmd == "balance" then
                local balance = MCX.getBalance(player.id)
                MCX.sendMessage(player.id, "Your balance: " .. balance .. " coins")
                
            elseif cmd == "pay" and args[2] and args[3] then
                local targetName = args[2]
                local amount = tonumber(args[3])
                
                -- Find target player
                local players = MCX.getOnlinePlayers()
                for _, p in ipairs(players) do
                    if p.name == targetName then
                        local success = MCX.transfer(player.id, p.id, amount)
                        if success then
                            MCX.sendMessage(player.id, "Paid " .. amount .. " to " .. targetName)
                        else
                            MCX.sendMessage(player.id, "Payment failed!")
                        end
                        break
                    end
                end
                
            elseif cmd == "spawn" then
                MCX.teleport(player.id, 0, 64, 0)
                MCX.sendMessage(player.id, "Teleported to spawn!")
            end
        end
    end
end

Scheduled Tasks

Run code after a delay:

-- Schedule a message in 5 seconds
MCX.schedule(5000, function()
    MCX.broadcast("5 seconds have passed!")
end)

-- Repeating task (every 30 seconds)
local function announceRestart()
    MCX.broadcast("§cServer restart in 1 minute!")
end

-- Call every 30 seconds
MCX.scheduleRepeating(30000, announceRestart)

File I/O

Save and load data:

-- Save player data
local playerData = {}

function saveData()
    local file = io.open("data/players.json", "w")
    if file then
        -- Convert table to JSON string (simplified)
        local json = "{"
        for id, data in pairs(playerData) do
            json = json .. '"' .. id .. '":' .. data.kills .. ","
        end
        json = json .. "}"
        file:write(json)
        file:close()
    end
end

function loadData()
    local file = io.open("data/players.json", "r")
    if file then
        local content = file:read("*all")
        file:close()
        -- Parse JSON (you'd use a proper JSON library)
        print("Loaded: " .. content)
    end
end

-- Auto-save every 5 minutes
MCX.scheduleRepeating(300000, saveData)

Best Practices

-- Good: Using local
local function helper() end

-- Bad: Global function
function helper() end

-- Good: Error handling
local ok, result = pcall(function()
    return riskyOperation()
end)
if not ok then
    print("Error: " .. result)
end