Skip to main content

Overview

The world global provides access to the current world state, including player information, tile data, and world objects.

Player Access

Get Local Player

world:get_local_player
function
Returns the local player (your character), or nil if not in a world.
local player = world:get_local_player()
if player then
    logger.info("My name: {}", player.name)
    logger.info("Position: ({}, {})", player.position.x, player.position.y)
end

Get All Players

world:get_players
function
Returns a table mapping net IDs to player objects.
local players = world:get_players()
for net_id, player in pairs(players) do
    logger.info("Player {}: {} at ({}, {})",
        net_id, player.name, player.position.x, player.position.y
    )
end

Get Player by Net ID

world:get_player
function
net_id
number
required
The network ID of the player
Returns the player with the specified net ID, or nil if not found.
local player = world:get_player(12345)
if player then
    logger.info("Found player: {}", player.name)
end

Get Local Net ID

world:get_local_net_id
function
Returns the local player’s network ID, or -1 if not in a world.
local net_id = world:get_local_net_id()
if net_id >= 0 then
    logger.info("My net ID: {}", net_id)
end

Player Properties

net_id
number
Network ID of the player (unique per world session)
user_id
number
User ID (unique account identifier)
name
string
Player’s display name
country_code
string
Two-letter country code (e.g., “US”, “GB”)
position
Vec2
Player position with x and y coordinates
local pos = player.position
logger.info("X: {}, Y: {}", pos.x, pos.y)
collision
Vec4
Collision box with x, y, z, w dimensions
local col = player.collision
logger.info("Collision: {}, {}, {}, {}", col.x, col.y, col.z, col.w)
invisible
number
Invisibility level (0 = visible)
mod_state
number
Moderator state
supermod_state
number
Super moderator state
is_local
boolean
true if this is the local player, false otherwise

World Data Access

Get World Version

world:get_version
function
Returns the world version number.
logger.info("World version: {}", world:get_version())

Get Tile Map

world:get_tile_map
function
Returns the world’s tile map.
local tile_map = world:get_tile_map()
local size = tile_map:get_size()
logger.info("World size: {}x{}", size.x, size.y)

Get Object Map

