Skip to content

Wizards of Lua — Frequently Asked Questions


Where do I save my custom scripts?

Place your .lua scripts in the config/wizards-of-lua/ directory or any of its subfolders. You can organize them however you like and reference them from other scripts or the /lua command using Lua’s require keyword.


How can I include a script file from the /lua command?

For example, if a script file is located at config/wizards-of-lua/mickkay/hello.lua, you can include it like this:

/lua require "mickkay.hello"

How do I cast a spell in the Nether?

By default, a spell is created in the same dimension as the caster. You have three options for casting in the Nether:

  • Cast directly while inside the Nether. The spell stays active even after you leave.
  • Cast remotely using the /execute in command:
/execute in the_nether run lua print("This spell is at " .. spell.pos:floor() .. " in " .. spell.world.dimension)
  • Move an existing spell to the Nether by assigning its world:
/lua spell.world = spell.server:getWorld("the_nether"); print("This spell is at " .. spell.pos:floor() .. " in " .. spell.world.dimension)

How do I cast a spell on server startup?

Create a file named startup.lua inside the config/wizards-of-lua/ folder or one of its subdirectories:

print("This is executed during the startup sequence")

At startup, the mod recursively searches for all startup.lua files and launches them. Files in upper directories run first, and subdirectory files are launched afterward.

Tip: You can manually trigger the startup sequence with:

/wol startup


How long does a spell stay active?

A spell is a running Lua script that continues until it completes or is stopped. It runs on the main game thread until it either completes or hits the per-tick limit (currently 50,000 Lua operations). When that limit is reached, execution automatically pauses and picks up exactly where it left off at the start of the next tick — much like a coroutine yielding and resuming.

Note: A spell is not literally a Lua coroutine you control yourself — you can't call coroutine.yield() to suspend it. Use sleep(n) instead (see below).

You can call sleep(n) to pause your spell for n game ticks, even if you haven’t reached the per-tick limit. Once the sleep period ends, execution automatically resumes.


How do I stop all active spells?

You can break all your active spells using:

/wol spell break

This is especially helpful if a spell enters an infinite loop or causes unexpected behavior.


How do I hide spell output?

An active spell sends feedback in two cases:

  1. When you use print(...), its output is sent as command feedback.
  2. When you run commands using spell:execute(...), their output is also sent as command feedback.

You can globally suppress all command feedback using this gamerule:

/gamerule sendCommandFeedback false

However, this is often too broad, as it affects all commands. You can achieve better results by only suppressing the output of spells:

Suppressing print(...) Output

Use log(...) instead of print(...). This logs messages through the WizardsOfLua.log system, which gives you fine-grained control.

You can configure the log target by setting the WizardsOfLua.log property to one of:

  • "source" — the command source that ran the spell
  • "operators" — all online operators
  • "console" — only the server console
  • "none" — discard all output

Suppressing Command Feedback from spell:execute(...)

Instead of spell:execute(...), use spell:executeSilent(...)

This executes the command without sending any feedback to the command source. You can still capture the output manually with a Trace object if needed.


How do I evaluate Placeholder API placeholders in my scripts?

Placeholder API is a Fabric mod that lets other mods expose dynamic text placeholders, such as %player:name% or %world:player_count%. If you install it into your mods folder alongside Wizards of Lua, you can resolve these placeholders from Lua.

  • Use Spell:evaluate(text) for placeholders that don't depend on a specific entity, such as server- or world-related ones:
local text = "Number of players online: %world:player_count%"
local value = spell:evaluate(text)
print(value)
  • Use Entity:evaluate(text) for placeholders that resolve relative to a specific entity, such as a player:
local player = spell.owner
local text = "%player:name%'s ping: %player:ping%"
local value = player:evaluate(text)
print(value)

Both methods return the input text with all recognized placeholders replaced by their current values. If the Placeholder API jar is not present in the mods folder, these methods are unavailable.

Tip: See the Placeholder API documentation for the full list of placeholders provided by it and other installed mods.


How do I add a custom method to an existing class?

You can extend any Wizards of Lua class (such as Entity, Spell, Vec3, etc.) by defining new methods in your own Lua files.

For example, to add a say method to all Entity objects, place the following code in a new file — for example, extensions.lua:

function Entity:say(text)
  spell:execute("execute as " .. self.uuid .. " run say " .. text)
end

Usage

To use this in your script, load the file using require:

require "extensions"

spell.owner:say("Hi there!")
This will make the spell caster say “Hi there!” in chat.

Note: You must include require "extensions" in every script where you want to use say.


How do I override an existing method?

You can override existing methods of Wizards of Lua classes by saving a reference to the original method and then redefining it with custom behavior.

For example, to log a message every time a script calls Entity:dropItem(...), place the following code in a new file — for example, extensions.lua:

local _dropItem = Entity.dropItem

function Entity:dropItem(object, yOffset)
  log("dropping item " .. object.name)
  return _dropItem(self, object, yOffset)
end

This wraps the original method and adds a log message before calling the original implementation.

Usage

To use the overridden method, load the file using require:

require "extensions"

local item = spell.owner:dropItem(Item:new("diamond_sword"), 4)

This will print dropping item diamond_sword to the log and drop the item as usual.

Note: You must include require "extensions" in every script where you want the overridden method to apply.


Fabric or NeoForge: what is different?

Spells run the same on both loaders, with these exceptions, which work on Fabric only:

  • PermissionCheckEvent: spells can't answer permission checks on NeoForge.
  • Permission nodes of dynamic commands from any permissions mod: on NeoForge only LuckPerms answers them, since NeoForge knows only the nodes that exist when the server starts. The nodes of WoL's own commands work with any permissions mod on both loaders.
  • Placeholder API placeholders: Placeholder API is a Fabric mod.

A spell can ask which loader it runs on: WizardsOfLua.loader is "fabric" or "neoforge".

Moving a world between the loaders: from Minecraft 1.21.6 on, each loader stores the extra data of entities in a place of its own, so a world moved from Fabric to NeoForge, or back, loses it. Up to 1.21.5 it is part of the entity's NBT on both loaders and moves with the world.


Which LuckPerms version works on NeoForge?

On most Minecraft versions, use the newest LuckPerms for your version. On three versions that build doesn't work with current NeoForge, with or without Wizards of Lua (see LuckPerms #4259). Use a build made for a later Minecraft version instead:

Minecraft NeoForge tested Build for this version Use instead
1.21.1 21.1.264 5.4.140: players are kicked with "Invalid player data" 5.4.150, listed for 1.21.4
1.21.4 21.4.161 5.4.150: the server doesn't start 5.4.158, listed for 1.21.5
1.21.5 21.5.101 5.5.0: the server doesn't start 5.5.10, listed for 1.21.6 to 1.21.8

Launchers and version filters won't offer these builds for your Minecraft version: download the JAR from LuckPerms' version list and put it into the mods folder.

On 1.21.5, build 5.5.10 logs a NoSuchMethodError from its context calculator. Permissions work, but LuckPerms rules that depend on a world or game mode may not apply.

On Fabric the newest LuckPerms for your version works, with two notes: Modrinth lists no LuckPerms for 1.21.2, so use 5.4.145, listed for 1.21.3. And on 26.1.1 current LuckPerms builds need a recent Fabric API.


What's next?