Skip to main content

Cookbook

Real-world script examples you can drop straight into your server_scripts/ or client_scripts/ folders. Each recipe is self-contained and ready to use.


Coin Economy

A simple per-player coin economy with commands to check balance, pay other players, and an admin give command.

-- server_scripts/economy.lua

local function getCoins(uuid)
return data.get(uuid, "coins") or 0
end

local function setCoins(uuid, amount)
data.set(uuid, "coins", math.max(0, amount))
end

-- /balance — check your own coin balance
command.register("balance", function(ctx)
if not ctx.player then ctx.reply("Player only.") return end
ctx.reply("§6Your balance: §e" .. getCoins(ctx.player.uuid) .. " coins")
end)

-- /pay <name> <amount> (workaround: two commands)
-- Use /givecoin for admin grants
command.register("givecoin", function(ctx)
if not ctx.player then ctx.reply("Player only.") return end
-- Usage hint — argument parsing not yet supported, use scoreboard triggers or
-- a network packet from a client GUI for full UX
ctx.reply("§cUsage: run via server console: /atomicoffe givecoin <player> <amount>")
end)

-- Give starter coins on first join
onEvent("player.join", function(e)
local p = e.player
if not data.has(p.uuid, "coins") then
setCoins(p.uuid, 100)
p.tell("§aYou've been given §e100 starter coins§a!")
end
end)

-- Reward coins for killing mobs
onEvent("entity.killed", function(e)
if not e.player then return end
local rewards = {
["minecraft:zombie"] = 5,
["minecraft:skeleton"] = 8,
["minecraft:creeper"] = 10,
["minecraft:enderman"] = 25,
["minecraft:ender_dragon"] = 500,
}
local entityType = e.killed.type
local reward = rewards[entityType]
if reward then
local uuid = e.player.uuid
setCoins(uuid, getCoins(uuid) + reward)
e.player.sendActionBar("§6+" .. reward .. " coins §e(" .. entityType:gsub("minecraft:", "") .. ")")
end
end)

Player Homes

Let players set and teleport to a personal home location.

-- server_scripts/homes.lua

command.register("sethome", function(ctx)
if not ctx.player then ctx.reply("Player only.") return end
local p = ctx.player
data.set(p.uuid, "home_x", p.pos.x)
data.set(p.uuid, "home_y", p.pos.y)
data.set(p.uuid, "home_z", p.pos.z)
p.tell("§aHome set!")
end)

command.register("home", function(ctx)
if not ctx.player then ctx.reply("Player only.") return end
local p = ctx.player
if not data.has(p.uuid, "home_x") then
p.tell("§cYou haven't set a home yet. Use /sethome first.")
return
end
local x = data.get(p.uuid, "home_x")
local y = data.get(p.uuid, "home_y")
local z = data.get(p.uuid, "home_z")
p.teleport(x, y, z)
p.tell("§aTeleported to your home!")
end)

command.register("delhome", function(ctx)
if not ctx.player then ctx.reply("Player only.") return end
local p = ctx.player
data.delete(p.uuid, "home_x")
data.delete(p.uuid, "home_y")
data.delete(p.uuid, "home_z")
p.tell("§cHome deleted.")
end)

Kill / Death Scoreboard

Track kills and deaths and display a leaderboard via command.

-- server_scripts/stats.lua

scoreboard.createObjective("kills", "Kills")
scoreboard.createObjective("deaths", "Deaths")

onEvent("entity.killed", function(e)
if e.player then
scoreboard.add(e.player.name, "kills", 1)
end
end)

onEvent("player.death", function(e)
scoreboard.add(e.player.name, "deaths", 1)
local k = scoreboard.get(e.player.name, "kills") or 0
local d = scoreboard.get(e.player.name, "deaths") or 0
local kd = d == 0 and k or math.floor((k / d) * 100) / 100
e.player.sendTitle("§cYou died!", "§7K/D: §f" .. kd, 10, 60, 20)
end)

command.register("stats", function(ctx)
if not ctx.player then ctx.reply("Player only.") return end
local p = ctx.player
local k = scoreboard.get(p.name, "kills") or 0
local d = scoreboard.get(p.name, "deaths") or 0
p.tell("§6--- Your Stats ---")
p.tell("§7Kills: §f" .. k)
p.tell("§7Deaths: §f" .. d)
p.tell("§7K/D: §f" .. (d == 0 and k or math.floor((k / d) * 100) / 100))
end)

Rotating Announcements

