# Hate Framework Bridge

HateBridge is a central bridge system that provides framework independence for all Hate scripts. It supports ESX, QBCore, and QBox frameworks with automatic detection and unified API.

## Features

* **Automatic Framework Detection**: Automatically detects which framework is installed on the server
* **Unified API**: Provides a single API for all frameworks
* **Player Management**: Manages player data across different frameworks
* **Inventory Management**: Item adding/removing operations
* **Money Management**: Money adding/removing operations
* **Notification System**: Framework-independent notifications
* **Progress Bar**: Framework-independent progress bars
* **Callback System**: Server-client callbacks
* **Database Operations**: Helper functions for MySQL operations
* **Target System**: Unified targeting system (ox\_target, qb-target, qtarget)

## Installation

1. Copy the `hate-bridge` folder to your resources directory
2. Add this line to your `server.cfg`:

```
ensure hate-bridge
```

## Framework Support

| Framework | Status | Version Support |
| --------- | ------ | --------------- |
| ESX       | ✅      | Legacy & Final  |
| QBCore    | ✅      | All Versions    |
| QBox      | ✅      | Latest          |

## Dependencies

* `oxmysql` (required)
* `ox_lib` (optional, for enhanced features)

## Usage in Other Hate Scripts

### FXManifest Dependency

Add dependency to your `fxmanifest.lua`:

```lua
dependencies {
    'hate-bridge'
}
```

### Client Side Usage

```lua
local HateBridge = nil

-- Load HateBridge
CreateThread(function()
    while HateBridge == nil do
        HateBridge = exports['hate-bridge']:getBridge()
        Wait(100)
    end
end)

-- Usage examples
-- Get player data
local playerData = HateBridge.GetPlayerData()

-- Check if player is loaded
if HateBridge.IsPlayerLoaded() then
    print("Player is loaded")
end

-- Get player job
local job = HateBridge.GetPlayerJob()

-- Get player money
local money = HateBridge.GetPlayerMoney('money') -- or 'bank', 'black_money'

-- Show notification
HateBridge.ShowNotification('Hello World!', 'success', 5000)

-- Progress bar
HateBridge.ProgressBar('my_progressbar', 'Doing something...', 5000, false, true, {
    disableMovement = true,
    disableCarMovement = true,
    disableMouse = false,
    disableCombat = true,
}, {
    animDict = 'mini@repair',
    anim = 'fixing_a_player',
    flags = 49,
}, {}, function()
    print('Progress completed')
end, function()
    print('Progress cancelled')
end)

-- Trigger server callback
HateBridge.TriggerCallback('my_callback', function(result)
    print('Callback result:', result)
end, 'arg1', 'arg2')

-- Target system
HateBridge.AddTargetEntity(entity, {
    {
        name = 'my_option',
        icon = 'fas fa-hand',
        label = 'Interact',
        action = function()
            print('Entity targeted!')
        end,
        distance = 2.0
    }
})
```

### Server Side Usage

```lua
local HateBridge = exports['hate-bridge']:getBridgeServer()

-- Get player
local Player = HateBridge.GetPlayer(source)

-- Add money
HateBridge.AddMoney(source, 'money', 1000)

-- Remove money
HateBridge.RemoveMoney(source, 'money', 500)

-- Add item
HateBridge.AddItem(source, 'bread', 5, {quality = 100})

-- Remove item
HateBridge.RemoveItem(source, 'bread', 2)

-- Check if player has item
local hasItem = HateBridge.HasItem(source, 'bread', 3)

-- Get item count
local itemCount = HateBridge.GetItemCount(source, 'bread')

-- Create server callback
HateBridge.CreateCallback('my_callback', function(source, cb, arg1, arg2)
    cb(true)
end)

-- Database operations
HateBridge.ExecuteQuery('SELECT * FROM users WHERE identifier = ?', {identifier}, function(result)
    print('Query result:', json.encode(result))
end)
```

## Client API Reference

### Player Functions

<table><thead><tr><th width="272.6666259765625">Function</th><th>Description</th><th>Parameters</th><th>Returns</th></tr></thead><tbody><tr><td><code>GetPlayerData()</code></td><td>Get all player data</td><td>None</td><td>table</td></tr><tr><td><code>IsPlayerLoaded()</code></td><td>Check if player is loaded</td><td>None</td><td>boolean</td></tr><tr><td><code>GetPlayerJob()</code></td><td>Get player job information</td><td>None</td><td>table</td></tr><tr><td><code>GetPlayerMoney(moneyType)</code></td><td>Get player money amount</td><td>string (optional)</td><td>number</td></tr></tbody></table>

