Configuration
Overview
shared/config.lua: Core settings, features, the recycler definition, recipes, upgrades, durability, fuel, fixed stationsshared/data/item_models.lua: 3D prop mappings for the sinking animationserver/config_server.lua: Discord webhooks and rate limiting
The recipes and upgrades shipped in shared/config.lua are working examples. Replace them with the items your server uses.
General
1Config.Debug = false
2Config.Language = 'en'
3Config.Theme = 'default'
4Config.MaxRecyclersPerPlayer = 1
5Config.DuiResolution = { width = 1920, height = 1080 }
6Config.InteractionDistance = 3.0
7Config.PlacementDistance = 5.0Debug: Console output for troubleshootingLanguage: Locale code. See thelocales/folder.Theme: Visual theme for the screen. The shipped theme is'default'.MaxRecyclersPerPlayer: Maximum player-placed recyclers per characterDuiResolution: Render resolution of the screen on the prop.960x540is lighter,1920x1080is sharperInteractionDistance: Range in meters to interact with a placed machinePlacementDistance: Maximum distance from the player a new machine can be placed
Placement Rules
1Config.PlacementRestriction = {
2 enabled = false,
3 radius = 25.0,
4 requiredProps = {},
5}
6
7Config.PickupCooldown = {
8 enabled = true,
9 seconds = 300,
10}PlacementRestriction.enabled: Whentrue, a recycler can only be placed withinradiusmeters of one of the prop model hashes inrequiredPropsPickupCooldown.enabled: Locks pickup forsecondsafter placing, blocking place-then-instant-pickup abuse
Feature Toggles
1Config.Features = {
2 bulkRecycling = true,
3 queueSystem = true,
4 fuelSystem = true,
5 breakdownAnimations = true,
6 ambientSounds = true,
7 propSinking = true,
8 lootReveal = true,
9 upgradeSystem = true,
10 durabilitySystem = true,
11}bulkRecycling: Insert a stack of the same item in one actionqueueSystem: Items queue when all slots are busy and auto-promote as slots free upfuelSystem: Fuel is consumed while processing. Whenfalse, the fuel bar is hidden and refuel/consumption are disabledbreakdownAnimations: Particle effects during processingambientSounds: 3D loop sound through xsound while runningpropSinking: Inserted item models sink into the slot as they processlootReveal: Show the loot preview before collectingupgradeSystem: Allow upgrade installationdurabilitySystem: Degradation, slowdown, malfunction and repair
The Recycler
1Config.Recycler = {
2 label = _L('recycler_label'),
3 item = 'recycler',
4 baseSlots = 3,
5 maxSlots = 6,
6 processSpeedMultiplier = 1.0,
7 spawnDistance = 50.0,
8 screenDistance = 10.0,
9}label: Name shown in the UI and notificationsitem: Inventory item used to place the recyclerbaseSlots: Slots available before upgrades (each slot processes one item)maxSlots: Absolute slot cap. Base plus a slot-expansion upgrade can never exceed thisprocessSpeedMultiplier: Base speed.1.0is normal, below1.0is fasterspawnDistance: Distance at which the prop streams in for nearby playersscreenDistance: Distance at which the screen becomes visible
Recipes can gate outputs and bonuses behind a recycler tier. The recycler runs at tier 1 by default. Add tier = 2 (or 3) to Config.Recycler to unlock higher-tier outputs and bonuses everywhere.
Fuel
Read only when Config.Features.fuelSystem = true.
1Config.Fuel = {
2 capacity = 100,
3 perMinute = 2,
4 items = {
5 ['industrial_battery'] = 25,
6 ['fuel_canister'] = 50,
7 },
8 mlFuel = {
9 enabled = true,
10 hintItems = {},
11 acceptedFuelTypes = { 'diesel' },
12 typeLabels = { ['diesel'] = 'Diesel', ['fuel'] = 'Gasoline' },
13 litersToUnits = 5,
14 },
15}capacity: Tank size in units. Theextra_tankupgrade raises itperMinute: Units burned per minute of active processingitems: One-shot fuel items.['item'] = units. The item is removed on usemlFuel.enabled: Accept reusable jerrycans fromml_fuel. Any item carryingmetadata.fuelAmountandmetadata.fuelTypeis treated as a jerrycan: it is kept in the inventory and only emptied, never consumedmlFuel.acceptedFuelTypes: Fuel types the machine accepts. Must match keys inml_fuelConfig.FuelTypesmlFuel.typeLabels: UI label per fuel typemlFuel.litersToUnits: How many recycler fuel units one liter ofml_fuelbecomes
Recipes
The key is the input item. Each recipe defines the time and the possible outputs.
1Config.RecycleRecipes = {
2 ['broken_phone'] = {
3 baseTime = 20,
4 outputs = {
5 { item = 'glass', min = 1, max = 2, chance = 100 },
6 { item = 'copper', min = 1, max = 2, chance = 60 },
7 { item = 'microchip', min = 1, max = 1, chance = 15, tierRequired = 3 },
8 },
9 tierBonuses = {
10 [2] = { chanceBoost = 10, quantityBoost = 1 },
11 [3] = { chanceBoost = 25, quantityBoost = 2 },
12 },
13 },
14}baseTime: Processing time in seconds. Effective time =baseTime * processSpeedMultiplier, then upgrade and durability modifiersoutputs: Possible results. Each hasitem,min/maxquantity, andchance(0-100). AddtierRequired = 2to gate an output behind a recycler tiertierBonuses: Applied automatically by recycler tier.chanceBoostadds chance points to every output,quantityBoostadds to each outputmax
Rarity
Colors and labels for the loot preview.
1Config.Rarity = {
2 common = { color = '#9ca3af', label = _L('rarity_common') },
3 uncommon = { color = '#22c55e', label = _L('rarity_uncommon') },
4 rare = { color = '#3b82f6', label = _L('rarity_rare') },
5 epic = { color = '#a855f7', label = _L('rarity_epic') },
6 legendary = { color = '#f59e0b', label = _L('rarity_legendary') },
7}Upgrades
1Config.MaxUpgradesPerRecycler = 3
2
3Config.Upgrades = {
4 ['turbo_motor'] = { label = _L('upgrade_turbo_motor'), item = 'turbo_motor', icon = 'turbo_motor', effects = { processSpeedBonus = -0.20 } },
5 ['extra_tank'] = { label = _L('upgrade_extra_tank'), item = 'extra_tank', icon = 'extra_tank', effects = { fuelCapacityBonus = 0.50 } },
6 ['silencer_kit'] = { label = _L('upgrade_silencer_kit'), item = 'silencer_kit', icon = 'silencer_kit', effects = { soundDistanceMultiplier = 0.40 } },
7 ['solar_panel'] = { label = _L('upgrade_solar_panel'), item = 'solar_panel', icon = 'solar_panel', effects = { fuelRegenPerMinute = 1 } },
8}MaxUpgradesPerRecycler: Upgrade slots per machineeffects.processSpeedBonus: Multiplier change to processing time.-0.20is 20% fastereffects.fuelCapacityBonus: Fraction added to tank size.0.50is +50%effects.soundDistanceMultiplier: Multiplies the ambient and zombie-noise radius.0.40is 60% quietereffects.fuelRegenPerMinute: Passive fuel units generated per minute
Upgrades are consumed on install and returned to the player on removal, carrying their state. To make a slot-expansion module, add an upgrade with effects = { slotBonus = N }, give it an item, and the machine unlocks N extra slots up to maxSlots. The upgrade_slot_expansion label is already in the locale files.
Upgrades are permanent by default. Add a wear table to an upgrade definition to give it a durability curve that drains on use and auto-removes the module at zero:
1['turbo_motor'] = {
2 label = _L('upgrade_turbo_motor'), item = 'turbo_motor', icon = 'turbo_motor',
3 effects = { processSpeedBonus = -0.20 },
4 wear = { enabled = true, startDurability = 100, degradePerProcess = 1 },
5}Durability
1Config.Durability = {
2 degradePerProcess = 2,
3 slowdownThreshold = 50,
4 slowdownMultiplier = 1.20,
5 malfunctionThreshold = 25,
6 malfunctionChance = 15,
7 malfunctionCooldown = 600,
8 brokenThreshold = 0,
9}degradePerProcess: Durability points lost per completed slotslowdownThreshold: Below this percent, processing runs atslowdownMultipliertimemalfunctionThreshold: Below this percent, each process can jammalfunctionChance: Malfunction probability (0-100)malfunctionCooldown: Lockout in seconds after a malfunctionbrokenThreshold: At this value the machine stops until repaired
Repair Items
1Config.RepairItems = {
2 ['repair_kit'] = { restore = 100, label = _L('repair_item_repair_kit') },
3 ['patch_kit'] = { restore = 50, label = _L('repair_item_patch_kit') },
4 ['lubricant'] = { restore = 25, label = _L('repair_item_lubricant') },
5}restore: Durability points the item restores on use
Zombie Noise
1Config.ZombieNoise = {
2 enabled = false,
3 resourceName = 'ml_zombies',
4 defaultRadius = 50.0,
5 defaultDuration = 0,
6}enabled: A running machine attracts zombies withindefaultRadiusresourceName: Zombie resource to signal. The hook only fires if it is starteddefaultDuration:0keeps the noise active until processing stops
The silencer_kit upgrade multiplies defaultRadius down through soundDistanceMultiplier.
Fixed Stations
Permanent recyclers you place in the world. Players cannot pick them up.
1Config.FixedStations = {
2 {
3 id = 'unique_station_id',
4 coords = vec3(0.0, 0.0, 0.0),
5 heading = 0.0,
6 infiniteFuel = false,
7 permanentUpgrades = { 'turbo_motor', 'silencer_kit' },
8 },
9}id: Unique station id, stored in the databaseinfiniteFuel: Whentrue, this station never runs out of fuelpermanentUpgrades: Upgrades installed for good. Players cannot remove them and the wear system ignores them
Permissions
1Config.DefaultPermissions = {
2 onlyOwnerCanUse = false,
3 onlyOwnerCanRemove = true,
4 onlyOwnerCanRefuel = false,
5 onlyOwnerCanUpgrade = false,
6}- Applies to every player-placed recycler. Fixed stations always allow public upgrade access so a town can share one machine
Discord Webhooks
1ServerConfig.DiscordWebhook = ''
2ServerConfig.RecyclingWebhook = ''
3ServerConfig.PlacementWebhook = ''
4ServerConfig.ErrorWebhook = ''
5ServerConfig.ExploitsWebhook = ''
6ServerConfig.RateLimitCooldown = 1000DiscordWebhook: Fallback webhook used by any channel left emptyRecyclingWebhook: Recycling started, collected, refueled, repaired, upgrade install/removePlacementWebhook: Recycler placed and picked upErrorWebhook: Database failures and rollback eventsExploitsWebhook: Rate-limit spam, payload type mismatches, distance and origin checksRateLimitCooldown: Minimum milliseconds between actions per player
Set any webhook to false to disable that log entirely.