Can-Check Hooks
Hook functions that run before shredder actions are executed. Return false to deny with an optional reason.
Can-check hooks allow you to control player actions in zyke_shredder before they execute. Return false with an optional locale key to deny an action and notify the player.
Client hooks return true by default. Server hooks allow every action at a scrapyard shredder, and apply compact.access to props of the compact set.
#File Locations
| Side | File |
|---|---|
| Server | server/unlocked/can_checks.lua |
| Client | client/unlocked/can_checks.lua |
Both files are unencrypted and safe to edit directly. Edit the existing functions inside Shredder.
Types / Classes
All types / classes can be found in
types/types.lua.plyIdis the requesting player's server ID. Server hooks receive the machine'sShredderMachineConfig, or a compact prop'sShredderPlacedConfig; client hooks receive itsid.A compact prop has a
kind(compactfor the shredder,generator, orbox), theowneridentifier of the character who set it up, the routingbucketkey it stands in, and whether it standsindoors. Scrapyard machines have nokind.
#How Reason Strings Work
#Server-side reasons
The server returns the reason to the client, which passes it to Z.notify(), so use a locale key. Missing reasons fall back to "noPermission". Refusals also fire zyke_shredder:OnActionRefused and are written to the activity log when logs.refusals is enabled, except for CanEquipShredderCan.
#Client-side reasons
Client checks also use locale keys and fall back to "noPermission". They provide immediate feedback; enforce trusted restrictions in the corresponding server hook. Add custom reason keys to every resource locale.
This server-side example allows only one scrapyard machine to be started or stopped by players, and leaves compact props alone.
Example:
lua---@param plyId PlayerId ---@param machine ShredderMachineConfig ---@param running boolean ---@return boolean allowed ---@return string? reason function CanOperateShredder(plyId, machine, running) if (not machine.kind and machine.id ~= "sandy_scrapyard") then return false, "noPermission" end return true end
#Compact Access Rules
The shipped server hooks call a local hasAccess helper for compact props. It reads the action's rule from compact.access: "owner" allows the character who set the prop up and admins with compact.admin.permission, and anything else allows everyone. Denied actions return "compactNotOwner".
Keep these calls when you edit a hook, or extend hasAccess itself to add jobs, gangs, or keys.
Example:
lua---@param plyId PlayerId ---@param machine ShredderMachineConfig | ShredderPlacedConfig ---@param action "load" | "operate" | "collect" | "refuel" | "link" | "pickup" ---@return boolean allowed local function hasAccess(plyId, machine, action) if (not machine.kind) then return true end if (access[action] ~= "owner") then return true end if (machine.owner == Z.getIdentifier(plyId)) then return true end return IsShredderCompactAdmin(plyId) end
#Execution & Validation
Keep hooks synchronous and free of side effects. Returning true continues the normal flow; built-in distance, recipe, inventory, fuel, and capacity checks still apply.
Machines stopping by themselves, admin panel actions, the /shreddercompact command, and parts already on the line are not subject to player action hooks.
#Server-Sided Hooks
All server-sided hooks are in server/unlocked/can_checks.lua.
#Can Feed Shredder
Called before a part is loaded onto the infeed, or into a compact shredder's hopper.
itemis the inventory item being loaded.Example:
lua---@param plyId PlayerId ---@param machine ShredderMachineConfig | ShredderPlacedConfig ---@param item Item @ Part being loaded onto the infeed, or into the compact shredder's hopper ---@return boolean allowed ---@return string? reason function CanFeedShredder(plyId, machine, item) if (not hasAccess(plyId, machine, "load")) then return false, "compactNotOwner" end return true end
#Can Unload Shredder
Called before a part is taken back off the infeed.
itemis the part's item name. Scrapyard shredders only.Example:
lua---@param plyId PlayerId ---@param machine ShredderMachineConfig ---@param item string @ Name of the part being taken back off the infeed ---@return boolean allowed ---@return string? reason function CanUnloadShredder(plyId, machine, item) return true end
#Can Operate Shredder
Called before a player starts or stops a machine.
runningistruewhen starting. Also called for the portable generator's switch;machine.kindtells them apart.Example:
lua---@param plyId PlayerId ---@param machine ShredderMachineConfig | ShredderPlacedConfig ---@param running boolean @ Whether the player is starting or stopping it ---@return boolean allowed ---@return string? reason function CanOperateShredder(plyId, machine, running) if (not hasAccess(plyId, machine, "operate")) then return false, "compactNotOwner" end return true end
#Can Collect Shredder Bin
Called before a player takes scrap from the bin. For the compact set,
machineis the catch crate.Example:
lua---@param plyId PlayerId ---@param machine ShredderMachineConfig | ShredderPlacedConfig @ The line's machine, or the catch box ---@return boolean allowed ---@return string? reason function CanCollectShredderBin(plyId, machine) if (not hasAccess(plyId, machine, "collect")) then return false, "compactNotOwner" end return true end
#Can Equip Shredder Can
Called when a player uses a fuel can to take it out. Server only.
Example:
lua---@param plyId PlayerId ---@param item Item @ Fuel can being taken out ---@return boolean allowed ---@return string? reason function CanEquipShredderCan(plyId, item) return true end
#Can Refuel Shredder
Called before the can in hand is poured into a generator. For the compact set,
machineis the portable generator.Example:
lua---@param plyId PlayerId ---@param machine ShredderMachineConfig | ShredderPlacedConfig @ The line's machine, or the portable generator ---@param item Item @ Can in hand being poured into the generator ---@return boolean allowed ---@return string? reason function CanRefuelShredder(plyId, machine, item) if (not hasAccess(plyId, machine, "refuel")) then return false, "compactNotOwner" end return true end
#Can Place Shredder Prop
Called before a compact prop is set up from its item, once the room and the distance are fine. The admin command does not pass through here.
Example:
lua---@param plyId PlayerId ---@param kind ShredderPlacedKind ---@param coords vector4 @ Where it would stand ---@return boolean allowed ---@return string? reason function CanPlaceShredderProp(plyId, kind, coords) return true end
#Can Pickup Shredder Prop
Called before a compact prop is packed back into its item, ahead of the wait and of what it holds or is linked to.
Example:
lua---@param plyId PlayerId ---@param machine ShredderPlacedConfig ---@return boolean allowed ---@return string? reason function CanPickupShredderProp(plyId, machine) if (not hasAccess(plyId, machine, "pickup")) then return false, "compactNotOwner" end return true end
#Can Link Shredder
Called at both ends of the cable: taking it off the generator, plugging it into the shredder, and pulling it out again.
linkingisfalsewhen the cable is being pulled out.Example:
lua---@param plyId PlayerId ---@param machine ShredderPlacedConfig @ The generator or the shredder the player stands at ---@param linking boolean @ false when the cable is being pulled out ---@return boolean allowed ---@return string? reason function CanLinkShredder(plyId, machine, linking) if (not hasAccess(plyId, machine, "link")) then return false, "compactNotOwner" end return true end
#Get Shredder Bucket Key
Returns the key a routing bucket is known by, 64 characters at most. A compact prop is saved under the key of the bucket it was set up in and only exists for players whose bucket has the same key. When your housing hands out bucket numbers anew each restart, return a key that stays the same, such as the apartment the player is in.
Example:
lua---@param bucket integer @ Routing bucket the player is in ---@param plyId PlayerId ---@return string key @ 64 characters at most function GetShredderBucketKey(bucket, plyId) return tostring(bucket) end
#Is Shredder Prop Indoors
Decides whether a compact prop being set up stands indoors, where a running generator's fumes build up.
reportedis what the player's client found throughIsShredderPlacementIndoors.Example:
lua---@param plyId PlayerId ---@param coords vector4 @ Where it is set up ---@param bucket integer @ Routing bucket the player is in ---@param reported boolean ---@return boolean indoors function IsShredderPropIndoors(plyId, coords, bucket, reported) if (reported) then return true end return fumes.bucketsAreIndoors == true and bucket ~= 0 end
#Can Sell Scrap
Called before a player sells scrap to a buyer.
buyeris the entry frombuyer.positions.Example:
lua---@param plyId PlayerId ---@param buyer ShredderBuyerPosition ---@return boolean allowed ---@return string? reason function CanSellScrap(plyId, buyer) return true end
#Client-Sided Hooks
All client-sided hooks are in client/unlocked/can_checks.lua. The server re-validates every action.
#Can Feed Shredder
Called before the loading flow starts.
slotis the inventory slot of the part.Example:
lua---@param machineId string ---@param slot integer @ Inventory slot of the part being loaded ---@return boolean allowed ---@return string? reason function CanFeedShredder(machineId, slot) return true end
#Can Unload Shredder
Called before a part is taken back off the infeed.
loadIdidentifies the part on the belt.Example:
lua---@param machineId string ---@param loadId string @ Part riding the infeed being taken back off ---@return boolean allowed ---@return string? reason function CanUnloadShredder(machineId, loadId) return true end
#Can Operate Shredder
Called before the start or stop request is sent.
Example:
lua---@param machineId string ---@param running boolean @ Whether the player is starting or stopping it ---@return boolean allowed ---@return string? reason function CanOperateShredder(machineId, running) return true end
#Can Collect Shredder Bin
Called before the bin menu collects scrap.
Example:
lua---@param machineId string ---@return boolean allowed ---@return string? reason function CanCollectShredderBin(machineId) return true end
#Can Refuel Shredder
Called before pouring starts at the generator's filler.
Example:
lua---@param machineId string ---@return boolean allowed ---@return string? reason function CanRefuelShredder(machineId) return true end
#Can Place Shredder Prop
Called before the placement preview of a compact prop starts, and again as it is confirmed.
coordsisnilbefore the preview has started.Example:
lua---@param kind ShredderPlacedKind @ "compact" for the shredder, "generator" or "box" ---@param coords? vector4 @ Where the preview stands, nil before it has started ---@return boolean allowed ---@return string? reason function CanPlaceShredderProp(kind, coords) return true end
#Can Pickup Shredder Prop
Called before the pack-up request is sent.
Example:
lua---@param machineId string ---@return boolean allowed ---@return string? reason function CanPickupShredderProp(machineId) return true end
#Can Link Shredder
Called before a cable is plugged in or pulled out.
machineIdis the generator or the shredder the player stands at.Example:
lua---@param machineId string @ The generator or the shredder the player stands at ---@param linking boolean @ false when the cable is being pulled out ---@return boolean allowed ---@return string? reason function CanLinkShredder(machineId, linking) return true end
#Is Shredder Placement Indoors
Reports whether a compact prop set up at
coordsstands indoors. The result is sent along as the prop is placed. Returntruefor shells and other builds the game does not know as an interior.Example:
lua---@param coords vector4 ---@return boolean indoors function IsShredderPlacementIndoors(coords) return GetInteriorFromEntity(PlayerPedId()) ~= 0 or GetInteriorAtCoords(coords.x, coords.y, coords.z + 0.5) ~= 0 end
#Can Sell Scrap
Called before the sell request is sent.
buyerIndexis the index inbuyer.positions.Example:
lua---@param buyerIndex integer ---@return boolean allowed ---@return string? reason function CanSellScrap(buyerIndex) return true end
#Common Patterns
#Restrict Compact Shredders to a Job
Denies setting up any compact prop unless the player has the job.
Example:
lua---@param plyId PlayerId ---@param kind ShredderPlacedKind ---@param coords vector4 ---@return boolean allowed ---@return string? reason function CanPlaceShredderProp(plyId, kind, coords) if (not Z.isJob(plyId, "scrapyard")) then return false, "noPermission" end return true end
#Restrict the Scrap Buyer to a Job
Uses the server hook so the restriction cannot be bypassed from the client.
Example:
lua---@param plyId PlayerId ---@param buyer ShredderBuyerPosition ---@return boolean allowed ---@return string? reason function CanSellScrap(plyId, buyer) if (not Z.isJob(plyId, "scrapyard")) then return false, "noPermission" end return true end