> For the complete documentation index, see [llms.txt](https://mango-5m.gitbook.io/mango5m-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mango-5m.gitbook.io/mango5m-docs/resources/mango-prison/developer-guide/jailing-from-an-mdt.md).

# Jailing from an MDT

Sentence a report in your MDT and have the charges land the player in Bolingbroke — for Mango MDT, ps-mdt and codem mMDT AIO.

Your MDT already knows the charges and what each one is worth. Mango Corrections already knows how to run a sentence. This page connects the two, so an officer files the report, hits sentence, and the suspect is on the prison bus.

{% hint style="warning" %}
**Mango Corrections counts in real minutes. Every MDT counts in months.**

`JailPlayer(src, 5)` is a **5 minute** sentence that displays in game as "5 months" (`Config.Sentence.displayScale`). If you pass months straight through, a 120-month sentence becomes two hours of real time and your player will not thank you. Every integration below converts.
{% endhint %}

## What each MDT does

| MDT                                                   | Sentence computed from       | Sent as                     | Work needed                            |
| ----------------------------------------------------- | ---------------------------- | --------------------------- | -------------------------------------- |
| [**Mango MDT**](/mango5m-docs/resources/mango-mdt.md) | Charge `jail_months`, summed | minutes                     | **None** — a provider ships in the box |
| **ps-mdt** (Project Sloth)                            | Charge sheet on the report   | months, to a *client* event | One line in `sentencing.lua`           |
| **codem mMDT AIO**                                    | Its own penal code           | framework jail event        | **Usually none** — test first          |

***

## Mango MDT

Mango MDT routes jailing through a **bridge provider**, and `mango_prison` is one of the shipped providers. Nothing to write.

{% stepper %}
{% step %}

### Point the bridge at the prison

In `mango_mdt/config/bridge.lua`:

```lua
Config.Bridge = {
    Jail = 'mango_prison',   -- or 'auto'
}
```

`'auto'` picks `mango_prison` ahead of the other prison resources when it is running, so either value works. Name it explicitly if you also have an old prison script installed.
{% endstep %}

{% step %}

### Set what a month is worth

In `mango_mdt/config/jail.lua`:

```lua
Config.Jail = {
    minutesPerMonth = 1.0,   -- 12 months of charges -> a 12 minute sentence
}
```

This is the only conversion in the chain. Raise it for a slower server, lower it for a busier one.
{% endstep %}

{% step %}

### Give the rank permission

The `jail.sentence` permission gates the sentencing action. Grant it to the ranks allowed to send people down — see the MDT's own ranks config.
{% endstep %}

{% step %}

### Restart both

```
ensure mango_prison
ensure mango_mdt
```

On boot the MDT prints which jail provider it bound. If it says no provider is bound, `Config.Bridge.Jail` is wrong or `mango_prison` is not started.
{% endstep %}
{% endstepper %}

### How charges become time

Each charge in the MDT's penal code carries a `jail_months` value. When an officer sentences a report:

1. Every selected charge's `jail_months` is added up.
2. The total is multiplied by `Config.Jail.minutesPerMonth`.
3. Any plea deduction (0–50%) is taken off.
4. The result — in minutes — is handed to `exports.mango_prison:JailPlayer`.

The MDT stores a snapshot of the exact charges alongside the record, so the sentence stays auditable even if you re-price the penal code later.

### What you get back

Because the MDT and the prison both belong to Mango 5M, the link runs **both ways**:

| Event                                         | Effect in the MDT                                                                                           |
| --------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| Sentence served, or an officer releases early | The jail record closes itself and **IN PRISON** clears                                                      |
| Prisoner escapes Bolingbroke                  | The record is marked escaped, and an automatic **BOLO warrant** is raised if `Config.Jail.escapeBOLO` is on |

There is also a read-back poll: once a minute the MDT asks the prison whether each active inmate is genuinely still inside, so a record can never get stuck showing IN PRISON on someone who is walking around.

***

## ps-mdt (Project Sloth)

ps-mdt computes the sentence from the report's charge sheet, then hands it off with:

```lua
TriggerClientEvent('police:client:SendToJail', targetSource, sentence)
```

Two things about that line matter:

* `sentence` is in **months**, not minutes.
* It is a **client** event, so Mango Corrections cannot intercept it server-side the way it intercepts the framework jail events. It has to be redirected at the source.

### The edit

In `ps-mdt/server/backend/sentencing.lua`, find the `sendToJail` callback and replace that one `TriggerClientEvent` line:

```lua
-- ps-mdt/server/backend/sentencing.lua
local MINUTES_PER_MONTH = 1.0   -- tune this to your server's pace

-- REPLACE: TriggerClientEvent('police:client:SendToJail', targetSource, sentence)
exports.mango_prison:JailPlayer(
    targetSource,
    math.max(1, math.floor(sentence * MINUTES_PER_MONTH)),
    { reason = 'MDT sentencing', officer = GetPlayerName(src) }
)
```

Leave everything else in that callback alone. The permission check above it still applies, and the `injail` / `criminalrecord` metadata writes are what ps-mdt's own UI reads.

{% hint style="info" %}
**Keep the surrounding code.** `src` is the sentencing officer and `targetSource` is the suspect — both are already local variables in that callback. Do not swap them, or every sentence will be logged against the wrong person.
{% endhint %}

{% hint style="danger" %}
**Remove qb-policejob's jail, or you will jail twice.**

`police:client:SendToJail` is qb-policejob's own event. If qb-policejob (or qb-prison) is still handling it while Mango Corrections is running, one sentence can start two prison timers. Mango Corrections prints a startup warning when it spots a conflicting jail resource — do not ignore it.
{% endhint %}

### Known limits

* **ps-mdt refuses offline suspects** — it returns *"Player must be online to send to jail"* before ever reaching the jail call. Mango Corrections itself is happy to sentence an offline identifier (see [Jailing Players](/mango5m-docs/resources/mango-prison/developer-guide/jailing-players.md)); that restriction is ps-mdt's, not ours.
* **The `injail` metadata does not clear itself.** ps-mdt writes QBCore metadata that Mango Corrections knows nothing about, so its own badge can linger after release. Clear it in your release handler if it bothers you:

```lua
AddEventHandler('mango_prison:playerReleased', function(src, info)
    if not src then return end
    local Player = exports['qb-core']:GetCoreObject().Functions.GetPlayer(src)
    if Player then Player.Functions.SetMetaData('injail', 0) end
end)
```

***

## codem mMDT AIO

codem's MDT is escrowed and its public documentation does not publish a jail hook, so start by assuming **you need to change nothing**.

codem's MDT jails the framework way, and Mango Corrections already intercepts both framework jail events:

| Framework | Event it catches                              | Unit    |
| --------- | --------------------------------------------- | ------- |
| ESX       | `esx_jail:sendToJail(playerId, seconds)`      | seconds |
| QB / Qbox | `police:server:JailPlayer(playerId, minutes)` | minutes |

{% stepper %}
{% step %}

### Remove the old jail resource

Delete or stop `esx_jail` (ESX) or `qb-prison` (QB). Mango Corrections takes its place — leaving it installed is what causes double sentences.
{% endstep %}

{% step %}

### Confirm the compat layer is on

In `config/main.lua`:

```lua
Config.Compat = {
    esx_jail      = true,
    qb_policejob  = true,
    warnConflicts = true,
}
```

{% endstep %}

{% step %}

### Sentence a test player

Charge a suspect in the MDT and send them down. If the prison bus arrives, you are finished — no code at all.
{% endstep %}

{% step %}

### If nothing happens, find the call

codem ships modifiable server code in its **`editable/`** folder. Search that folder for the jail call:

```
grep -ri "jail" codem-mdt/editable/
```

Swap whatever it triggers for the export, converting to minutes:

```lua
exports.mango_prison:JailPlayer(targetSource, minutes, {
    reason  = 'MDT sentencing',
    officer = GetPlayerName(src),
})
```

{% endstep %}
{% endstepper %}

{% hint style="danger" %}
**The ESX seconds/minutes trap.** `esx_jail:sendToJail` is documented in **seconds**, but plenty of MDTs and police jobs send **minutes** through it. A sentence of `20` then becomes a 20 *second* stay.

Mango Corrections prints a warning when the number it receives looks like the wrong unit. If your MDT sends minutes, tell it so:

```lua
Config.Compat.esxJailUnit = 'minutes'
```

{% endhint %}

***

## Any other MDT

The contract is one export. Call it server-side, in minutes:

```lua
-- returns: boolean ok, string|nil err
local ok, err = exports.mango_prison:JailPlayer(target, minutes, {
    reason  = 'Armed robbery, evading',   -- shown on the inmate file
    officer = 'Officer Smith',            -- who signed it off
    cell    = 'A3',                       -- optional; auto-assigned otherwise
})
```

`target` may be a **server id** or a **character identifier** — pass the identifier and an offline suspect is sentenced anyway, with intake running at their next login.

To mirror the state back into your MDT, listen for these. They are registered with `AddEventHandler` only, so a modified client cannot fake them:

```lua
AddEventHandler('mango_prison:playerJailed', function(src, info)
    -- info = { identifier, minutes, reason }
end)

AddEventHandler('mango_prison:playerReleased', function(src, info)
    -- info = { identifier, reason }
end)

AddEventHandler('mango_prison:playerEscaped', function(src, info)
    -- info = { identifier }
end)
```

`src` is `nil` when the subject was offline at the time — always prefer `info.identifier`. Full list on [Events & Statebags](/mango5m-docs/resources/mango-prison/developer-guide/events-and-statebags.md), and every export on [Server Exports](/mango5m-docs/resources/mango-prison/developer-guide/server-exports.md).

## Troubleshooting

<details>

<summary>The MDT says the sentence went through, but nobody is jailed</summary>

The MDT called something Mango Corrections never heard. Check in this order: the jail resource it is bound to, whether an old prison script is still installed and answering first, and whether `mango_prison` was started at all. `Config.Debug = true` logs every jail call the prison receives.

</details>

<details>

<summary>Sentences are far too short</summary>

Months are being passed as minutes. In Mango MDT that is `Config.Jail.minutesPerMonth`; in ps-mdt it is the `MINUTES_PER_MONTH` constant above; on ESX compat it is `Config.Compat.esxJailUnit`.

</details>

<details>

<summary>Sentences are absurdly long</summary>

The reverse: seconds are being read as minutes, or a penal code priced in months is being multiplied twice. Check that only **one** conversion exists in the chain.

</details>

<details>

<summary>The player is jailed twice, or the timer restarts</summary>

Two jail resources are live. Remove `esx_jail`, `qb-prison` or `qalle-jail` — Mango Corrections warns about all three at startup.

</details>

<details>

<summary>Mango MDT responds "no_provider"</summary>

`Config.Bridge.Jail` is set to `'none'`, or to a provider whose resource is not running. Set it to `'mango_prison'` and restart the MDT.

</details>

<details>

<summary>The MDT still shows IN PRISON after release</summary>

Expected on any MDT that has no release signal from its prison. Mango MDT does not have this problem — it is told directly and also re-checks every minute. On other MDTs, hook `mango_prison:playerReleased` as shown above.

</details>