world:get_object_map
function
Returns the world’s object map (dropped items).
local object_map = world:get_object_map()
local objects = object_map:get_objects()
logger.info("Number of objects: {}", #objects)

Tile Map API

Get Tile Map Size

local tile_map = world:get_tile_map()
local size = tile_map:get_size()
logger.info("Width: {}, Height: {}", size.x, size.y)

Get All Tiles

local tile_map = world:get_tile_map()
local tiles = tile_map:get_tiles()

for i, tile in ipairs(tiles) do
    logger.info("Tile {} - FG: {}, BG: {}", i, tile.foreground, tile.background)
end

Tile Properties

foreground
number
Foreground block item ID
background
number
Background block item ID
extra
TileExtra
Extra tile data (doors, signs, etc.)
if tile.extra:has_value() then
    local door = tile.extra:get_as_door()
    if door then
        logger.info("Door label: {}", door.label)
    end
end

Object Map API

Get All Objects

local object_map = world:get_object_map()
local objects = object_map:get_objects()

for i, obj in ipairs(objects) do
    logger.info("Object {} - ID: {}, Amount: {}", i, obj.item_id, obj.amount)
end

Object Properties

item_id
number
The item ID of the dropped object
pos
Vec2
Position of the object in the world
logger.info("Object at ({}, {})", obj.pos.x, obj.pos.y)
amount
number
Number of items in the stack

Examples

Player Position Tracker

command.register("pos", "Show your position", function(ctx)
    local player = world:get_local_player()
    
    if not player then
        ctx:reply("`4Error: ``Not in a world")
        return false
    end
    
    ctx:reply("`2Position: ``({}, {})", player.position.x, player.position.y)
    ctx:reply("`2Net ID: ``{}", player.net_id)
    
    return true
end)

List All Players

command.register("players", "List all players", function(ctx)
    local players = world:get_players()
    local count = 0
    
    for net_id, player in pairs(players) do
        count = count + 1
    end
    
    ctx:reply("`2Players in world: ``{}", count)
    
    for net_id, player in pairs(players) do
        local marker = player.is_local and "`2(You)`` " or ""
        ctx:reply("  {}[{}] {}", marker, net_id, player.name)
    end
    
    return true
end)

Track Player Movement

local last_position = nil

scheduler.schedule_periodic(1000, function()
    local player = world:get_local_player()
    
    if player then
        local current_pos = player.position
        
        if last_position then
            local dx = current_pos.x - last_position.x
            local dy = current_pos.y - last_position.y
            local distance = math.sqrt(dx * dx + dy * dy)
            
            if distance > 0 then
                logger.info("Moved {:.2f} tiles", distance)
            end
        end
        
        last_position = { x = current_pos.x, y = current_pos.y }
    end
    
    return true
end)

World Information

event.on("server:SendMapData", function(ctx)
    if ctx:has_packet() then
        local tile_map = world:get_tile_map()
        local size = tile_map:get_size()
        
        logger.info("World loaded: {}x{}", size.x, size.y)
        logger.info("World version: {}", world:get_version())
        
        local object_map = world:get_object_map()
        local objects = object_map:get_objects()
        logger.info("Dropped items: {}", #objects)
    end
end)

Find Specific Player

command.register("findplayer", "Find a player by name", function(ctx)
    if #ctx.args < 1 then
        ctx:reply("Usage: /findplayer <name>")
        return false
    end
    
    local search_name = ctx.args[1]:lower()
    local players = world:get_players()
    local found = {}
    
    for net_id, player in pairs(players) do
        if player.name:lower():find(search_name) then
            table.insert(found, player)
        end
    end
    
    if #found == 0 then
        ctx:reply("`4No players found matching '{}'", ctx.args[1])
    else
        ctx:reply("`2Found {} player(s):", #found)
        for _, player in ipairs(found) do
            ctx:reply("  [{}] {} ({})", player.net_id, player.name, player.country_code)
        end
    end
    
    return true
end)

Tile Scanner

command.register("scan", "Scan world for blocks", function(ctx)
    if #ctx.args < 1 then
        ctx:reply("Usage: /scan <item_id>")
        return false
    end
    
    local item_id = tonumber(ctx.args[1])
    if not item_id then
        ctx:reply("`4Error: ``Invalid item ID")
        return false
    end
    
    local tile_map = world:get_tile_map()
    local tiles = tile_map:get_tiles()
    local count = 0
    
    for i, tile in ipairs(tiles) do
        if tile.foreground == item_id or tile.background == item_id then
            count = count + 1
        end
    end
    
    ctx:reply("`2Found {} tiles with item ID {}", count, item_id)
    return true
end)

Object Collector Info

command.register("objects", "List dropped objects", function(ctx)
    local object_map = world:get_object_map()
    local objects = object_map:get_objects()
    
    if #objects == 0 then
        ctx:reply("`4No objects in world")
        return true
    end
    
    ctx:reply("`2Dropped objects: ``{}", #objects)
    
    local item_counts = {}
    for _, obj in ipairs(objects) do
        item_counts[obj.item_id] = (item_counts[obj.item_id] or 0) + obj.amount
    end
    
    for item_id, amount in pairs(item_counts) do
        local item = item_database:get_item(item_id)
        local name = item and item.item_name or "Unknown"
        ctx:reply("  {} x{}", name, amount)
    end
    
    return true
end)

Player Spawn Tracker

local spawn_times = {}

event.on("OnSpawn", function(ctx)
    if ctx:has_packet() then
        local pkt = ctx:get_packet()
        spawn_times[pkt.net_id] = os.time()
        
        local player = world:get_player(pkt.net_id)
        if player then
            logger.info("Player {} spawned at ({}, {})",
                player.name,
                player.position.x,
                player.position.y
            )
        end
    end
end)

command.register("uptime", "Show player uptime", function(ctx)
    local player = world:get_local_player()
    if not player then
        ctx:reply("`4Error: ``Not in a world")
        return false
    end
    
    local spawn_time = spawn_times[player.net_id]
    if spawn_time then
        local uptime = os.time() - spawn_time
        local minutes = math.floor(uptime / 60)
        local seconds = uptime % 60
        
        ctx:reply("`2Uptime: ``{}m {}s", minutes, seconds)
    else
        ctx:reply("`4No spawn time recorded")
    end
    
    return true
end)

Best Practices

Always check if player exists
local player = world:get_local_player()
if not player then
    -- Not in a world
    return
end

-- Safe to use player
Use net_id for player trackingNet IDs are unique within a world session and are the best way to track players:
local tracked_players = {}

event.on("OnSpawn", function(ctx)
    if ctx:has_packet() then
        local pkt = ctx:get_packet()
        tracked_players[pkt.net_id] = pkt.name
    end
end)
Cache world data when neededIf you need to access world data frequently, cache it:
local world_size = nil

event.on("server:SendMapData", function(ctx)
    local tile_map = world:get_tile_map()
    world_size = tile_map:get_size()
    logger.info("World size cached: {}x{}", world_size.x, world_size.y)
end)

See Also

Events API

Track player and world events

Items API

Look up item information