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:
| Function | Description | Example |
|---|---|---|
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
- Use local variables - Faster and avoids conflicts
- Check for nil - Always verify data exists before using
- Handle errors - Use pcall for risky operations
- Organize code - Split into multiple files: commands.lua, events.lua, utils.lua
-- 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