### UI Functions

<table><thead><tr><th width="312.66668701171875">Function</th><th>Description</th><th>Parameters</th><th>Returns</th></tr></thead><tbody><tr><td><code>ShowNotification(message, type, duration)</code></td><td>Show notification</td><td>string, string, number</td><td>void</td></tr><tr><td><code>ProgressBar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, onFinish, onCancel)</code></td><td>Show progress bar</td><td>multiple</td><td>void</td></tr></tbody></table>

### Callback Functions

<table><thead><tr><th width="292">Function</th><th>Description</th><th>Parameters</th><th>Returns</th></tr></thead><tbody><tr><td><code>TriggerCallback(name, cb, ...)</code></td><td>Trigger server callback</td><td>string, function, ...</td><td>void</td></tr></tbody></table>

### Target System Functions

<table><thead><tr><th width="342.66668701171875">Function</th><th>Description</th><th>Parameters</th><th>Returns</th></tr></thead><tbody><tr><td><code>AddTargetEntity(entity, options)</code></td><td>Add target to entity</td><td>number, table</td><td>void</td></tr><tr><td><code>RemoveTargetEntity(entity, optionNames)</code></td><td>Remove target from entity</td><td>number, table</td><td>void</td></tr><tr><td><code>AddTargetModel(models, options)</code></td><td>Add target to models</td><td>table, table</td><td>void</td></tr><tr><td><code>RemoveTargetModel(models, optionNames)</code></td><td>Remove target from models</td><td>table, table</td><td>void</td></tr><tr><td><code>AddGlobalPed(options)</code></td><td>Add global ped target</td><td>table</td><td>void</td></tr><tr><td><code>RemoveGlobalPed(optionNames)</code></td><td>Remove global ped target</td><td>table</td><td>void</td></tr><tr><td><code>AddTargetZone(name, coords, length, width, options, targetOptions)</code></td><td>Add target zone</td><td>string, vector3, number, number, table, table</td><td>void</td></tr><tr><td><code>AddCircleZone(name, coords, radius, options, targetOptions)</code></td><td>Add circle zone</td><td>string, vector3, number, table, table</td><td>void</td></tr><tr><td><code>RemoveTargetZone(name)</code></td><td>Remove target zone</td><td>string</td><td>void</td></tr></tbody></table>

## Server API Reference

### Player Functions

<table><thead><tr><th width="347.3333740234375">Function</th><th>Description</th><th>Parameters</th><th>Returns</th></tr></thead><tbody><tr><td><code>GetPlayer(source)</code></td><td>Get player object</td><td>number</td><td>object</td></tr><tr><td><code>GetPlayerFromIdentifier(identifier)</code></td><td>Get player by identifier</td><td>string</td><td>object</td></tr><tr><td><code>GetPlayerIdentifier(source)</code></td><td>Get player identifier</td><td>number</td><td>string</td></tr><tr><td><code>GetPlayerName(source)</code></td><td>Get player name</td><td>number</td><td>string</td></tr><tr><td><code>GetPlayerCharName(source, useNickname)</code></td><td>Get character name</td><td>number, boolean</td><td>string</td></tr></tbody></table>

### Money Functions

<table><thead><tr><th width="345.3333740234375">Function</th><th>Description</th><th>Parameters</th><th>Returns</th></tr></thead><tbody><tr><td><code>AddMoney(source, moneyType, amount)</code></td><td>Add money to player</td><td>number, string, number</td><td>boolean</td></tr><tr><td><code>RemoveMoney(source, moneyType, amount)</code></td><td>Remove money from player</td><td>number, string, number</td><td>boolean</td></tr><tr><td><code>GetPlayerMoney(source, moneyType)</code></td><td>Get player money</td><td>number, string</td><td>number</td></tr><tr><td><code>HasEnoughMoney(source, moneyType, amount)</code></td><td>Check if player has enough money</td><td>number, string, number</td><td>boolean</td></tr></tbody></table>

### Inventory Functions

