Add QBCore tools for player and shared data information
- Implement GetQBCorePlayers tool to retrieve player data structure, methods, events, and examples. - Implement GetQBCoreSharedData tool to retrieve shared data types including items, jobs, gangs, vehicles, weapons, starter items, and utilities. - Create corresponding Blade views for displaying player and shared data information. - Add tests for GetQBCoreConfig, GetQBCorePlayers, and GetQBCoreSharedData tools to ensure correct functionality and response handling.
This commit is contained in:
14 files changed
+1157
-6
No files matched your search
@@ -14,7 +14,7 @@ The FiveM MCP Server enables seamless integration with AI coding assistants (Cla
|
||||
|
||||
### Live Site
|
||||
|
||||
A live instance is available at: **https://fivem-mcp.kingsoflossantos.com/fivem**
|
||||
A live instance is available at: **https://fivem-mcp.kingsoflossantos.com**
|
||||
|
||||
This site includes interactive documentation, tool descriptions, and integration guides.
|
||||
|
||||
@@ -44,6 +44,18 @@ npm run build
|
||||
|
||||
### Running the Server
|
||||
|
||||
**Live AI Assistants (Claude/Client):**
|
||||
```json
|
||||
{
|
||||
"servers": {
|
||||
"fivem": {
|
||||
"url": "https://fivem-mcp.kingsoflossantos.com/fivem",
|
||||
"type": "http"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Local Testing:**
|
||||
```bash
|
||||
php artisan mcp:inspector fivem
|
||||
|
||||
@@ -24,6 +24,9 @@ use App\Mcp\Tools\FiveM\Server\GetEventServerReference;
|
||||
use App\Mcp\Tools\FiveM\Server\GetNativeServerFunction;
|
||||
use App\Mcp\Tools\QBCore\Client\GetQBCoreClientEventReference;
|
||||
use App\Mcp\Tools\QBCore\Client\GetQBCoreClientFunction;
|
||||
use App\Mcp\Tools\QBCore\GetQBCoreConfig;
|
||||
use App\Mcp\Tools\QBCore\GetQBCorePlayers;
|
||||
use App\Mcp\Tools\QBCore\GetQBCoreSharedData;
|
||||
use App\Mcp\Tools\QBCore\Server\GetQBCoreServerEventReference;
|
||||
use App\Mcp\Tools\QBCore\Server\GetQBCoreServerFunction;
|
||||
use Laravel\Mcp\Server;
|
||||
@@ -60,6 +63,9 @@ class FiveMServer extends Server
|
||||
GetQBCoreClientFunction::class,
|
||||
GetQBCoreServerEventReference::class,
|
||||
GetQBCoreClientEventReference::class,
|
||||
GetQBCoreSharedData::class,
|
||||
GetQBCoreConfig::class,
|
||||
GetQBCorePlayers::class,
|
||||
GetCOXEventReference::class,
|
||||
GetCOXFunction::class,
|
||||
GetInventoryServerFunction::class,
|
||||
|
||||
@@ -113,6 +113,101 @@ class GetQBCoreClientFunction extends Tool
|
||||
'lua_example' => "RegisterNetEvent('QBCore:Client:OnPlayerLoad')\nAddEventHandler('QBCore:Client:OnPlayerLoad', function()\n local playerData = QBCore.Functions.GetPlayerData()\n print('Player loaded: ' .. playerData.charinfo.firstname)\nend)",
|
||||
'js_example' => "RegisterNetEvent('QBCore:Client:OnPlayerLoad');\nAddEventHandler('QBCore:Client:OnPlayerLoad', function() {\n const playerData = QBCore.Functions.GetPlayerData();\n console.log(`Player loaded: \${playerData.charinfo.firstname}`);\n});",
|
||||
],
|
||||
'TriggerServerEvent' => [
|
||||
'namespace' => 'FiveM Core',
|
||||
'description' => 'Trigger a server-side event from the client (client-side only)',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'eventName', 'type' => 'string', 'description' => 'Event name to trigger on server'],
|
||||
['name' => '...', 'type' => 'any', 'description' => 'Arguments to pass to server event'],
|
||||
],
|
||||
'returns' => ['type' => 'void', 'description' => ''],
|
||||
'lua_example' => "TriggerServerEvent('myResource:serverEvent', 'arg1', 'arg2')\n-- Received on server with:\n-- RegisterNetEvent('myResource:serverEvent')\n-- AddEventHandler('myResource:serverEvent', function(arg1, arg2) end)",
|
||||
'js_example' => "TriggerServerEvent('myResource:serverEvent', 'arg1', 'arg2');\n// Received on server with:\n// on('myResource:serverEvent', (arg1, arg2) => {})",
|
||||
],
|
||||
'Citizen.Wait' => [
|
||||
'namespace' => 'FiveM Core',
|
||||
'description' => 'Wait/sleep for a specified duration in milliseconds (client-side)',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'ms', 'type' => 'number', 'description' => 'Duration in milliseconds'],
|
||||
],
|
||||
'returns' => ['type' => 'void', 'description' => ''],
|
||||
'lua_example' => "print('Before wait')\nCitizen.Wait(5000) -- Wait 5 seconds\nprint('After wait')",
|
||||
'js_example' => "console.log('Before wait');\nawait Citizen.Wait(5000); // Wait 5 seconds\nconsole.log('After wait');",
|
||||
],
|
||||
'Citizen.CreateThread' => [
|
||||
'namespace' => 'FiveM Core',
|
||||
'description' => 'Create an async thread (client-side)',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'callback', 'type' => 'function', 'description' => 'Function to execute as thread'],
|
||||
],
|
||||
'returns' => ['type' => 'number', 'description' => 'Thread ID'],
|
||||
'lua_example' => "Citizen.CreateThread(function()\n while true do\n Citizen.Wait(1000) -- Repeat every second\n print('This runs repeatedly')\n end\nend)",
|
||||
'js_example' => "Citizen.CreateThread(async () => {\n while (true) {\n await Citizen.Wait(1000); // Repeat every second\n console.log('This runs repeatedly');\n }\n});",
|
||||
],
|
||||
'PlayerPedId' => [
|
||||
'namespace' => 'FiveM Core',
|
||||
'description' => 'Get the local player ped entity (client-side only)',
|
||||
'side' => 'client',
|
||||
'parameters' => [],
|
||||
'returns' => ['type' => 'number', 'description' => 'Player ped entity ID'],
|
||||
'lua_example' => "local playerPed = PlayerPedId()\nprint('My ped ID: ' .. playerPed)",
|
||||
'js_example' => "const playerPed = PlayerPedId();\nconsole.log(`My ped ID: \${playerPed}`);",
|
||||
],
|
||||
'GetEntityCoords' => [
|
||||
'namespace' => 'FiveM Core',
|
||||
'description' => 'Get the coordinates of an entity (client-side)',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'entity', 'type' => 'number', 'description' => 'Entity ID'],
|
||||
['name' => 'alive', 'type' => 'boolean|nil', 'description' => 'Whether to get alive coords (default true)'],
|
||||
],
|
||||
'returns' => ['type' => 'vector3', 'description' => 'X, Y, Z coordinates'],
|
||||
'lua_example' => "local playerPed = PlayerPedId()\nlocal playerCoords = GetEntityCoords(playerPed)\nprint('Player at: ' .. playerCoords.x .. ', ' .. playerCoords.y .. ', ' .. playerCoords.z)",
|
||||
'js_example' => "const playerPed = PlayerPedId();\nconst playerCoords = GetEntityCoords(playerPed);\nconsole.log(`Player at: \${playerCoords.x}, \${playerCoords.y}, \${playerCoords.z}`);",
|
||||
],
|
||||
'SetEntityCoords' => [
|
||||
'namespace' => 'FiveM Core',
|
||||
'description' => 'Set the coordinates of an entity (client-side)',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'entity', 'type' => 'number', 'description' => 'Entity ID'],
|
||||
['name' => 'x', 'type' => 'number', 'description' => 'X coordinate'],
|
||||
['name' => 'y', 'type' => 'number', 'description' => 'Y coordinate'],
|
||||
['name' => 'z', 'type' => 'number', 'description' => 'Z coordinate'],
|
||||
['name' => 'alive', 'type' => 'boolean|nil', 'description' => 'Whether alive (default true)'],
|
||||
['name' => 'animate', 'type' => 'boolean|nil', 'description' => 'Whether to animate movement (default false)'],
|
||||
],
|
||||
'returns' => ['type' => 'void', 'description' => ''],
|
||||
'lua_example' => "local playerPed = PlayerPedId()\nSetEntityCoords(playerPed, 100.0, 200.0, 50.0, false, false, false, false)\nprint('Teleported!')",
|
||||
'js_example' => "const playerPed = PlayerPedId();\nSetEntityCoords(playerPed, 100.0, 200.0, 50.0, false, false, false, false);\nconsole.log('Teleported!');",
|
||||
],
|
||||
'QBCore.Functions.Notify' => [
|
||||
'namespace' => 'UI',
|
||||
'description' => 'Send a notification to the local player on client (client-side only)',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'text', 'type' => 'string', 'description' => 'Notification text'],
|
||||
['name' => 'type', 'type' => 'string', 'description' => 'Notification type: error, success, primary, warning'],
|
||||
['name' => 'duration', 'type' => 'number|nil', 'description' => 'Duration in milliseconds (default 5000)'],
|
||||
],
|
||||
'returns' => ['type' => 'void', 'description' => ''],
|
||||
'lua_example' => "QBCore.Functions.Notify('Welcome to the server!', 'success', 5000)",
|
||||
'js_example' => "QBCore.Functions.Notify('Welcome to the server!', 'success', 5000);",
|
||||
],
|
||||
'QBCore.Functions.GetResourceMeta' => [
|
||||
'namespace' => 'Core',
|
||||
'description' => 'Get a resource metadata value (client-side)',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'key', 'type' => 'string', 'description' => 'Metadata key to retrieve'],
|
||||
],
|
||||
'returns' => ['type' => 'any', 'description' => 'The metadata value or nil'],
|
||||
'lua_example' => "local version = QBCore.Functions.GetResourceMeta('version')\nif version then\n print('QBCore Version: ' .. version)\nend",
|
||||
'js_example' => "const version = QBCore.Functions.GetResourceMeta('version');\nif (version) {\n console.log(`QBCore Version: \${version}`);\n}",
|
||||
],
|
||||
];
|
||||
|
||||
$nameLower = strtolower($name);
|
||||
@@ -147,7 +242,7 @@ class GetQBCoreClientFunction extends Tool
|
||||
return [
|
||||
'function_name' => $schema
|
||||
->string()
|
||||
->description('The name of the QBCore client function to look up (e.g., "QBCore.Functions.GetPlayerData", "QBCore.Commands.Add")')
|
||||
->description('The name of the QBCore client function to look up (e.g., "QBCore.Functions.GetPlayerData", "QBCore.Commands.Add", "TriggerServerEvent", "Citizen.Wait", "PlayerPedId")')
|
||||
->required(),
|
||||
'language' => $schema
|
||||
->string()
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mcp\Tools\QBCore;
|
||||
|
||||
use Illuminate\Contracts\JsonSchema\JsonSchema;
|
||||
use Laravel\Mcp\Request;
|
||||
use Laravel\Mcp\Response;
|
||||
use Laravel\Mcp\Server\Attributes\Description;
|
||||
use Laravel\Mcp\Server\Tool;
|
||||
|
||||
#[Description('Look up QBCore configuration options and settings. Returns information about core config, player defaults, server settings, and framework options.')]
|
||||
class GetQBCoreConfig extends Tool
|
||||
{
|
||||
/**
|
||||
* Handle the tool request.
|
||||
*/
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
$configType = $request->get('config_type');
|
||||
$language = $request->get('language', 'lua');
|
||||
|
||||
$config = $this->findConfigType($configType);
|
||||
|
||||
if (! $config) {
|
||||
return Response::text(sprintf("QBCore config '%s' not found. Available types: Player, Framework, Database, Callbacks, Database, Features", $configType));
|
||||
}
|
||||
|
||||
$output = $this->formatConfigInfo($config, $language);
|
||||
|
||||
return Response::text($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a QBCore config type.
|
||||
*/
|
||||
protected function findConfigType(string $name): ?array
|
||||
{
|
||||
$configs = [
|
||||
'Player' => [
|
||||
'category' => 'Player',
|
||||
'description' => 'Default player configuration including character generation and initial data setup.',
|
||||
'location' => 'qb-core/config.lua',
|
||||
'config_options' => [
|
||||
['name' => 'PlayerDefaults', 'type' => 'table', 'description' => 'Default values for new player characters (money, metadata, inventory)'],
|
||||
['name' => 'Metadata', 'type' => 'table', 'description' => 'Default metadata values like hunger, thirst, stress, temperature'],
|
||||
['name' => 'Money', 'type' => 'table', 'description' => 'Default starting money (cash, bank, crypto)'],
|
||||
['name' => 'Licenses', 'type' => 'table', 'description' => 'Default licenses a player starts with'],
|
||||
],
|
||||
'lua_example' => "local QBConfig = exports['qb-core']:GetCoreObject().Config\nif QBConfig.PlayerDefaults then\n print('Default metadata: ' .. json.encode(QBConfig.PlayerDefaults.metadata))\nend",
|
||||
'js_example' => "const QBConfig = exports['qb-core']:GetCoreObject().Config;\nif (QBConfig.PlayerDefaults) {\n console.log('Default metadata: ' + JSON.stringify(QBConfig.PlayerDefaults.metadata));\n}",
|
||||
],
|
||||
'Framework' => [
|
||||
'category' => 'Framework',
|
||||
'description' => 'Core framework settings including server name, version, and general options.',
|
||||
'location' => 'qb-core/config.lua',
|
||||
'config_options' => [
|
||||
['name' => 'ServerName', 'type' => 'string', 'description' => 'Name of your QBCore server'],
|
||||
['name' => 'Version', 'type' => 'string', 'description' => 'QBCore framework version'],
|
||||
['name' => 'Timezone', 'type' => 'string', 'description' => 'Server timezone (e.g., "America/New_York")'],
|
||||
['name' => 'Debug', 'type' => 'boolean', 'description' => 'Enable debug logging'],
|
||||
],
|
||||
'lua_example' => "local QBConfig = exports['qb-core']:GetCoreObject().Config\nprint('Server Name: ' .. QBConfig.ServerName)\nprint('Version: ' .. QBConfig.Version)\nprint('Debug Mode: ' .. tostring(QBConfig.Debug))",
|
||||
'js_example' => "const QBConfig = exports['qb-core']:GetCoreObject().Config;\nconsole.log(`Server Name: \${QBConfig.ServerName}`);\nconsole.log(`Version: \${QBConfig.Version}`);\nconsole.log(`Debug Mode: \${QBConfig.Debug}`);",
|
||||
],
|
||||
'Database' => [
|
||||
'category' => 'Database',
|
||||
'description' => 'Database configuration and connection settings.',
|
||||
'location' => 'qb-core/config.lua',
|
||||
'config_options' => [
|
||||
['name' => 'Backend', 'type' => 'string', 'description' => 'Database backend (ox_mysql, mysql-async, oxmysql)'],
|
||||
['name' => 'Host', 'type' => 'string', 'description' => 'Database server address'],
|
||||
['name' => 'Port', 'type' => 'number', 'description' => 'Database server port'],
|
||||
['name' => 'Username', 'type' => 'string', 'description' => 'Database username'],
|
||||
['name' => 'Password', 'type' => 'string', 'description' => 'Database password (set in .env or server.cfg)'],
|
||||
['name' => 'Database', 'type' => 'string', 'description' => 'Database name'],
|
||||
],
|
||||
'lua_example' => "-- Database configuration is typically in environment variables\n-- Access through resource config if exposed\nprint('Database configuration is set in server.cfg or environment variables')",
|
||||
'js_example' => "// Database configuration is typically in environment variables\n// Access through resource config if exposed\nconsole.log('Database configuration is set in server.cfg or environment variables');",
|
||||
],
|
||||
'Callbacks' => [
|
||||
'category' => 'Callbacks',
|
||||
'description' => 'Server-side callbacks that resources can register to respond to client requests.',
|
||||
'location' => 'qb-core/server/callbacks.lua',
|
||||
'config_options' => [
|
||||
['name' => 'RegisterCallback', 'type' => 'function', 'description' => 'Register a server callback that client scripts can call'],
|
||||
['name' => 'TriggerCallback', 'type' => 'function', 'description' => 'Trigger a callback from client to server with response'],
|
||||
],
|
||||
'lua_example' => "-- Server-side callback registration\nQBCore.Functions.CreateCallback('myResource:getData', function(source, cb, data)\n -- Process data from client\n cb({success = true, message = 'Data received'})\nend)\n\n-- Client-side callback usage\nQBCore.Functions.TriggerCallback('myResource:getData', function(result)\n print('Server response: ' .. result.message)\nend, myData)",
|
||||
'js_example' => "// Server-side callback registration\nQBCore.Functions.CreateCallback('myResource:getData', (source, cb, data) => {\n // Process data from client\n cb({success: true, message: 'Data received'});\n});\n\n// Client-side callback usage\nQBCore.Functions.TriggerCallback('myResource:getData', (result) => {\n console.log(`Server response: \${result.message}`);\n}, myData);",
|
||||
],
|
||||
'Features' => [
|
||||
'category' => 'Features',
|
||||
'description' => 'Framework feature flags and optional feature configurations.',
|
||||
'location' => 'qb-core/config.lua',
|
||||
'config_options' => [
|
||||
['name' => 'Encryption', 'type' => 'boolean', 'description' => 'Enable data encryption'],
|
||||
['name' => 'Logging', 'type' => 'boolean', 'description' => 'Enable comprehensive logging'],
|
||||
['name' => 'PerformanceMonitor', 'type' => 'boolean', 'description' => 'Monitor resource performance'],
|
||||
['name' => 'AntiCheat', 'type' => 'boolean', 'description' => 'Enable anti-cheat systems'],
|
||||
],
|
||||
'lua_example' => "local QBConfig = exports['qb-core']:GetCoreObject().Config\nif QBConfig.Encryption then\n print('Data encryption is enabled')\nend\nif QBConfig.AntiCheat then\n print('Anti-cheat is enabled')\nend",
|
||||
'js_example' => "const QBConfig = exports['qb-core']:GetCoreObject().Config;\nif (QBConfig.Encryption) {\n console.log('Data encryption is enabled');\n}\nif (QBConfig.AntiCheat) {\n console.log('Anti-cheat is enabled');\n}",
|
||||
],
|
||||
'RepTypes' => [
|
||||
'category' => 'RepTypes',
|
||||
'description' => 'Reputation types available for player progression. Defined in config for use with AddRep/RemoveRep.',
|
||||
'location' => 'qb-core/config.lua',
|
||||
'config_options' => [
|
||||
['name' => 'Examples', 'type' => 'table', 'description' => 'Common rep types: selling, heist, cartheft, etc.'],
|
||||
['name' => 'Custom', 'type' => 'string', 'description' => 'Add custom rep types in config for your resources'],
|
||||
],
|
||||
'lua_example' => "-- Add rep to player (types defined in config)\nPlayer.Functions.AddRep('selling', 10)\nPlayer.Functions.AddRep('heist', 5)\nPlayer.Functions.AddRep('cartheft', 15)\n\n-- Get current rep\nlocal sellingRep = Player.Functions.GetRep('selling')\nprint('Selling Rep: ' .. sellingRep)",
|
||||
'js_example' => "// Add rep to player (types defined in config)\nPlayer.Functions.AddRep('selling', 10);\nPlayer.Functions.AddRep('heist', 5);\nPlayer.Functions.AddRep('cartheft', 15);\n\n// Get current rep\nconst sellingRep = Player.Functions.GetRep('selling');\nconsole.log(`Selling Rep: \${sellingRep}`);",
|
||||
],
|
||||
];
|
||||
|
||||
$nameLower = strtolower($name);
|
||||
|
||||
foreach ($configs as $configName => $configData) {
|
||||
if (strtolower($configName) === $nameLower) {
|
||||
return $configData;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format config info.
|
||||
*/
|
||||
protected function formatConfigInfo(array $config, string $language): string
|
||||
{
|
||||
return view('mcp.qbcore.qbcore-config', [
|
||||
'config' => $config,
|
||||
'language' => $language,
|
||||
])->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tool's input schema.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\JsonSchema\JsonSchema>
|
||||
*/
|
||||
public function schema(JsonSchema $schema): array
|
||||
{
|
||||
return [
|
||||
'config_type' => $schema
|
||||
->string()
|
||||
->description('The type of QBCore configuration to look up (Player, Framework, Database, Callbacks, Features, RepTypes)')
|
||||
->enum(['Player', 'Framework', 'Database', 'Callbacks', 'Features', 'RepTypes'])
|
||||
->required(),
|
||||
'language' => $schema
|
||||
->string()
|
||||
->enum(['lua', 'js'])
|
||||
->description('The scripting language for code examples')
|
||||
->default('lua'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mcp\Tools\QBCore;
|
||||
|
||||
use Illuminate\Contracts\JsonSchema\JsonSchema;
|
||||
use Laravel\Mcp\Request;
|
||||
use Laravel\Mcp\Response;
|
||||
use Laravel\Mcp\Server\Attributes\Description;
|
||||
use Laravel\Mcp\Server\Tool;
|
||||
|
||||
#[Description('Look up information about the QBCore.Players table structure and how to access player data. Describes player object properties and methods.')]
|
||||
class GetQBCorePlayers extends Tool
|
||||
{
|
||||
/**
|
||||
* Handle the tool request.
|
||||
*/
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
$infoType = $request->get('info_type');
|
||||
$language = $request->get('language', 'lua');
|
||||
|
||||
$info = $this->findPlayerInfo($infoType);
|
||||
|
||||
if (! $info) {
|
||||
return Response::text(sprintf("QBCore player info '%s' not found. Available types: Structure, PlayerData, Methods, Events, Examples", $infoType));
|
||||
}
|
||||
|
||||
$output = $this->formatPlayerInfo($info, $language);
|
||||
|
||||
return Response::text($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find QBCore player information.
|
||||
*/
|
||||
protected function findPlayerInfo(string $name): ?array
|
||||
{
|
||||
$playerInfo = [
|
||||
'Structure' => [
|
||||
'type' => 'Structure',
|
||||
'title' => 'QBCore.Players Table Structure',
|
||||
'description' => 'The QBCore.Players table on the server contains all currently connected players indexed by their source (net ID).',
|
||||
'properties' => [
|
||||
['name' => 'QBCore.Players[source]', 'type' => 'table', 'description' => 'Player object for given source ID'],
|
||||
['name' => 'PlayerData', 'type' => 'table', 'description' => 'All player data (citizenid, job, gang, money, items, etc.)'],
|
||||
['name' => 'Functions', 'type' => 'table', 'description' => 'Methods available on player object (AddItem, RemoveItem, etc.)'],
|
||||
['name' => 'Metadata', 'type' => 'table', 'description' => 'Player metadata (hunger, thirst, stress, etc.)'],
|
||||
['name' => 'Inventory', 'type' => 'table', 'description' => 'Current inventory items and slots'],
|
||||
],
|
||||
'lua_example' => "-- Access a player by source (server-side)\nlocal Player = QBCore.Players[source]\nif Player then\n print('Player found: ' .. Player.PlayerData.charinfo.firstname)\nend\n\n-- Better to use the function instead:\nlocal Player = QBCore.Functions.GetPlayer(source)\nif Player then\n print('Player: ' .. Player.Functions.GetName())\nend",
|
||||
'js_example' => "// Access a player by source (server-side)\nconst Player = QBCore.Players[global.source];\nif (Player) {\n console.log(`Player found: \${Player.PlayerData.charinfo.firstname}`);\n}\n\n// Better to use the function instead:\nconst Player = QBCore.Functions.GetPlayer(global.source);\nif (Player) {\n console.log(`Player: \${Player.Functions.GetName()}`);\n}",
|
||||
],
|
||||
'PlayerData' => [
|
||||
'type' => 'PlayerData',
|
||||
'title' => 'Player Data Properties',
|
||||
'description' => 'Complete structure of the PlayerData table containing all player information.',
|
||||
'properties' => [
|
||||
['name' => 'source', 'type' => 'number', 'description' => 'Player net ID (used to identify player)'],
|
||||
['name' => 'citizenid', 'type' => 'string', 'description' => 'Unique character identifier'],
|
||||
['name' => 'cid', 'type' => 'number', 'description' => 'Character ID in database'],
|
||||
['name' => 'charinfo', 'type' => 'table', 'description' => 'Character information (firstname, lastname, gender, birthdate, etc.)'],
|
||||
['name' => 'job', 'type' => 'table', 'description' => 'Job information (name, label, grade, payment, onduty)'],
|
||||
['name' => 'gang', 'type' => 'table', 'description' => 'Gang information (name, label, grade, isboss)'],
|
||||
['name' => 'money', 'type' => 'table', 'description' => 'Money table (cash, bank accounts)'],
|
||||
['name' => 'metadata', 'type' => 'table', 'description' => 'Player metadata (hunger, thirst, stress, armor, health)'],
|
||||
['name' => 'items', 'type' => 'table', 'description' => 'Inventory items'],
|
||||
['name' => 'position', 'type' => 'vector3', 'description' => 'Player position coordinates'],
|
||||
['name' => 'licenses', 'type' => 'table', 'description' => 'Licenses owned by player'],
|
||||
],
|
||||
'lua_example' => "local Player = QBCore.Functions.GetPlayer(source)\nif Player then\n local pd = Player.PlayerData\n print('Name: ' .. pd.charinfo.firstname .. ' ' .. pd.charinfo.lastname)\n print('Citizen ID: ' .. pd.citizenid)\n print('Job: ' .. pd.job.name .. ' (Grade: ' .. pd.job.grade.level .. ')')\n print('Cash: $' .. pd.money.cash .. ' | Bank: $' .. pd.money.bank)\n print('Hunger: ' .. pd.metadata.hunger)\nend",
|
||||
'js_example' => "const Player = QBCore.Functions.GetPlayer(global.source);\nif (Player) {\n const pd = Player.PlayerData;\n console.log(`Name: \${pd.charinfo.firstname} \${pd.charinfo.lastname}`);\n console.log(`Citizen ID: \${pd.citizenid}`);\n console.log(`Job: \${pd.job.name} (Grade: \${pd.job.grade.level})`);\n console.log(`Cash: \\\$\${pd.money.cash} | Bank: \\\$\${pd.money.bank}`);\n console.log(`Hunger: \${pd.metadata.hunger}`);\n}",
|
||||
],
|
||||
'Methods' => [
|
||||
'type' => 'Methods',
|
||||
'title' => 'Player Object Methods',
|
||||
'description' => 'Functions available on the Player object for manipulating player data.',
|
||||
'methods' => [
|
||||
['name' => 'AddItem(item, amount)', 'description' => 'Add item to player inventory'],
|
||||
['name' => 'RemoveItem(item, amount)', 'description' => 'Remove item from player inventory'],
|
||||
['name' => 'HasItem(item, amount)', 'description' => 'Check if player has item'],
|
||||
['name' => 'GetItemByName(item)', 'description' => 'Get item data by name'],
|
||||
['name' => 'AddMoney(type, amount, reason)', 'description' => 'Add money to player account'],
|
||||
['name' => 'RemoveMoney(type, amount, reason)', 'description' => 'Remove money from player account'],
|
||||
['name' => 'SetMoney(type, amount, reason)', 'description' => 'Set money to exact amount'],
|
||||
['name' => 'GetMoney(type)', 'description' => 'Get player money amount'],
|
||||
['name' => 'SetJob(job, grade)', 'description' => 'Set player job and grade'],
|
||||
['name' => 'GetJob()', 'description' => 'Get player job data'],
|
||||
['name' => 'SetJobDuty(onDuty)', 'description' => 'Set player on/off duty'],
|
||||
['name' => 'SetGang(gang, grade)', 'description' => 'Set player gang and grade'],
|
||||
['name' => 'SetPlayerData(key, value)', 'description' => 'Set player data by key'],
|
||||
['name' => 'SetMetaData(key, value)', 'description' => 'Set player metadata by key'],
|
||||
['name' => 'GetMetaData(key)', 'description' => 'Get player metadata by key'],
|
||||
['name' => 'AddRep(type, amount)', 'description' => 'Add reputation points'],
|
||||
['name' => 'RemoveRep(type, amount)', 'description' => 'Remove reputation points'],
|
||||
['name' => 'GetRep(type)', 'description' => 'Get reputation value'],
|
||||
['name' => 'Notify(text, type, duration)', 'description' => 'Send notification to player'],
|
||||
['name' => 'Save()', 'description' => 'Save player data to database'],
|
||||
['name' => 'UpdatePlayerData()', 'description' => 'Sync player data to client'],
|
||||
['name' => 'GetName()', 'description' => 'Get full player name'],
|
||||
['name' => 'Logout()', 'description' => 'Force player to logout'],
|
||||
],
|
||||
'lua_example' => "local Player = QBCore.Functions.GetPlayer(source)\nif Player then\n -- Manage inventory\n Player.Functions.AddItem('water', 5)\n Player.Functions.RemoveItem('water', 2)\n \n -- Manage money\n Player.Functions.AddMoney('cash', 1000, 'Salary')\n local cash = Player.Functions.GetMoney('cash')\n \n -- Set job\n Player.Functions.SetJob('police', 2)\n Player.Functions.SetJobDuty(true)\n \n -- Notify player\n Player.Functions.Notify('Welcome to the server!', 'success')\n \n -- Save changes\n Player.Functions.Save()\nend",
|
||||
'js_example' => "const Player = QBCore.Functions.GetPlayer(global.source);\nif (Player) {\n // Manage inventory\n Player.Functions.AddItem('water', 5);\n Player.Functions.RemoveItem('water', 2);\n \n // Manage money\n Player.Functions.AddMoney('cash', 1000, 'Salary');\n const cash = Player.Functions.GetMoney('cash');\n \n // Set job\n Player.Functions.SetJob('police', 2);\n Player.Functions.SetJobDuty(true);\n \n // Notify player\n Player.Functions.Notify('Welcome to the server!', 'success');\n \n // Save changes\n Player.Functions.Save();\n}",
|
||||
],
|
||||
'Events' => [
|
||||
'type' => 'Events',
|
||||
'title' => 'Player-Related Events',
|
||||
'description' => 'Events triggered when player data changes or player actions occur.',
|
||||
'events' => [
|
||||
['name' => 'QBCore:Player:SetPlayerData', 'description' => 'Triggered when player data is updated'],
|
||||
['name' => 'QBCore:Server:OnJobUpdate', 'description' => 'Triggered when player job is changed'],
|
||||
['name' => 'QBCore:Client:OnJobUpdate', 'description' => 'Client-side job update event'],
|
||||
['name' => 'QBCore:Player:PlayerLoaded', 'description' => 'Triggered when player finishes loading'],
|
||||
['name' => 'QBCore:Player:PlayerLoggedOut', 'description' => 'Triggered when player logs out'],
|
||||
],
|
||||
'lua_example' => "-- Server-side: Listen for job updates\nRegisterNetEvent('QBCore:Server:OnJobUpdate', function(source)\n local Player = QBCore.Functions.GetPlayer(source)\n if Player then\n print(Player.Functions.GetName() .. ' job updated to ' .. Player.PlayerData.job.name)\n end\nend)\n\n-- Client-side: Listen for player load\nRegisterNetEvent('QBCore:Player:SetPlayerData')\nAddEventHandler('QBCore:Player:SetPlayerData', function()\n local playerData = QBCore.Functions.GetPlayerData()\n print('Player data updated!')\nend)",
|
||||
'js_example' => "// Server-side: Listen for job updates\non('QBCore:Server:OnJobUpdate', (source) => {\n const Player = QBCore.Functions.GetPlayer(source);\n if (Player) {\n console.log(`\${Player.Functions.GetName()} job updated to \${Player.PlayerData.job.name}`);\n }\n});\n\n// Client-side: Listen for player load\non('QBCore:Player:SetPlayerData', () => {\n const playerData = QBCore.Functions.GetPlayerData();\n console.log('Player data updated!');\n});",
|
||||
],
|
||||
'Examples' => [
|
||||
'type' => 'Examples',
|
||||
'title' => 'Common Player Usage Examples',
|
||||
'description' => 'Real-world examples of working with player objects in QBCore.',
|
||||
'lua_example' => "-- Example 1: Check if player has items before proceeding\nlocal Player = QBCore.Functions.GetPlayer(source)\nif Player then\n if Player.Functions.HasItem('police_badge', 1) then\n print('Player is a police officer')\n end\nend\n\n-- Example 2: Transfer money between players\nlocal Player1 = QBCore.Functions.GetPlayer(source)\nlocal Player2 = QBCore.Functions.GetPlayerByCitizenId(citizenid)\nif Player1 and Player2 then\n local amount = 500\n if Player1.Functions.RemoveMoney('cash', amount) then\n Player2.Functions.AddMoney('cash', amount, 'Player Transfer')\n Player1.Functions.Notify('Gave \$' .. amount .. ' to ' .. Player2.Functions.GetName(), 'success')\n Player2.Functions.Notify('Received \$' .. amount .. ' from ' .. Player1.Functions.GetName(), 'success')\n end\nend\n\n-- Example 3: Job paycheck system\nfor i = 1, #QBCore.Functions.GetPlayers() do\n local Player = QBCore.Functions.GetPlayer(QBCore.Functions.GetPlayers()[i])\n if Player and Player.PlayerData.job.onduty then\n local payment = Player.PlayerData.job.payment\n Player.Functions.AddMoney('bank', payment, 'Salary')\n Player.Functions.Notify('Received \$' .. payment .. ' salary', 'success')\n end\nend",
|
||||
'js_example' => "// Example 1: Check if player has items before proceeding\nconst Player = QBCore.Functions.GetPlayer(global.source);\nif (Player) {\n if (Player.Functions.HasItem('police_badge', 1)) {\n console.log('Player is a police officer');\n }\n}\n\n// Example 2: Transfer money between players\nconst Player1 = QBCore.Functions.GetPlayer(global.source);\nconst Player2 = QBCore.Functions.GetPlayerByCitizenId(citizenid);\nif (Player1 && Player2) {\n const amount = 500;\n if (Player1.Functions.RemoveMoney('cash', amount)) {\n Player2.Functions.AddMoney('cash', amount, 'Player Transfer');\n Player1.Functions.Notify(`Gave \\\$\${amount} to \${Player2.Functions.GetName()}`, 'success');\n Player2.Functions.Notify(`Received \\\$\${amount} from \${Player1.Functions.GetName()}`, 'success');\n }\n}\n\n// Example 3: Job paycheck system\nconst players = QBCore.Functions.GetPlayers();\nfor (const playerId of players) {\n const Player = QBCore.Functions.GetPlayer(playerId);\n if (Player && Player.PlayerData.job.onduty) {\n const payment = Player.PlayerData.job.payment;\n Player.Functions.AddMoney('bank', payment, 'Salary');\n Player.Functions.Notify(`Received \\\$\${payment} salary`, 'success');\n }\n}",
|
||||
],
|
||||
];
|
||||
|
||||
$nameLower = strtolower($name);
|
||||
|
||||
foreach ($playerInfo as $infoName => $infoData) {
|
||||
if (strtolower($infoName) === $nameLower) {
|
||||
return $infoData;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format player info.
|
||||
*/
|
||||
protected function formatPlayerInfo(array $info, string $language): string
|
||||
{
|
||||
return view('mcp.qbcore.qbcore-players', [
|
||||
'info' => $info,
|
||||
'language' => $language,
|
||||
])->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tool's input schema.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\JsonSchema\JsonSchema>
|
||||
*/
|
||||
public function schema(JsonSchema $schema): array
|
||||
{
|
||||
return [
|
||||
'info_type' => $schema
|
||||
->string()
|
||||
->description('The type of QBCore player information to look up (Structure, PlayerData, Methods, Events, Examples)')
|
||||
->enum(['Structure', 'PlayerData', 'Methods', 'Events', 'Examples'])
|
||||
->required(),
|
||||
'language' => $schema
|
||||
->string()
|
||||
->enum(['lua', 'js'])
|
||||
->description('The scripting language for code examples')
|
||||
->default('lua'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mcp\Tools\QBCore;
|
||||
|
||||
use Illuminate\Contracts\JsonSchema\JsonSchema;
|
||||
use Laravel\Mcp\Request;
|
||||
use Laravel\Mcp\Response;
|
||||
use Laravel\Mcp\Server\Attributes\Description;
|
||||
use Laravel\Mcp\Server\Tool;
|
||||
|
||||
#[Description('Look up QBCore shared data structure by name. Returns information about items, jobs, gangs, vehicles, weapons, and utility functions.')]
|
||||
class GetQBCoreSharedData extends Tool
|
||||
{
|
||||
/**
|
||||
* Handle the tool request.
|
||||
*/
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
$dataType = $request->get('data_type');
|
||||
$language = $request->get('language', 'lua');
|
||||
|
||||
$data = $this->findSharedData($dataType);
|
||||
|
||||
if (! $data) {
|
||||
return Response::text(sprintf("QBCore shared data '%s' not found. Available types: Items, Jobs, Gangs, Vehicles, Weapons, StarterItems, Utilities", $dataType));
|
||||
}
|
||||
|
||||
$output = $this->formatSharedInfo($data, $language);
|
||||
|
||||
return Response::text($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a QBCore shared data type.
|
||||
*/
|
||||
protected function findSharedData(string $name): ?array
|
||||
{
|
||||
$sharedData = [
|
||||
'Items' => [
|
||||
'type' => 'Items',
|
||||
'description' => 'Table of all items available on the server. Each item has properties like label, weight, type, image, useable, etc.',
|
||||
'location' => 'qb-core/shared/items.lua',
|
||||
'properties' => [
|
||||
['name' => 'name', 'type' => 'string', 'description' => 'Internal item identifier'],
|
||||
['name' => 'label', 'type' => 'string', 'description' => 'Display name shown to players'],
|
||||
['name' => 'weight', 'type' => 'number', 'description' => 'Item weight (affects inventory limit)'],
|
||||
['name' => 'type', 'type' => 'string', 'description' => 'Item type (item, weapon, component, etc.)'],
|
||||
['name' => 'image', 'type' => 'string', 'description' => 'Image filename for inventory display'],
|
||||
['name' => 'unique', 'type' => 'boolean', 'description' => 'If true, item cannot be stacked'],
|
||||
['name' => 'useable', 'type' => 'boolean', 'description' => 'If true, item can be used/consumed'],
|
||||
['name' => 'shouldClose', 'type' => 'boolean', 'description' => 'If true, inventory closes when using item'],
|
||||
['name' => 'description', 'type' => 'string', 'description' => 'Item description shown in inventory'],
|
||||
],
|
||||
'lua_example' => "local QBCore = exports['qb-core']:GetCoreObject({'Shared'})\nlocal item = QBCore.Shared.Items['water_bottle']\nif item then\n print('Item: ' .. item.label .. ' (Weight: ' .. item.weight .. ')')\nend",
|
||||
'js_example' => "const QBCore = exports['qb-core']:GetCoreObject(['Shared']);\nconst item = QBCore.Shared.Items['water_bottle'];\nif (item) {\n console.log(`Item: \${item.label} (Weight: \${item.weight})`);\n}",
|
||||
],
|
||||
'Jobs' => [
|
||||
'type' => 'Jobs',
|
||||
'description' => 'Table of all jobs available on the server. Each job has grades (ranks) and payment amounts.',
|
||||
'location' => 'qb-core/shared/jobs.lua',
|
||||
'properties' => [
|
||||
['name' => 'label', 'type' => 'string', 'description' => 'Job display name'],
|
||||
['name' => 'type', 'type' => 'string', 'description' => 'Job type (leo, illegal, casino, etc.)'],
|
||||
['name' => 'defaultDuty', 'type' => 'boolean', 'description' => 'If true, player starts on duty'],
|
||||
['name' => 'offDutyPay', 'type' => 'boolean', 'description' => 'If true, player gets paid while off duty'],
|
||||
['name' => 'grades', 'type' => 'table', 'description' => 'Array of job grades with name and payment'],
|
||||
],
|
||||
'lua_example' => "local QBCore = exports['qb-core']:GetCoreObject({'Shared'})\nlocal job = QBCore.Shared.Jobs['police']\nif job then\n print('Job: ' .. job.label)\n for i = 1, #job.grades do\n local grade = job.grades[i]\n print(' Grade: ' .. grade.name .. ' (Payment: $' .. grade.payment .. ')')\n end\nend",
|
||||
'js_example' => "const QBCore = exports['qb-core']:GetCoreObject(['Shared']);\nconst job = QBCore.Shared.Jobs['police'];\nif (job) {\n console.log(`Job: \${job.label}`);\n job.grades.forEach((grade, i) => {\n console.log(` Grade: \${grade.name} (Payment: \\\$\${grade.payment})`);\n });\n}",
|
||||
],
|
||||
'Gangs' => [
|
||||
'type' => 'Gangs',
|
||||
'description' => 'Table of all gangs available on the server. Similar structure to jobs with labels and grades.',
|
||||
'location' => 'qb-core/shared/gangs.lua',
|
||||
'properties' => [
|
||||
['name' => 'label', 'type' => 'string', 'description' => 'Gang display name'],
|
||||
['name' => 'grades', 'type' => 'table', 'description' => 'Array of gang grades/ranks'],
|
||||
],
|
||||
'lua_example' => "local QBCore = exports['qb-core']:GetCoreObject({'Shared'})\nlocal gang = QBCore.Shared.Gangs['lostmc']\nif gang then\n print('Gang: ' .. gang.label)\n for i = 1, #gang.grades do\n print(' Rank: ' .. gang.grades[i].name)\n end\nend",
|
||||
'js_example' => "const QBCore = exports['qb-core']:GetCoreObject(['Shared']);\nconst gang = QBCore.Shared.Gangs['lostmc'];\nif (gang) {\n console.log(`Gang: \${gang.label}`);\n gang.grades.forEach((grade) => {\n console.log(` Rank: \${grade.name}`);\n });\n}",
|
||||
],
|
||||
'Vehicles' => [
|
||||
'type' => 'Vehicles',
|
||||
'description' => 'Table of all vehicle models available on the server. Indexed by model name for quick lookup.',
|
||||
'location' => 'qb-core/shared/vehicles.lua',
|
||||
'properties' => [
|
||||
['name' => 'model', 'type' => 'string', 'description' => 'Vehicle model spawn code'],
|
||||
['name' => 'name', 'type' => 'string', 'description' => 'Vehicle display name'],
|
||||
['name' => 'brand', 'type' => 'string', 'description' => 'Vehicle manufacturer/brand'],
|
||||
['name' => 'price', 'type' => 'number', 'description' => 'Vehicle resale price'],
|
||||
['name' => 'category', 'type' => 'string', 'description' => 'Vehicle category (compacts, sedans, etc.)'],
|
||||
['name' => 'type', 'type' => 'string', 'description' => 'Vehicle type (automobile, bike, helicopter, etc.)'],
|
||||
['name' => 'shop', 'type' => 'string|table', 'description' => 'Shop(s) where vehicle can be purchased'],
|
||||
],
|
||||
'lua_example' => "local QBCore = exports['qb-core']:GetCoreObject({'Shared'})\nlocal vehicle = QBCore.Shared.Vehicles['adder']\nif vehicle then\n print('Vehicle: ' .. vehicle.name .. ' by ' .. vehicle.brand)\n print('Price: $' .. vehicle.price)\nend",
|
||||
'js_example' => "const QBCore = exports['qb-core']:GetCoreObject(['Shared']);\nconst vehicle = QBCore.Shared.Vehicles['adder'];\nif (vehicle) {\n console.log(`Vehicle: \${vehicle.name} by \${vehicle.brand}`);\n console.log(`Price: \\\$\${vehicle.price}`);\n}",
|
||||
],
|
||||
'Weapons' => [
|
||||
'type' => 'Weapons',
|
||||
'description' => 'Table of all weapons indexed by weapon hash. Used for retrieving weapon information.',
|
||||
'location' => 'qb-core/shared/weapons.lua',
|
||||
'properties' => [
|
||||
['name' => 'name', 'type' => 'string', 'description' => 'Weapon model/spawn name'],
|
||||
['name' => 'label', 'type' => 'string', 'description' => 'Weapon display name'],
|
||||
['name' => 'weapontype', 'type' => 'string', 'description' => 'Weapon type (Pistol, Rifle, Shotgun, etc.)'],
|
||||
['name' => 'ammotype', 'type' => 'string', 'description' => 'Ammo type used by weapon'],
|
||||
['name' => 'damageReason', 'type' => 'string', 'description' => 'Death notification message for kills'],
|
||||
],
|
||||
'lua_example' => "local QBCore = exports['qb-core']:GetCoreObject({'Shared'})\nlocal weapon = QBCore.Shared.Weapons[`weapon_pistol`]\nif weapon then\n print('Weapon: ' .. weapon.label .. ' (' .. weapon.weapontype .. ')')\nend",
|
||||
'js_example' => "const QBCore = exports['qb-core']:GetCoreObject(['Shared']);\nconst weapon = QBCore.Shared.Weapons['weapon_pistol'];\nif (weapon) {\n console.log(`Weapon: \${weapon.label} (\${weapon.weapontype})`);\n}",
|
||||
],
|
||||
'StarterItems' => [
|
||||
'type' => 'StarterItems',
|
||||
'description' => 'Table of items that new players receive when first joining. Defines item name and amount.',
|
||||
'location' => 'qb-core/shared/main.lua',
|
||||
'properties' => [
|
||||
['name' => 'item_name', 'type' => 'string', 'description' => 'Item to give to new players'],
|
||||
['name' => 'amount', 'type' => 'number', 'description' => 'Amount of item to give'],
|
||||
],
|
||||
'lua_example' => "local QBCore = exports['qb-core']:GetCoreObject({'Shared'})\nfor item, amount in pairs(QBCore.Shared.StarterItems) do\n local itemInfo = QBCore.Shared.Items[item]\n if itemInfo then\n print('New players get ' .. amount .. 'x ' .. itemInfo.label)\n end\nend",
|
||||
'js_example' => "const QBCore = exports['qb-core']:GetCoreObject(['Shared']);\nfor (const [item, amount] of Object.entries(QBCore.Shared.StarterItems)) {\n const itemInfo = QBCore.Shared.Items[item];\n if (itemInfo) {\n console.log(`New players get \${amount}x \${itemInfo.label}`);\n }\n}",
|
||||
],
|
||||
'Utilities' => [
|
||||
'type' => 'Utilities',
|
||||
'description' => 'Utility functions available in QBShared for common operations like string manipulation and vehicle handling.',
|
||||
'location' => 'qb-core/shared/main.lua',
|
||||
'methods' => [
|
||||
['name' => 'RandomStr(length)', 'description' => 'Generate random string of specified length'],
|
||||
['name' => 'RandomInt(length)', 'description' => 'Generate random numeric string of specified length'],
|
||||
['name' => 'SplitStr(str, delimiter)', 'description' => 'Split string by delimiter into table'],
|
||||
['name' => 'Trim(value)', 'description' => 'Remove leading/trailing whitespace'],
|
||||
['name' => 'Round(number, decimals)', 'description' => 'Round number to specified decimal places'],
|
||||
['name' => 'ChangeVehicleExtra(vehicle, extra, enable)', 'description' => 'Toggle vehicle extra on/off'],
|
||||
['name' => 'SetDefaultVehicleExtras(vehicle, config)', 'description' => 'Set default vehicle extras from config table'],
|
||||
],
|
||||
'lua_example' => "local QBCore = exports['qb-core']:GetCoreObject({'Shared'})\nlocal randomId = QBCore.Shared.RandomStr(8)\nlocal trimmed = QBCore.Shared.Trim(' hello world ')\nlocal rounded = QBCore.Shared.Round(3.14159, 2) -- Returns 3.14\nprint('Random ID: ' .. randomId)\nprint('Trimmed: ' .. trimmed)\nprint('Rounded: ' .. rounded)",
|
||||
'js_example' => "const QBCore = exports['qb-core']:GetCoreObject(['Shared']);\nconst randomId = QBCore.Shared.RandomStr(8);\nconst trimmed = QBCore.Shared.Trim(' hello world ');\nconst rounded = QBCore.Shared.Round(3.14159, 2); // Returns 3.14\nconsole.log(`Random ID: \${randomId}`);\nconsole.log(`Trimmed: \${trimmed}`);\nconsole.log(`Rounded: \${rounded}`);",
|
||||
],
|
||||
];
|
||||
|
||||
$nameLower = strtolower($name);
|
||||
|
||||
foreach ($sharedData as $typeName => $typeData) {
|
||||
if (strtolower($typeName) === $nameLower) {
|
||||
return $typeData;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format shared data info.
|
||||
*/
|
||||
protected function formatSharedInfo(array $data, string $language): string
|
||||
{
|
||||
return view('mcp.qbcore.qbcore-shared-data', [
|
||||
'data' => $data,
|
||||
'language' => $language,
|
||||
])->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tool's input schema.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\JsonSchema\JsonSchema>
|
||||
*/
|
||||
public function schema(JsonSchema $schema): array
|
||||
{
|
||||
return [
|
||||
'data_type' => $schema
|
||||
->string()
|
||||
->description('The type of QBCore shared data to look up (Items, Jobs, Gangs, Vehicles, Weapons, StarterItems, Utilities)')
|
||||
->enum(['Items', 'Jobs', 'Gangs', 'Vehicles', 'Weapons', 'StarterItems', 'Utilities'])
|
||||
->required(),
|
||||
'language' => $schema
|
||||
->string()
|
||||
->enum(['lua', 'js'])
|
||||
->description('The scripting language for code examples')
|
||||
->default('lua'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -178,6 +178,193 @@ class GetQBCoreServerFunction extends Tool
|
||||
'lua_example' => "local Player = QBCore.Functions.GetPlayer(source)\nif Player then\n Player.Functions.DeleteVehicle('QBTEST')\n TriggerClientEvent('QBCore:Notify', source, 'Vehicle removed from garage')\nend",
|
||||
'js_example' => "const Player = QBCore.Functions.GetPlayer(global.source);\nif (Player) {\n Player.Functions.DeleteVehicle('QBTEST');\n TriggerClientEvent('QBCore:Notify', global.source, 'Vehicle removed from garage');\n}",
|
||||
],
|
||||
'SetGang' => [
|
||||
'namespace' => 'Player',
|
||||
'description' => 'Set a player\'s gang and grade (server-side)',
|
||||
'side' => 'server',
|
||||
'parameters' => [
|
||||
['name' => 'gangName', 'type' => 'string', 'description' => 'The gang name'],
|
||||
['name' => 'grade', 'type' => 'number', 'description' => 'The gang grade/rank level'],
|
||||
],
|
||||
'returns' => ['type' => 'boolean', 'description' => 'Success status'],
|
||||
'lua_example' => "local Player = QBCore.Functions.GetPlayer(source)\nif Player then\n Player.Functions.SetGang('lostmc', 1)\n TriggerClientEvent('QBCore:Notify', source, 'You joined the gang', 'success')\nend",
|
||||
'js_example' => "const Player = QBCore.Functions.GetPlayer(global.source);\nif (Player) {\n Player.Functions.SetGang('lostmc', 1);\n TriggerClientEvent('QBCore:Notify', global.source, 'You joined the gang', 'success');\n}",
|
||||
],
|
||||
'Notify' => [
|
||||
'namespace' => 'Player',
|
||||
'description' => 'Send a notification to a player (server-side)',
|
||||
'side' => 'server',
|
||||
'parameters' => [
|
||||
['name' => 'text', 'type' => 'string', 'description' => 'Notification text'],
|
||||
['name' => 'type', 'type' => 'string', 'description' => 'Notification type: error, success, primary, warning'],
|
||||
['name' => 'duration', 'type' => 'number|nil', 'description' => 'Duration in milliseconds (default 5000)'],
|
||||
],
|
||||
'returns' => ['type' => 'void', 'description' => ''],
|
||||
'lua_example' => "local Player = QBCore.Functions.GetPlayer(source)\nif Player then\n Player.Functions.Notify('Hello!', 'success', 5000)\nend",
|
||||
'js_example' => "const Player = QBCore.Functions.GetPlayer(global.source);\nif (Player) {\n Player.Functions.Notify('Hello!', 'success', 5000);\n}",
|
||||
],
|
||||
'HasItem' => [
|
||||
'namespace' => 'Player',
|
||||
'description' => 'Check if a player has an item (server-side)',
|
||||
'side' => 'server',
|
||||
'parameters' => [
|
||||
['name' => 'item', 'type' => 'string|table', 'description' => 'Item name or array of item names'],
|
||||
['name' => 'amount', 'type' => 'number', 'description' => 'Amount required (default 1)'],
|
||||
],
|
||||
'returns' => ['type' => 'boolean', 'description' => 'True if player has the item(s)'],
|
||||
'lua_example' => "local Player = QBCore.Functions.GetPlayer(source)\nif Player then\n if Player.Functions.HasItem('water_bottle', 1) then\n print('Player has water')\n end\nend",
|
||||
'js_example' => "const Player = QBCore.Functions.GetPlayer(global.source);\nif (Player) {\n if (Player.Functions.HasItem('water_bottle', 1)) {\n console.log('Player has water');\n }\n}",
|
||||
],
|
||||
'GetName' => [
|
||||
'namespace' => 'Player',
|
||||
'description' => 'Get a player\'s full character name (server-side)',
|
||||
'side' => 'server',
|
||||
'parameters' => [],
|
||||
'returns' => ['type' => 'string', 'description' => 'Full name (first lastname)'],
|
||||
'lua_example' => "local Player = QBCore.Functions.GetPlayer(source)\nif Player then\n local fullName = Player.Functions.GetName()\n print('Player name: ' .. fullName)\nend",
|
||||
'js_example' => "const Player = QBCore.Functions.GetPlayer(global.source);\nif (Player) {\n const fullName = Player.Functions.GetName();\n console.log(`Player name: \${fullName}`);\n}",
|
||||
],
|
||||
'SetJobDuty' => [
|
||||
'namespace' => 'Player',
|
||||
'description' => 'Set a player on/off duty for their job (server-side)',
|
||||
'side' => 'server',
|
||||
'parameters' => [
|
||||
['name' => 'onDuty', 'type' => 'boolean', 'description' => 'True to set on duty, false to set off duty'],
|
||||
],
|
||||
'returns' => ['type' => 'void', 'description' => ''],
|
||||
'lua_example' => "local Player = QBCore.Functions.GetPlayer(source)\nif Player then\n Player.Functions.SetJobDuty(true)\n Player.Functions.Notify('You are now on duty', 'success')\nend",
|
||||
'js_example' => "const Player = QBCore.Functions.GetPlayer(global.source);\nif (Player) {\n Player.Functions.SetJobDuty(true);\n Player.Functions.Notify('You are now on duty', 'success');\n}",
|
||||
],
|
||||
'SetPlayerData' => [
|
||||
'namespace' => 'Player',
|
||||
'description' => 'Set a player data value by key (server-side)',
|
||||
'side' => 'server',
|
||||
'parameters' => [
|
||||
['name' => 'key', 'type' => 'string', 'description' => 'The player data key to set'],
|
||||
['name' => 'value', 'type' => 'any', 'description' => 'The value to set'],
|
||||
],
|
||||
'returns' => ['type' => 'void', 'description' => ''],
|
||||
'lua_example' => "local Player = QBCore.Functions.GetPlayer(source)\nif Player then\n Player.Functions.SetPlayerData('position', vector3(-425.3, 1123.6, 325.0))\nend",
|
||||
'js_example' => "const Player = QBCore.Functions.GetPlayer(global.source);\nif (Player) {\n Player.Functions.SetPlayerData('position', [-425.3, 1123.6, 325.0]);\n}",
|
||||
],
|
||||
'SetMetaData' => [
|
||||
'namespace' => 'Player',
|
||||
'description' => 'Set a player metadata value by key (server-side)',
|
||||
'side' => 'server',
|
||||
'parameters' => [
|
||||
['name' => 'key', 'type' => 'string', 'description' => 'The metadata key to set'],
|
||||
['name' => 'value', 'type' => 'any', 'description' => 'The value to set'],
|
||||
],
|
||||
'returns' => ['type' => 'void', 'description' => ''],
|
||||
'lua_example' => "local Player = QBCore.Functions.GetPlayer(source)\nif Player then\n Player.Functions.SetMetaData('hunger', 80)\n Player.Functions.SetMetaData('thirst', 70)\nend",
|
||||
'js_example' => "const Player = QBCore.Functions.GetPlayer(global.source);\nif (Player) {\n Player.Functions.SetMetaData('hunger', 80);\n Player.Functions.SetMetaData('thirst', 70);\n}",
|
||||
],
|
||||
'GetMetaData' => [
|
||||
'namespace' => 'Player',
|
||||
'description' => 'Get a player metadata value by key (server-side)',
|
||||
'side' => 'server',
|
||||
'parameters' => [
|
||||
['name' => 'key', 'type' => 'string', 'description' => 'The metadata key to retrieve'],
|
||||
],
|
||||
'returns' => ['type' => 'any', 'description' => 'The metadata value'],
|
||||
'lua_example' => "local Player = QBCore.Functions.GetPlayer(source)\nif Player then\n local hunger = Player.Functions.GetMetaData('hunger')\n print('Hunger Level: ' .. hunger)\nend",
|
||||
'js_example' => "const Player = QBCore.Functions.GetPlayer(global.source);\nif (Player) {\n const hunger = Player.Functions.GetMetaData('hunger');\n console.log(`Hunger Level: \${hunger}`);\n}",
|
||||
],
|
||||
'AddRep' => [
|
||||
'namespace' => 'Player',
|
||||
'description' => 'Add reputation points to a player (server-side)',
|
||||
'side' => 'server',
|
||||
'parameters' => [
|
||||
['name' => 'repType', 'type' => 'string', 'description' => 'Type of reputation to add (e.g., selling, heist)'],
|
||||
['name' => 'amount', 'type' => 'number', 'description' => 'Amount of reputation to add'],
|
||||
],
|
||||
'returns' => ['type' => 'void', 'description' => ''],
|
||||
'lua_example' => "local Player = QBCore.Functions.GetPlayer(source)\nif Player then\n Player.Functions.AddRep('selling', 10)\nend",
|
||||
'js_example' => "const Player = QBCore.Functions.GetPlayer(global.source);\nif (Player) {\n Player.Functions.AddRep('selling', 10);\n}",
|
||||
],
|
||||
'RemoveRep' => [
|
||||
'namespace' => 'Player',
|
||||
'description' => 'Remove reputation points from a player (server-side)',
|
||||
'side' => 'server',
|
||||
'parameters' => [
|
||||
['name' => 'repType', 'type' => 'string', 'description' => 'Type of reputation to remove'],
|
||||
['name' => 'amount', 'type' => 'number', 'description' => 'Amount of reputation to remove'],
|
||||
],
|
||||
'returns' => ['type' => 'void', 'description' => ''],
|
||||
'lua_example' => "local Player = QBCore.Functions.GetPlayer(source)\nif Player then\n Player.Functions.RemoveRep('selling', 5)\nend",
|
||||
'js_example' => "const Player = QBCore.Functions.GetPlayer(global.source);\nif (Player) {\n Player.Functions.RemoveRep('selling', 5);\n}",
|
||||
],
|
||||
'GetRep' => [
|
||||
'namespace' => 'Player',
|
||||
'description' => 'Get a player\'s reputation value (server-side)',
|
||||
'side' => 'server',
|
||||
'parameters' => [
|
||||
['name' => 'repType', 'type' => 'string', 'description' => 'Type of reputation to retrieve'],
|
||||
],
|
||||
'returns' => ['type' => 'number', 'description' => 'Reputation value'],
|
||||
'lua_example' => "local Player = QBCore.Functions.GetPlayer(source)\nif Player then\n local sellingRep = Player.Functions.GetRep('selling')\n print('Selling Rep: ' .. sellingRep)\nend",
|
||||
'js_example' => "const Player = QBCore.Functions.GetPlayer(global.source);\nif (Player) {\n const sellingRep = Player.Functions.GetRep('selling');\n console.log(`Selling Rep: \${sellingRep}`);\n}",
|
||||
],
|
||||
'SetMoney' => [
|
||||
'namespace' => 'Player',
|
||||
'description' => 'Set a player\'s money to a specific amount (server-side)',
|
||||
'side' => 'server',
|
||||
'parameters' => [
|
||||
['name' => 'moneyType', 'type' => 'string', 'description' => 'Type: "cash", "bank", or custom'],
|
||||
['name' => 'amount', 'type' => 'number', 'description' => 'Amount to set'],
|
||||
['name' => 'reason', 'type' => 'string|nil', 'description' => 'Optional reason for logging'],
|
||||
],
|
||||
'returns' => ['type' => 'boolean', 'description' => 'Success status'],
|
||||
'lua_example' => "local Player = QBCore.Functions.GetPlayer(source)\nif Player then\n Player.Functions.SetMoney('cash', 5000, 'Admin Command')\n Player.Functions.Notify('Your cash has been set', 'info')\nend",
|
||||
'js_example' => "const Player = QBCore.Functions.GetPlayer(global.source);\nif (Player) {\n Player.Functions.SetMoney('cash', 5000, 'Admin Command');\n Player.Functions.Notify('Your cash has been set', 'info');\n}",
|
||||
],
|
||||
'Save' => [
|
||||
'namespace' => 'Player',
|
||||
'description' => 'Save a player\'s data to the database (server-side)',
|
||||
'side' => 'server',
|
||||
'parameters' => [],
|
||||
'returns' => ['type' => 'void', 'description' => ''],
|
||||
'lua_example' => "local Player = QBCore.Functions.GetPlayer(source)\nif Player then\n Player.Functions.Save()\nend",
|
||||
'js_example' => "const Player = QBCore.Functions.GetPlayer(global.source);\nif (Player) {\n Player.Functions.Save();\n}",
|
||||
],
|
||||
'Logout' => [
|
||||
'namespace' => 'Player',
|
||||
'description' => 'Force a player to logout to the character selection (server-side)',
|
||||
'side' => 'server',
|
||||
'parameters' => [],
|
||||
'returns' => ['type' => 'void', 'description' => ''],
|
||||
'lua_example' => "local Player = QBCore.Functions.GetPlayer(source)\nif Player then\n Player.Functions.Logout()\nend",
|
||||
'js_example' => "const Player = QBCore.Functions.GetPlayer(global.source);\nif (Player) {\n Player.Functions.Logout();\n}",
|
||||
],
|
||||
'UpdatePlayerData' => [
|
||||
'namespace' => 'Player',
|
||||
'description' => 'Update the player data on client and server (server-side)',
|
||||
'side' => 'server',
|
||||
'parameters' => [],
|
||||
'returns' => ['type' => 'void', 'description' => ''],
|
||||
'lua_example' => "local Player = QBCore.Functions.GetPlayer(source)\nif Player then\n Player.Functions.UpdatePlayerData()\nend",
|
||||
'js_example' => "const Player = QBCore.Functions.GetPlayer(global.source);\nif (Player) {\n Player.Functions.UpdatePlayerData();\n}",
|
||||
],
|
||||
'GetPlayerBophone' => [
|
||||
'namespace' => 'Core',
|
||||
'description' => 'Get a player by their phone number (server-side only)',
|
||||
'side' => 'server',
|
||||
'parameters' => [
|
||||
['name' => 'phoneNumber', 'type' => 'string', 'description' => 'The phone number to search for'],
|
||||
],
|
||||
'returns' => ['type' => 'table', 'description' => 'QBCore player object or nil'],
|
||||
'lua_example' => "local Player = QBCore.Functions.GetPlayerByPhone('555-0001')\nif Player then\n print('Found player: ' .. Player.Functions.GetName())\nend",
|
||||
'js_example' => "const Player = QBCore.Functions.GetPlayerByPhone('555-0001');\nif (Player) {\n console.log(`Found player: \${Player.Functions.GetName()}`);\n}",
|
||||
],
|
||||
'GetPlayers' => [
|
||||
'namespace' => 'Core',
|
||||
'description' => 'Get table of all online player net IDs (server-side only)',
|
||||
'side' => 'server',
|
||||
'parameters' => [],
|
||||
'returns' => ['type' => 'table', 'description' => 'Array of all connected player net IDs'],
|
||||
'lua_example' => "local players = QBCore.Functions.GetPlayers()\nfor i = 1, #players do\n local Player = QBCore.Functions.GetPlayer(players[i])\n if Player then\n print('Player: ' .. Player.Functions.GetName())\n end\nend",
|
||||
'js_example' => "const players = QBCore.Functions.GetPlayers();\nfor (const playerId of players) {\n const Player = QBCore.Functions.GetPlayer(playerId);\n if (Player) {\n console.log(`Player: \${Player.Functions.GetName()}`);\n }\n}",
|
||||
],
|
||||
];
|
||||
|
||||
$nameLower = strtolower($name);
|
||||
@@ -212,7 +399,7 @@ class GetQBCoreServerFunction extends Tool
|
||||
return [
|
||||
'function_name' => $schema
|
||||
->string()
|
||||
->description('The name of the QBCore server function to look up (e.g., "QBCore.Functions.GetPlayer", "AddMoney", "SetJob")')
|
||||
->description('The name of the QBCore server function to look up (e.g., "QBCore.Functions.GetPlayer", "AddMoney", "SetJob", "SetGang", "Notify", "HasItem", "SetMetaData", "GetRep")')
|
||||
->required(),
|
||||
'language' => $schema
|
||||
->string()
|
||||
|
||||
@@ -171,11 +171,18 @@
|
||||
<h2 class="text-3xl font-extrabold text-gray-900 mb-8">Resources</h2>
|
||||
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2">
|
||||
<div class="bg-white shadow rounded-lg p-6">
|
||||
<h3 class="text-lg font-medium text-gray-900 mb-4">Testing</h3>
|
||||
<h3 class="text-lg font-medium text-gray-900 mb-4">MCP Server Configuration</h3>
|
||||
<p class="text-sm text-gray-500 mb-4">
|
||||
Test the MCP server locally using the inspector:
|
||||
To connect to the FiveM MCP server, use the following configuration in your MCP client:
|
||||
</p>
|
||||
<pre class="bg-gray-50 rounded p-4 text-sm overflow-x-auto"><code>php artisan mcp:inspector fivem</code></pre>
|
||||
<pre class="bg-gray-50 rounded p-4 text-sm overflow-x-auto"><code>{
|
||||
"servers": {
|
||||
"fivem": {
|
||||
"url": "{{ route('fivem') }}",
|
||||
"type": "http"
|
||||
}
|
||||
}
|
||||
}</code></pre>
|
||||
</div>
|
||||
<div class="bg-white shadow rounded-lg p-6">
|
||||
<h3 class="text-lg font-medium text-gray-900 mb-4">External Links</h3>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
## {{ $config['category'] }} Configuration
|
||||
|
||||
**Location:** `{{ $config['location'] }}`
|
||||
|
||||
{{ $config['description'] }}
|
||||
|
||||
### Configuration Options
|
||||
| Option | Type | Description |
|
||||
|--------|------|-------------|
|
||||
@foreach($config['config_options'] as $option)
|
||||
| `{{ $option['name'] }}` | {{ $option['type'] }} | {{ $option['description'] }} |
|
||||
@endforeach
|
||||
|
||||
@if($language === 'lua')
|
||||
### Lua Example
|
||||
```lua
|
||||
{{ $config['lua_example'] }}
|
||||
```
|
||||
@else
|
||||
### JavaScript Example
|
||||
```javascript
|
||||
{{ $config['js_example'] }}
|
||||
```
|
||||
@endif
|
||||
|
||||
### Learn More
|
||||
- [QBCore Configuration Guide](https://docs.qbcore.org/qbcore-documentation/qb-core/configuration)
|
||||
- [QBCore Repository](https://github.com/qbcore-framework/qb-core)
|
||||
@@ -0,0 +1,46 @@
|
||||
## {{ $info['title'] }}
|
||||
|
||||
{{ $info['description'] }}
|
||||
|
||||
@if(isset($info['properties']))
|
||||
### Properties
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
@foreach($info['properties'] as $prop)
|
||||
| `{{ $prop['name'] }}` | {{ $prop['type'] }} | {{ $prop['description'] }} |
|
||||
@endforeach
|
||||
@endif
|
||||
|
||||
@if(isset($info['methods']))
|
||||
### Available Methods
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
@foreach($info['methods'] as $method)
|
||||
| `{{ $method['name'] }}` | {{ $method['description'] }} |
|
||||
@endforeach
|
||||
@endif
|
||||
|
||||
@if(isset($info['events']))
|
||||
### Events
|
||||
| Event | Description |
|
||||
|-------|-------------|
|
||||
@foreach($info['events'] as $event)
|
||||
| `{{ $event['name'] }}` | {{ $event['description'] }} |
|
||||
@endforeach
|
||||
@endif
|
||||
|
||||
@if($language === 'lua')
|
||||
### Lua Example
|
||||
```lua
|
||||
{{ $info['lua_example'] }}
|
||||
```
|
||||
@else
|
||||
### JavaScript Example
|
||||
```javascript
|
||||
{{ $info['js_example'] }}
|
||||
```
|
||||
@endif
|
||||
|
||||
### Learn More
|
||||
- [QBCore Player Data Documentation](https://docs.qbcore.org/qbcore-documentation/qb-core/player-data)
|
||||
- [QBCore Repository](https://github.com/qbcore-framework/qb-core)
|
||||
@@ -0,0 +1,35 @@
|
||||
## {{ $data['type'] }} - QBCore Shared Data
|
||||
|
||||
**Location:** `{{ $data['location'] }}`
|
||||
|
||||
{{ $data['description'] }}
|
||||
|
||||
### Properties
|
||||
@if(isset($data['properties']))
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
@foreach($data['properties'] as $prop)
|
||||
| `{{ $prop['name'] }}` | {{ $prop['type'] }} | {{ $prop['description'] }} |
|
||||
@endforeach
|
||||
@endif
|
||||
|
||||
@if(isset($data['methods']))
|
||||
### Available Methods
|
||||
@foreach($data['methods'] as $method)
|
||||
- **{{ $method['name'] }}** - {{ $method['description'] }}
|
||||
@endforeach
|
||||
@endif
|
||||
|
||||
### Lua Example
|
||||
```lua
|
||||
{{ $data['lua_example'] }}
|
||||
```
|
||||
|
||||
### JavaScript Example
|
||||
```javascript
|
||||
{{ $data['js_example'] }}
|
||||
```
|
||||
|
||||
### Learn More
|
||||
- [QBCore Shared Documentation](https://docs.qbcore.org/qbcore-documentation/qb-core/shared)
|
||||
- [QBCore Repository](https://github.com/qbcore-framework/qb-core)
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
use App\Mcp\Tools\QBCore\GetQBCoreConfig;
|
||||
use Laravel\Mcp\Request;
|
||||
|
||||
test('GetQBCoreConfig returns Player config', function () {
|
||||
$tool = new GetQBCoreConfig;
|
||||
$request = new Request(['config_type' => 'Player', 'language' => 'lua']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect((string) $response->content())->toContain('Player');
|
||||
expect((string) $response->content())->toContain('PlayerDefaults');
|
||||
});
|
||||
|
||||
test('GetQBCoreConfig returns Framework config', function () {
|
||||
$tool = new GetQBCoreConfig;
|
||||
$request = new Request(['config_type' => 'Framework', 'language' => 'lua']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect((string) $response->content())->toContain('Framework');
|
||||
expect((string) $response->content())->toContain('Version');
|
||||
});
|
||||
|
||||
test('GetQBCoreConfig returns Database config', function () {
|
||||
$tool = new GetQBCoreConfig;
|
||||
$request = new Request(['config_type' => 'Database', 'language' => 'lua']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect((string) $response->content())->toContain('Database');
|
||||
expect((string) $response->content())->toContain('Backend');
|
||||
});
|
||||
|
||||
test('GetQBCoreConfig returns Callbacks config', function () {
|
||||
$tool = new GetQBCoreConfig;
|
||||
$request = new Request(['config_type' => 'Callbacks', 'language' => 'js']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect((string) $response->content())->toContain('Callbacks');
|
||||
expect((string) $response->content())->toContain('JavaScript Example');
|
||||
});
|
||||
|
||||
test('GetQBCoreConfig returns Features config', function () {
|
||||
$tool = new GetQBCoreConfig;
|
||||
$request = new Request(['config_type' => 'Features', 'language' => 'lua']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect((string) $response->content())->toContain('Features');
|
||||
});
|
||||
|
||||
test('GetQBCoreConfig returns RepTypes config', function () {
|
||||
$tool = new GetQBCoreConfig;
|
||||
$request = new Request(['config_type' => 'RepTypes', 'language' => 'lua']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect((string) $response->content())->toContain('RepTypes');
|
||||
expect((string) $response->content())->toContain('selling');
|
||||
});
|
||||
|
||||
test('GetQBCoreConfig returns not found for invalid type', function () {
|
||||
$tool = new GetQBCoreConfig;
|
||||
$request = new Request(['config_type' => 'InvalidType', 'language' => 'lua']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect((string) $response->content())->toContain('not found');
|
||||
});
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
use App\Mcp\Tools\QBCore\GetQBCorePlayers;
|
||||
use Laravel\Mcp\Request;
|
||||
|
||||
test('GetQBCorePlayers returns Structure info', function () {
|
||||
$tool = new GetQBCorePlayers;
|
||||
$request = new Request(['info_type' => 'Structure', 'language' => 'lua']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect((string) $response->content())->toContain('Structure');
|
||||
expect((string) $response->content())->toContain('PlayerData');
|
||||
expect((string) $response->content())->toContain('Functions');
|
||||
});
|
||||
|
||||
test('GetQBCorePlayers returns PlayerData info', function () {
|
||||
$tool = new GetQBCorePlayers;
|
||||
$request = new Request(['info_type' => 'PlayerData', 'language' => 'lua']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect((string) $response->content())->toContain('PlayerData');
|
||||
expect((string) $response->content())->toContain('citizenid');
|
||||
expect((string) $response->content())->toContain('charinfo');
|
||||
});
|
||||
|
||||
test('GetQBCorePlayers returns Methods info', function () {
|
||||
$tool = new GetQBCorePlayers;
|
||||
$request = new Request(['info_type' => 'Methods', 'language' => 'lua']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect((string) $response->content())->toContain('Methods');
|
||||
expect((string) $response->content())->toContain('AddItem');
|
||||
expect((string) $response->content())->toContain('SetJob');
|
||||
});
|
||||
|
||||
test('GetQBCorePlayers returns Events info', function () {
|
||||
$tool = new GetQBCorePlayers;
|
||||
$request = new Request(['info_type' => 'Events', 'language' => 'js']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect((string) $response->content())->toContain('Events');
|
||||
expect((string) $response->content())->toContain('JavaScript Example');
|
||||
});
|
||||
|
||||
test('GetQBCorePlayers returns Examples info', function () {
|
||||
$tool = new GetQBCorePlayers;
|
||||
$request = new Request(['info_type' => 'Examples', 'language' => 'lua']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect((string) $response->content())->toContain('Examples');
|
||||
expect((string) $response->content())->toContain('HasItem');
|
||||
});
|
||||
|
||||
test('GetQBCorePlayers returns not found for invalid type', function () {
|
||||
$tool = new GetQBCorePlayers;
|
||||
$request = new Request(['info_type' => 'InvalidType', 'language' => 'lua']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect((string) $response->content())->toContain('not found');
|
||||
});
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
use App\Mcp\Tools\QBCore\GetQBCoreSharedData;
|
||||
use Laravel\Mcp\Request;
|
||||
|
||||
test('GetQBCoreSharedData returns Items data', function () {
|
||||
$tool = new GetQBCoreSharedData;
|
||||
$request = new Request(['data_type' => 'Items', 'language' => 'lua']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect((string) $response->content())->toContain('Items');
|
||||
expect((string) $response->content())->toContain('label');
|
||||
expect((string) $response->content())->toContain('weight');
|
||||
});
|
||||
|
||||
test('GetQBCoreSharedData returns Jobs data', function () {
|
||||
$tool = new GetQBCoreSharedData;
|
||||
$request = new Request(['data_type' => 'Jobs', 'language' => 'lua']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect((string) $response->content())->toContain('Jobs');
|
||||
expect((string) $response->content())->toContain('grades');
|
||||
expect((string) $response->content())->toContain('Lua Example');
|
||||
});
|
||||
|
||||
test('GetQBCoreSharedData returns Gangs data', function () {
|
||||
$tool = new GetQBCoreSharedData;
|
||||
$request = new Request(['data_type' => 'Gangs', 'language' => 'lua']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect((string) $response->content())->toContain('Gangs');
|
||||
});
|
||||
|
||||
test('GetQBCoreSharedData returns Vehicles data', function () {
|
||||
$tool = new GetQBCoreSharedData;
|
||||
$request = new Request(['data_type' => 'Vehicles', 'language' => 'lua']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect((string) $response->content())->toContain('Vehicles');
|
||||
expect((string) $response->content())->toContain('model');
|
||||
expect((string) $response->content())->toContain('price');
|
||||
});
|
||||
|
||||
test('GetQBCoreSharedData returns Weapons data', function () {
|
||||
$tool = new GetQBCoreSharedData;
|
||||
$request = new Request(['data_type' => 'Weapons', 'language' => 'js']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect((string) $response->content())->toContain('Weapons');
|
||||
expect((string) $response->content())->toContain('JavaScript Example');
|
||||
});
|
||||
|
||||
test('GetQBCoreSharedData returns StarterItems data', function () {
|
||||
$tool = new GetQBCoreSharedData;
|
||||
$request = new Request(['data_type' => 'StarterItems', 'language' => 'lua']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect((string) $response->content())->toContain('StarterItems');
|
||||
});
|
||||
|
||||
test('GetQBCoreSharedData returns Utilities data', function () {
|
||||
$tool = new GetQBCoreSharedData;
|
||||
$request = new Request(['data_type' => 'Utilities', 'language' => 'lua']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect((string) $response->content())->toContain('Utilities');
|
||||
expect((string) $response->content())->toContain('RandomStr');
|
||||
expect((string) $response->content())->toContain('Trim');
|
||||
});
|
||||
|
||||
test('GetQBCoreSharedData returns not found for invalid type', function () {
|
||||
$tool = new GetQBCoreSharedData;
|
||||
$request = new Request(['data_type' => 'InvalidType', 'language' => 'lua']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect((string) $response->content())->toContain('not found');
|
||||
});
|
||||
Reference in new issue
Block a user