DocsJobsMining Operations

Mining Operations

A comprehensive guide to installing and configuring the Mining Job. Includes Setup, Database, Items, and a line-by-line explanation of the configuration.

1

Database Installation

You must run this SQL query to create the table where player levels, XP, and equipment tiers are saved.

  1. Open HeidiSQL or phpMyAdmin.
  2. Select your server database.
  3. Go to the Query tab, paste the code below, and run it.
install.sql
CREATE TABLE IF NOT EXISTS `xada_mining` (
  `identifier` varchar(60) NOT NULL, -- Steam Hex / Citizen ID
  `level` int(11) DEFAULT 1,         -- Player Level
  `xp` int(11) DEFAULT 0,            -- Current XP
  `equipment_tier` int(11) DEFAULT 1,-- Drill Level (1-3)
  `truck_tier` int(11) DEFAULT 1,    -- Truck License (1-3)
  `processing_tier` int(11) DEFAULT 0, -- Refinery Upgrade
  `scanner_tier` int(11) DEFAULT 0,  -- Gem Scanner
  `total_earned` int(11) DEFAULT 0,  -- Total Money Made
  `total_mined` int(11) DEFAULT 0,   -- Total Rocks Mined
  `deliveries_completed` int(11) DEFAULT 0, -- Total Runs
  PRIMARY KEY (`identifier`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2

Item Setup

Add the required items to your inventory system. Only use the section matching your framework.

Option A: Ox Inventory

ox_inventory/data/items.lua

['sandstone'] = { label = 'Raw Sandstone', weight = 1000, stack = true },
['refined_sand'] = { label = 'Refined Sand', weight = 500, stack = true },
['limestone'] = { label = 'Raw Limestone', weight = 1200, stack = true },
['concrete_mix'] = { label = 'Concrete Mix', weight = 800, stack = true },
['iron_ore'] = { label = 'Iron Ore', weight = 1500, stack = true },
['steel_ingot'] = { label = 'Steel Ingot', weight = 1000, stack = true },
['paydirt_bag'] = { label = 'Paydirt Bag', weight = 800, stack = true },
['washed_gravel'] = { label = 'Washed Gravel', weight = 200, stack = true },
['diamond'] = { label = 'Rough Diamond', weight = 10, stack = true },
['emerald'] = { label = 'Rough Emerald', weight = 10, stack = true },
['sapphire'] = { label = 'Rough Sapphire', weight = 10, stack = true },
['gold'] = { label = 'Gold Nugget', weight = 20, stack = true },

Option B: QB-Core

qb-core/shared/items.lua

['sandstone'] = {['name'] = 'sandstone', ['label'] = 'Raw Sandstone', ['weight'] = 1000, ['type'] = 'item', ['image'] = 'sandstone.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Raw sandstone debris.'},
['refined_sand'] = {['name'] = 'refined_sand', ['label'] = 'Refined Sand', ['weight'] = 500, ['type'] = 'item', ['image'] = 'refined_sand.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Refined sand for construction.'},
['limestone'] = {['name'] = 'limestone', ['label'] = 'Raw Limestone', ['weight'] = 1200, ['type'] = 'item', ['image'] = 'limestone.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Heavy limestone rock.'},
['concrete_mix'] = {['name'] = 'concrete_mix', ['label'] = 'Concrete Mix', ['weight'] = 800, ['type'] = 'item', ['image'] = 'concrete_mix.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Industrial concrete mix.'},
['iron_ore'] = {['name'] = 'iron_ore', ['label'] = 'Iron Ore', ['weight'] = 1500, ['type'] = 'item', ['image'] = 'iron_ore.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Unrefined iron ore.'},
['steel_ingot'] = {['name'] = 'steel_ingot', ['label'] = 'Steel Ingot', ['weight'] = 1000, ['type'] = 'item', ['image'] = 'steel_ingot.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Pure steel ingot.'},
['paydirt_bag'] = {['name'] = 'paydirt_bag', ['label'] = 'Paydirt Bag', ['weight'] = 800, ['type'] = 'item', ['image'] = 'paydirt_bag.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'A bag of dirty river mud.'},
['washed_gravel'] = {['name'] = 'washed_gravel', ['label'] = 'Washed Gravel', ['weight'] = 200, ['type'] = 'item', ['image'] = 'washed_gravel.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Worthless rocks.'},
['diamond'] = {['name'] = 'diamond', ['label'] = 'Rough Diamond', ['weight'] = 10, ['type'] = 'item', ['image'] = 'diamond.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'A shiny rough diamond.'},
['emerald'] = {['name'] = 'emerald', ['label'] = 'Rough Emerald', ['weight'] = 10, ['type'] = 'item', ['image'] = 'emerald.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'A green gemstone.'},
['sapphire'] = {['name'] = 'sapphire', ['label'] = 'Rough Sapphire', ['weight'] = 10, ['type'] = 'item', ['image'] = 'sapphire.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'A blue gemstone.'},
['gold'] = {['name'] = 'gold', ['label'] = 'Gold Nugget', ['weight'] = 20, ['type'] = 'item', ['image'] = 'gold.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'A heavy gold nugget.'},

Option C: ESX Legacy

Run this SQL Query:

INSERT INTO `items` (`name`, `label`, `weight`, `rare`, `can_remove`) VALUES
('sandstone', 'Raw Sandstone', 1000, 0, 1),
('refined_sand', 'Refined Sand', 500, 0, 1),
('limestone', 'Raw Limestone', 1200, 0, 1),
('concrete_mix', 'Concrete Mix', 800, 0, 1),
('iron_ore', 'Iron Ore', 1500, 0, 1),
('steel_ingot', 'Steel Ingot', 1000, 0, 1),
('paydirt_bag', 'Paydirt Bag', 800, 0, 1),
('washed_gravel', 'Washed Gravel', 200, 0, 1),
('diamond', 'Rough Diamond', 10, 1, 1),
('emerald', 'Rough Emerald', 10, 1, 1),
('sapphire', 'Rough Sapphire', 10, 1, 1),
('gold', 'Gold Nugget', 20, 1, 1);
3

Adding Images

Copy all .png files from the img/ folder in the download to your inventory images folder.

  • Ox Inventory: ox_inventory/web/images/
  • QB Inventory: qb-inventory/html/images/
  • QS Inventory: qs-inventory/html/img/
4

Line-by-Line Configuration

Below is a complete breakdown of modules/mining/config.lua.

Core & Framework

Config.Debug = false 
Config.Locale = 'en'
Config.Framework = 'qb' 
Config.InteractionType = 'textui' 
Config.InventorySystem = 'ox'
  • Debug: If true, it draws red boxes around locations and prints extra info in console (F8). Useful if you are editing locations.
  • Locale: Matches a file in the locales/ folder (e.g., 'en', 'fr', 'es').
  • Framework: Set to 'esx' or 'qb'. This auto-detects your job and money functions.
  • InteractionType:
    • 'textui': Shows a popup "Press E to Mine".
    • 'target': Uses ox_target or qb-target (Third Eye).
  • InventorySystem: Set to 'ox', 'qb', 'qs', or 'esx'. This ensures the script checks for items correctly.

UI Providers

Config.NotifyProvider = 'xada' 
Config.TextUIProvider = 'xada'
Config.ProgressProvider = 'xada'

These control the visual style.
'xada' uses the xada_lib included in your download (Modern Look).
'ox' uses standard ox_lib styling.
'esx' / 'qb' uses legacy notifications.

Discord Webhook Setup

Config.Discord = {
    Enabled = true,
    Webhook = "", -- PASTE HERE
    BotName = "Mining Logistics",
    ...
}
How to get a Webhook URL:
  1. Open your Discord Server settings.
  2. Go to IntegrationsWebhooks.
  3. Click New Webhook.
  4. Name it (e.g., "Mining Logs") and choose a channel.
  5. Click Copy Webhook URL.
  6. Paste it inside the Webhook = "PASTE_HERE" quotes.

Progression System

Config.Leveling = {
    BaseXP = 500,       
    Multiplier = 1.2,   
    MaxLevel = 50       
}
  • BaseXP: XP needed to go from Level 1 to 2.
  • Multiplier: The difficulty curve.
    Example: Level 2 requires 500 * 1.2 = 600 XP.
    Level 3 requires 600 * 1.2 = 720 XP.
  • MaxLevel: The hard cap. Players cannot level up past this.

Locations & Blips

Config.JobCenter = {
    Location = vector3(2946.5, 2746.9, 43.4),
    
    Marker = {
        Enable = true,
        Type = 27, -- Standard Cylinder
        Color = {r = 255, g = 165, b = 0, a = 150}, -- RGBA Color
    },

    Blip = {
        Enable = true,
        Sprite = 478, -- The Map Icon ID
        Color = 5,    -- The Map Icon Color
        Scale = 0.8,  -- Size
        Name = "Davis Quartz Logistics" -- Map Name
    }
}

To change the location, use /coords in-game and replace the vector3 numbers.
Note: Config.Processing and Config.Export work exactly the same way.

Job Contracts

This defines the actual jobs. Do not change the ID unless you also change the database/item name.

[1] = {
    id = 'sandstone',       -- Internal ID (Matches Item Name)
    label = 'Raw Sandstone',-- Name shown in Menu
    level = 1,              -- Min Level required
    xp = 50,                -- XP earned per action
    prop = 'prop_rock_1_a', -- The rock object to spawn
    
    payout = {min = 150, max = 300}, -- Visual estimate shown in UI
    sellPrice = 250,        -- Actual money given per item sold
    
    locations = { ... },    -- List of coordinates where rocks spawn

    -- Refining Logic
    recipe = {
        input = "sandstone",        -- Item taken
        output = "refined_sand",    -- Item given
        duration = 5000             -- Time in ms
    }
}

Equipment Shop

Config.Equipment = {
    {
        category = "Extraction Tools",
        id = "drills",
        items = {
            { 
                id = "drill_t1",  -- Unique ID
                label = "Rusted Jackhammer", 
                price = 0,        -- Cost
                level = 1,        -- Level Req
                tier = 1          -- DB Value (1 = Slow, 3 = Fast)
            },
        }
    }
}

Important: These are not physical items. When a player buys "Drill T2", the script updates their equipment_tier column in the database to 2. It does not give a physical drill item. The script checks this tier to decide how fast you mine.

Final Check: Did you restart the server after adding the items and SQL? If not, the script will fail to load player data.