<table><thead><tr><th width="359.33331298828125">Function</th><th>Description</th><th>Parameters</th><th>Returns</th></tr></thead><tbody><tr><td><code>AddItem(source, itemName, amount, metadata)</code></td><td>Add item to player</td><td>number, string, number, table</td><td>boolean</td></tr><tr><td><code>RemoveItem(source, itemName, amount)</code></td><td>Remove item from player</td><td>number, string, number</td><td>boolean</td></tr><tr><td><code>GetItemCount(source, itemName)</code></td><td>Get item count</td><td>number, string</td><td>number</td></tr><tr><td><code>HasItem(source, itemName, amount)</code></td><td>Check if player has item</td><td>number, string, number</td><td>boolean</td></tr><tr><td><code>HasEnoughItem(source, itemName, amount)</code></td><td>Check if player has enough items</td><td>number, string, number</td><td>boolean</td></tr><tr><td><code>CanCarryItem(source, itemName, amount)</code></td><td>Check if player can carry item</td><td>number, string, number</td><td>boolean</td></tr><tr><td><code>GetPlayerInventory(source)</code></td><td>Get player inventory</td><td>number</td><td>table</td></tr></tbody></table>

### Job Functions

| Function                               | Description    | Parameters             | Returns |
| -------------------------------------- | -------------- | ---------------------- | ------- |
| `GetPlayerJob(source)`                 | Get player job | number                 | table   |
| `SetPlayerJob(source, jobName, grade)` | Set player job | number, string, number | boolean |

### Callback Functions

| Function                   | Description            | Parameters       | Returns |
| -------------------------- | ---------------------- | ---------------- | ------- |
| `CreateCallback(name, cb)` | Create server callback | string, function | void    |

### Database Functions

| Function                               | Description          | Parameters              | Returns |
| -------------------------------------- | -------------------- | ----------------------- | ------- |
| `ExecuteQuery(query, parameters, cb)`  | Execute MySQL query  | string, table, function | mixed   |
| `ExecuteInsert(query, parameters, cb)` | Execute MySQL insert | string, table, function | number  |
| `ExecuteUpdate(query, parameters, cb)` | Execute MySQL update | string, table, function | number  |

### Utility Functions

| Function                                            | Description                 | Parameters                     | Returns |
| --------------------------------------------------- | --------------------------- | ------------------------------ | ------- |
| `CreateUseableItem(itemName, cb)`                   | Create useable item         | string, function               | void    |
| `ShowNotification(source, message, type, duration)` | Show notification to player | number, string, string, number | void    |
| `GetItemLabel(itemName)`                            | Get item label              | string                         | string  |
| `GetItemImagePath(itemName)`                        | Get item image path         | string                         | string  |

## Shared Exports

These exports are available on both client and server:

| Export                   | Description                      | Returns |
| ------------------------ | -------------------------------- | ------- |
| `getFramework()`         | Get detected framework name      | string  |
| `getTargetSystem()`      | Get detected target system       | string  |
| `getProgressBarSystem()` | Get detected progress bar system | string  |
| `getFrameworkEvents()`   | Get framework events table       | table   |
| `getServerEvents()`      | Get server events table          | table   |

## Framework Detection

The bridge automatically detects your framework on startup:

* **ESX**: Detects `es_extended` resource
* **QBCore**: Detects `qb-core` resource
* **QBox**: Detects `qbx_core` resource

## Target System Support

Automatically detects and supports:

* `ox_target`
* `qb-target`
* `qtarget`

## Progress Bar Support

Automatically detects and supports:

* `ox_lib` (progressCircle)
* `esx_progressbar`
* `qb-progressbar`

## Events

### Client Events

| Event                               | Description                   | Parameters |
| ----------------------------------- | ----------------------------- | ---------- |
| `hate-bridge:client:playerLoaded`   | Triggered when player loads   | playerData |
| `hate-bridge:client:playerUnloaded` | Triggered when player unloads | None       |
| `hate-bridge:client:jobUpdate`      | Triggered when job updates    | jobData    |

### Server Events

| Event                              | Description                 | Parameters |
| ---------------------------------- | --------------------------- | ---------- |
| `hate-bridge:server:playerLoaded`  | Triggered when player loads | source     |
| `hate-bridge:server:playerDropped` | Triggered when player drops | source     |

## Configuration

Edit `config.lua` to customize:

