RedM documentation

Murphy's Telegram & Mail

Advanced

Player Home Mailboxes


murphy_post allows other resources (housing, camps, admin tools...) to register physical mailbox props in the world, tied to a specific player. Players can then check their personal inbox directly from home.

Configuration

In config/config.lua:

lua
-- Prop spawn/despawn distance (in game units)
Config.PlayerMailboxStreamDistance = 50.0
-- Allow sending mail from home mailbox (true) or receive only (false)
Config.PlayerMailboxSendEnabled = false
-- Discord webhook notification when a mailbox is registered (leave empty to disable)
Config.DiscordWebhook = 'https://discord.com/api/webhooks/...'
Config.DiscordWebhookName = 'Murphy Post'

Exports API

All exports are server-side only.

RegisterPlayerMailbox

Registers a new mailbox. A prop is spawned client-side and an interaction point is created automatically.

lua
local result = exports.murphy_post:RegisterPlayerMailbox({
coords = { x = 100.0, y = 200.0, z = 50.0 }, -- Required: world position
heading = 90.0, -- Optional: prop heading (default 0)
propModel = 'p_mailbox01x', -- Optional: RedM prop model (default 'p_mailbox01x')
ownerIdentifier = '32', -- Required: character identifier (charidentifier for VORP)
label = "John's Mailbox", -- Optional: display name
externalId = 'housing_plot_42', -- Optional: your own unique key for later removal
})
-- result = { ok = true, id = 1 } -- success (id = database ID)
-- result = { ok = false, error = '...' } -- failure

Parameters:

Field Type Required Description
coords {x, y, z} Yes World position for the prop
heading number No Prop heading in degrees (default: 0)
propModel string No RedM prop model name (default: p_mailbox01x)
ownerIdentifier string/number Yes Character identifier of the mailbox owner
label string No Display name shown in the interaction
externalId string No Your own unique identifier for later retrieval/removal

Error codes: no_data, missing_coords, invalid_coords, missing_owner_identifier, duplicate_external_id, db_insert_failed

UnregisterPlayerMailbox

Removes a mailbox. The prop is despawned and the interaction removed for all players.

lua
-- By database ID:
local result = exports.murphy_post:UnregisterPlayerMailbox(1)
-- By external ID:
local result = exports.murphy_post:UnregisterPlayerMailbox('housing_plot_42')
-- result = { ok = true }
-- result = { ok = false, error = 'mailbox_not_found' }

GetPlayerMailboxes

Returns a list of registered mailboxes. Optionally filter by owner.

lua
-- All mailboxes:
local all = exports.murphy_post:GetPlayerMailboxes()
-- Only for a specific owner:
local mine = exports.murphy_post:GetPlayerMailboxes('32')
-- Returns: {
-- { id = 1, externalId = 'housing_plot_42', ownerIdentifier = '32',
-- label = "John's Mailbox", coords = {x=100, y=200, z=50},
-- heading = 90.0, propModel = 'p_mailbox01x' },
-- ...
-- }

How it works

  • Registered mailboxes are persisted in the database (post_player_mailboxes table) and survive server restarts.
  • On resource start, all mailboxes are loaded from DB and synced to connected players.
  • When a player is within Config.PlayerMailboxStreamDistance, the prop is spawned and an interaction point is created.
  • Clicking the interaction opens the player's personal inbox (same as at a post office).
  • If Config.PlayerMailboxSendEnabled = true, the full postal UI opens (send + receive). If false, only the inbox is shown.
  • The inbox is tied to the interacting player, not the mailbox owner. This means anyone can click the mailbox, but they will only see their own inbox (server-side filtering).

Integration examples

Housing resource

When a player buys a house:

lua
-- server-side, in your housing resource
local result = exports.murphy_post:RegisterPlayerMailbox({
coords = property.mailboxCoords,
heading = property.mailboxHeading,
propModel = 'p_mailbox01x',
ownerIdentifier = tostring(player.charIdentifier),
label = property.name .. ' Mailbox',
externalId = 'property_' .. property.id,
})

When a player sells/loses the house:

lua
exports.murphy_post:UnregisterPlayerMailbox('property_' .. property.id)

Admin command

See the full example resource in examples/murphy_post_mailbox_example/ which provides:

  • /createmailbox [label] - Creates a mailbox at your current position
  • /removemailbox [id] - Removes a mailbox by its database ID
  • /mymailboxes - Lists your registered mailboxes

To use it, copy the murphy_post_mailbox_example folder to your server's resources directory and add it to your server.cfg.

Discord Webhook

When Config.DiscordWebhook is set, a Discord notification is sent each time a new mailbox is registered via RegisterPlayerMailbox. The embed includes the owner name, label, and coordinates.

Database

The post_player_mailboxes table is auto-created on first startup. Schema:

sql
CREATE TABLE IF NOT EXISTS `post_player_mailboxes` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`external_id` VARCHAR(64) NULL,
`owner_identifier` VARCHAR(64) NOT NULL,
`label` VARCHAR(128) NULL,
`coord_x` FLOAT NOT NULL,
`coord_y` FLOAT NOT NULL,
`coord_z` FLOAT NOT NULL,
`heading` FLOAT NOT NULL DEFAULT 0.0,
`prop_model` VARCHAR(64) NOT NULL DEFAULT 'p_mailbox01x',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_external` (`external_id`),
INDEX `idx_owner` (`owner_identifier`)
);

Last updated: April 7, 2026