RedM documentation

Murphy's Craft

Advanced Usage

murphy_craft 1.14.0 - New Configuration Options


Quick reference for every option added in 1.14.0. All of them are optional: an untouched pre-1.14.0 config keeps working exactly as before.


1. Config.AllowClientXPRequests

File: shared/config.lua - Default: false

lua
Config.AllowClientXPRequests = false

Controls the client-side RequestAddXP export (murphy_craft:RequestAddXP network event). It is now blocked by default because any modified client can call it to grant itself XP.

  • Keep false unless one of your scripts really grants craft XP from the client side.
  • The safe alternative is to grant XP from your server scripts:
    TriggerEvent('murphy_craft:AddXP', source, 'docteur', 50)
    
  • Even when enabled, requests are validated (known specialisation only, max 1000 XP per request).

2. Alternative tools - anyOf groups

File: any recipe in shared/craft/*.lua

Tools are items the player must own but that are not consumed. Until now every listed tool was required. You can now offer alternatives: wrap them in an anyOf group, and owning any single one is enough.

lua
tools = {
-- classic form: this exact item is required
{ name = "Hammer", item = "hammer", uses = 10 },
-- new form: bone knife OR regular knife, either one works
{ anyOf = {
{ name = "Bone knife", item = "bone_knife", uses = 5 },
{ name = "Knife", item = "WEAPON_MELEE_KNIFE" },
}},
}

Notes:

  • Both forms can be mixed freely in the same tools list.
  • The menu shows the group as one line ("Bone knife / Knife") with a single Owned/Required state.
  • Durability (uses): the first owned alternative in the list order is the tool that loses durability, if it declares uses.
  • Fully validated server-side - a modified client cannot skip the tool check.

3. Station job lock - job / jobgrade

File: Config.CraftingStations entries in shared/config.lua

Crafting stations (furnace-type, with ingredients/production/output) can now be restricted to a job, with the same syntax as recipes:

lua
{
uniqueId = "furnace",
cat = { "furnace" },
-- ...
job = "blacksmith", -- string, or table: { "blacksmith", "gunsmith" }
jobgrade = 2, -- optional minimum grade
}

Behavior: players without the job get a notification when trying to open the station, and the server rejects every station action (open, deposit, retrieve) as well - it is not just hidden client-side.


4. Station specialisation lock - requiredSpecialisation

File: Config.CraftingStations entries in shared/config.lua

Locks a station behind a node of the skill-tree system - something job cannot express, and tree_ref could not either (it only works inside the recipe's own category).

lua
{
uniqueId = "furnace",
cat = { "furnace" },
-- ...
requiredSpecialisation = {
id = "armurier", -- Specialisation[x].id - ANY tree, not just the station's category
node = "root", -- node of SpecialisationRecipes[id] that must be unlocked (default: "root")
},
}

Notes:

  • id can reference any specialisation tree. A furnace station can require a node from the armurier tree, for example.
  • node = "root" simply requires the specialisation to be unlocked at all; use a deeper node id to require progression.
  • Same behavior as timelimit: the station is treated as unavailable - client shows a notification, and the server rejects every station action, so a modified client cannot bypass it.
  • Can be combined with job/jobgrade and timelimit (all must pass).

5. Held prop during crafting - animation.prop

File: any animation block (CraftingTables / CraftingProps / CraftingStations / Config.DefaultAnimation)

Spawns a prop in the character's hand while the crafting menu is open - e.g. a ladle to stir a cauldron. The prop is deleted automatically when the menu closes.

lua
animation = {
type = "scenario",
scenario = "WORLD_HUMAN_CROUCH_INSPECT",
prop = {
model = "p_ladle01x", -- prop model to hold
bone = 54565, -- bone id or bone name (default: 54565, right hand)
offset = vector3(0.0, 0.0, 0.0), -- position offset on the bone
rotation = vector3(0.0, 0.0, 0.0), -- rotation of the prop
},
}

Tip: many RDR3 scenarios already include their own props handled by the game engine - try the scenario alone first, and only add prop if it doesn't come with one.


6. Walk to the workstation - animation.walkTo

File: any animation block

Makes the character walk to a position and face a heading before starting the animation. The menu opens immediately; the walk happens in the background, so the character strolls to the bench and starts working while the player browses recipes.

lua
animation = {
type = "scenario",
scenario = "WORLD_HUMAN_BLACKSMITH",
walkTo = vector4(2949.8, 562.5, 43.7, 90.0), -- x, y, z, heading
}
  • The walk is cancelled automatically if the menu closes before arrival.
  • Works with both animation types, the default animation, and combined with prop.

See ANIMATION_SYSTEM.md for the full animation documentation.


7. For developers - RegisterStationRecipes (server export)

Since 1.14.0, station crafting is validated against the server's recipe table. If one of your resources injects station recipes at runtime (instead of shipping a shared/station/*.lua file), it must register them server-side too:

lua
-- server-side, raw config shape (same as shared/station/*.lua)
exports['murphy_craft']:RegisterStationRecipes("tannery", {
{
name = "Leather",
duration = 30,
ingredients = { { name = "Pelt", item = "pelt", amount = 2 } },
output = { { name = "Leather", item = "leather", amount = 1 } },
},
})

Without this, the server rejects those recipes with "unknown station recipe". Resources that only use categories shipped in shared/station/*.lua need no change.


Reminder - updating a customized config

If you customized shared/config.lua or shared/locales.lua, you only need to merge in:

  • Config.AllowClientXPRequests = false
  • the translation keys station_locked_job, station_locked_spe, spe_conditions_not_met, spe_unlock_failed (in each language)

Everything else in this update is new optional fields you opt into per recipe/station.


Last updated: September 9, 2026