```lua
Config.Debug = true -- Enable debug prints
Config.Framework = nil -- Force framework (auto-detect if nil)
```

## Example Usage in Scripts

### Complete Client Example

```lua
-- Wait for bridge to be available
local HateBridge = nil
CreateThread(function()
    while HateBridge == nil do
        HateBridge = exports['hate-bridge']:getBridge()
        Wait(100)
    end
    
    -- Now you can use HateBridge functions
    print('Bridge loaded, framework:', exports['hate-bridge']:getFramework())
end)

-- Listen for player load
RegisterNetEvent('hate-bridge:client:playerLoaded')
AddEventHandler('hate-bridge:client:playerLoaded', function(playerData)
    print('Player loaded with job:', playerData.job.name)
end)

-- Example interaction
RegisterCommand('testbridge', function()
    if not HateBridge or not HateBridge.IsPlayerLoaded() then
        return
    end
    
    local job = HateBridge.GetPlayerJob()
    local money = HateBridge.GetPlayerMoney('money')
    
    HateBridge.ShowNotification('Job: ' .. job.name .. ' | Money: $' .. money, 'info')
end)
```

### Complete Server Example

```lua
-- Get bridge on resource start
local HateBridge = exports['hate-bridge']:getBridgeServer()

-- Create a callback for client use
HateBridge.CreateCallback('myresource:getData', function(source, cb)
    local Player = HateBridge.GetPlayer(source)
    if Player then
        cb({
            name = HateBridge.GetPlayerName(source),
            job = HateBridge.GetPlayerJob(source),
            money = HateBridge.GetPlayerMoney(source, 'money')
        })
    else
        cb(false)
    end
end)

-- Listen for player load
RegisterNetEvent('hate-bridge:server:playerLoaded')
AddEventHandler('hate-bridge:server:playerLoaded', function()
    local src = source
    print('Player loaded on server:', src)
    
    -- Give welcome bonus
    HateBridge.AddMoney(src, 'money', 100)
    HateBridge.ShowNotification(src, 'Welcome bonus: $100', 'success')
end)

-- Example command
RegisterCommand('givebread', function(source, args)
    local amount = tonumber(args[1]) or 1
    
    if HateBridge.CanCarryItem(source, 'bread', amount) then
        HateBridge.AddItem(source, 'bread', amount)
        HateBridge.ShowNotification(source, 'You received ' .. amount .. ' bread', 'success')
    else
        HateBridge.ShowNotification(source, 'You cannot carry that much bread', 'error')
    end
end)
```

## Troubleshooting

### Common Issues

1. **Framework not detected**: Ensure your framework resource is started before hate-bridge
2. **Exports not working**: Make sure to add hate-bridge as a dependency in your fxmanifest.lua
3. **Player data nil**: Wait for the player to be fully loaded before accessing data

### Debug Mode

Enable debug mode in config.lua to see detection logs:

```lua
Config.Debug = true
```

### Framework Override

You can force a specific framework if auto-detection fails:

```lua
Config.Framework = 'esx' -- or 'qb', 'qbox'
```

## Migration from Framework-Specific Code

### From ESX:

```lua
-- Old ESX code
ESX.TriggerServerCallback('callback', function(result) end)
ESX.ShowNotification('message')

-- New HateBridge code  
HateBridge.TriggerCallback('callback', function(result) end)
HateBridge.ShowNotification('message', 'info')
```

### From QBCore:

```lua
-- Old QB code
QBCore.Functions.TriggerCallback('callback', function(result) end)
QBCore.Functions.Notify('message')

-- New HateBridge code
HateBridge.TriggerCallback('callback', function(result) end)  
HateBridge.ShowNotification('message', 'info')
```

## Performance Notes

* HateBridge uses minimal resources
* Framework detection happens once on startup
* No polling or continuous checks
* Event-driven architecture for optimal performance

## License

This project is licensed under the MIT License.

## Support

For support and updates, visit our community or contact the development team.

***

**Note**: This bridge is designed specifically for Hate scripts ecosystem. While it can be used with other resources, it's optimized for Hate scripts integration.

Eğer herhangi bir sorun yaşarsanız:

1. HateBridge'in düzgün yüklendiğinden emin olun
2. Debug modunu açın (`Config.Debug = true`)
3. Server console'unda hata mesajlarını kontrol edin
4. Framework'ünüzün desteklendiğinden emin olun