Cycle through a list of messages at a set interval.

-- server_scripts/announcements.lua

local messages = {
"§b[Info] §fJoin our Discord at §ndiscord.gg/example",
"§b[Info] §fVote for us at §nvoting-site.com",
"§b[Tip] §fUse §e/home §fto teleport to your base!",
"§b[Tip] §fKilling mobs earns you coins. Try §e/balance§f!",
"§b[Info] §fCurrent TPS: §a" .. server.getTps(),
}

local index = 1

-- Announce every 5 minutes (6 000 ticks)
schedule.every(6000, function()
-- Rebuild TPS message each cycle
messages[5] = "§b[Info] §fCurrent TPS: §a" .. string.format("%.1f", server.getTps())
server.broadcast(messages[index])
index = (index % #messages) + 1
end)

Daily Rewards

Give players a reward once every real-world day (86 400 seconds).

-- server_scripts/daily.lua

local REWARD_INTERVAL = 86400 -- seconds in a day

command.register("daily", function(ctx)
if not ctx.player then ctx.reply("Player only.") return end
local p = ctx.player

-- os.time() gives Unix timestamp in seconds
local now = os.time()
local lastClaim = data.get(p.uuid, "daily_last") or 0
local remaining = REWARD_INTERVAL - (now - lastClaim)

if remaining > 0 then
local hours = math.floor(remaining / 3600)
local minutes = math.floor((remaining % 3600) / 60)
p.tell("§cYou've already claimed your daily reward.")
p.tell("§7Next reward in: §e" .. hours .. "h " .. minutes .. "m")
return
end

data.set(p.uuid, "daily_last", now)
p.give("minecraft:diamond", 3)
p.give("minecraft:gold_ingot", 16)
p.addEffect("minecraft:regeneration", 200, 1)
p.tell("§a§lDAILY REWARD CLAIMED!")
p.tell("§7You received: §b3x Diamond, §616x Gold Ingot, §dRegeneration II")
p.sendTitle("§6Daily Reward!", "§aClaimed successfully", 10, 60, 20)
end)

Mob Bounties

Announce rare drops and give a bonus reward when a player kills a named rare mob.

-- server_scripts/bounties.lua

-- Bounties: entity type → { reward item, count, broadcast message }
local bounties = {
["minecraft:elder_guardian"] = {
item = "minecraft:sponge",
count = 5,
message = "§d%s §fslew an §bElder Guardian §fand earned §d5 Sponges§f!",
},
["minecraft:wither"] = {
item = "minecraft:nether_star",
count = 2,
message = "§d%s §fdefeated the §8Wither §fand earned §d2 Nether Stars§f!",
},
["minecraft:ender_dragon"] = {
item = "minecraft:dragon_egg",
count = 1,
message = "§d%s §fconquered the §5Ender Dragon §fand claimed the §5Dragon Egg§f!",
},
}

onEvent("entity.killed", function(e)
if not e.player then return end
local bounty = bounties[e.killed.type]
if not bounty then return end

e.player.give(bounty.item, bounty.count)
server.broadcast(string.format(bounty.message, e.player.name))
e.player.sendTitle("§6Bounty Claimed!", "§e+" .. bounty.count .. "x " .. bounty.item:gsub("minecraft:", ""), 10, 80, 20)
end)

Anti-Fall-Damage Zone

Cancel fall damage for players inside a defined region.

-- server_scripts/safe_zone.lua

-- Define the safe zone corners
local ZONE = { x1=-50, y1=60, z1=-50, x2=50, y2=120, z2=50 }

local function inZone(pos)
return pos.x >= ZONE.x1 and pos.x <= ZONE.x2
and pos.y >= ZONE.y1 and pos.y <= ZONE.y2
and pos.z >= ZONE.z1 and pos.z <= ZONE.z2
end

onEvent("entity.hurt", function(e)
if e.source ~= "fall" then return end
-- e.entity.type for players is "minecraft:player"
-- check position via the player table if attacker is nil
local p = server.getPlayer(e.entity.name)
if p and inZone(p.pos) then
return false -- cancel fall damage
end
end)

Custom Recipes & Loot Together

Add a custom "Emerald Sword" recipe and make it drop from Ender Dragons.

-- server_scripts/emerald_sword.lua

-- Custom shaped recipe: diamond sword + emerald block = emerald sword
-- (uses netherite_sword as a stand-in since custom items aren't in vanilla)
onEvent("recipes", function(e)
e.addShaped("mymod:emerald_sword", "minecraft:netherite_sword 1",
{" E ", " E ", " S "},
{ E = "minecraft:emerald_block", S = "minecraft:stick" }
)
end)

-- Also drop the item from the Ender Dragon loot table
loot.modifyTable("minecraft:entities/ender_dragon", function(e)
e.addDrop("minecraft:emerald_block", 5)
end)

Conditional PvP (Region-Based)

Disable PvP damage between players outside a specific arena region.

-- server_scripts/pvp.lua

local ARENA = { x1=200, y1=64, z1=200, x2=300, y2=100, z2=300 }

local function inArena(pos)
return pos.x >= ARENA.x1 and pos.x <= ARENA.x2
and pos.y >= ARENA.y1 and pos.y <= ARENA.y2
and pos.z >= ARENA.z1 and pos.z <= ARENA.z2
end

onEvent("entity.hurt", function(e)
-- Only care about player-vs-player damage
if not e.attacker then return end
if e.entity.type ~= "minecraft:player" then return end
if e.attacker.type ~= "minecraft:player" then return end

local victim = server.getPlayer(e.entity.name)
local attacker = server.getPlayer(e.attacker.name)
if not victim or not attacker then return end

-- Allow PvP only inside the arena
if not (inArena(victim.pos) and inArena(attacker.pos)) then
attacker.sendActionBar("§cPvP is only allowed in the arena!")
return false -- cancel damage
end
end)

command.register("arena", function(ctx)
if not ctx.player then return end
ctx.player.teleport(250, 65, 250)
ctx.player.tell("§aWelcome to the PvP arena!")
end)

Server Restart Countdown

Warn players before a scheduled restart and kick them gracefully.

-- server_scripts/restart.lua

-- Restart 10 minutes after server starts (12 000 ticks)
-- Change to your preferred interval
local RESTART_TICKS = 12000

schedule.after(RESTART_TICKS - 6000, function()
server.broadcast("§c[!] §fServer restarting in §e5 minutes§f!")
end)
schedule.after(RESTART_TICKS - 2400, function()
server.broadcast("§c[!] §fServer restarting in §e2 minutes§f. Please find a safe spot!")
end)
schedule.after(RESTART_TICKS - 600, function()
server.broadcast("§c[!] §fServer restarting in §e30 seconds§f!")
end)
schedule.after(RESTART_TICKS, function()
local players = server.getPlayers()
for _, p in ipairs(players) do
p.kick("§cServer is restarting. Please reconnect in a moment.")
end
server.runCommand("stop")
end)

HUD Compass & Coordinates

Draw a live coordinate display and a simple compass on the client HUD.

-- client_scripts/hud.lua

client.onHudRender(function(e)
local p = client.getPlayer()
if not p then return end

local sw = e.screenWidth
local x = math.floor(p.x)
local y = math.floor(p.y)
local z = math.floor(p.z)

-- Dark pill behind coordinates
e.drawRect(2, 2, 108, 12, 0xAA000000)
e.drawText(string.format("X %d Y %d Z %d", x, y, z), 4, 4, 0xFFFF55)
end)

Client Keybind → Server Action

Register a client keybind that sends a packet to the server to toggle a buff.

-- client_scripts/keybinds.lua

client.registerKeybind("mymod.buff", "B", function()
client.network.sendToServer("mymod:toggle_buff", { active = true })
client.sendMessage("§aBuff requested!")
end)
-- server_scripts/keybinds.lua

network.onReceive("mymod:toggle_buff", function(player, data)
if data.active then
player.addEffect("minecraft:speed", 200, 1)
player.addEffect("minecraft:strength", 200, 0)
player.tell("§aBuff activated for 10 seconds!")
end
end)

Startup Tag Tweaks

Add custom items to vanilla tags so they work with vanilla recipes and mechanics.

-- startup_scripts/tags.lua

-- Make custom ore mineable with a pickaxe
Tags.add("minecraft:blocks/mineable/pickaxe", "mymod:ruby_ore", "mymod:deepslate_ruby_ore")

-- Make custom ingot a valid beacon payment
Tags.add("minecraft:items/beacon_payment_items", "mymod:ruby_ingot")

-- Add custom logs to the logs tag so they burn in furnaces
Tags.add("minecraft:blocks/logs", "mymod:palm_log", "mymod:palm_wood")
Tags.add("minecraft:items/logs", "mymod:palm_log", "mymod:palm_wood")