Jak stworzyć swój pierwszy prosty dodatek do FiveM? (Poradnik dla początkujących)
1) O co w ogóle chodzi? — 3 pojęcia na start
- Resource (dodatek / mod) – folder z plikami Twojego skryptu. Każdy resource to „klocek” uruchamiany przez serwer FiveM.
fxmanifest.lua– metaplik (manifest) w każdym resource. Mówi serwerowi, co załadować (klient/serwer), jak nazywa się resource, itp.- Klient vs Serwer
- client.lua – kod uruchamiany u gracza (HUD, UI, rysowanie, reakcja na klawisze, lokalne komendy).
- server.lua – logika globalna (komunikaty do wszystkich, sprawy „wspólne”, zapisy w bazie – gdy później do tego dojdziesz).
2) Niezbędne narzędzia
- Działający serwer FiveM (najwygodniej przez txAdmin – instalator prowadzi za rękę).
- Edytor tekstu: Visual Studio Code (polecany) lub nawet Notatnik.
- Dostęp do plików serwera: lokalnie lub przez FTP/SFTP (jeśli to zdalny host).
- (Opcjonalnie) Git – żeby cofać zmiany i nie bać się eksperymentów.
Uwaga: przyda się domyślny resource
chat(zazwyczaj jest już w paczce). Nasz przykład go wykorzysta.
3) Gdzie wstawić pliki?
Najczęściej jedna z dwóch lokalizacji (w zależności od instalacji):
- Klasyczny układ:
server-data/resources/ - txAdmin (Windows/Linux):
txData/<nazwa_profilu>/resources/
W obrębie resources/ warto porządkować rzeczy w grupach, np.:
[local]– Twoje własne skrypty,[standalone],[esx],[qb]– zależnie od frameworka.
Utwórz folder: resources/[local]/cf_hello_world
W środku powstaną 3 pliki:
fxmanifest.luaclient.luaserver.lua
4) Twój pierwszy resource – minimalny przykład
fxmanifest.lua
fx_version 'cerulean'
game 'gta5'
author 'TwojaNazwa'
description 'Najprostszy możliwy dodatek hello world do FiveM'
version '1.0.0'
client_scripts {
'client.lua'
}
server_scripts {
'server.lua'
}
Co tu się dzieje?
fx_version/game– standardowe nagłówki.client_scriptsiserver_scriptsmówią, które pliki ładować po stronie klienta/serwera.
client.lua
-- Prosta komenda po stronie klienta: /hello
RegisterCommand('hello', function()
TriggerEvent('chat:addMessage', {
color = {255, 255, 255},
multiline = true,
args = {'CF', 'Cześć! To jest mój pierwszy dodatek do FiveM 🚀'}
})
end, false)
-- Autopowiadomienie po dołączeniu gracza
AddEventHandler('onClientMapStart', function()
TriggerEvent('chat:addMessage', {
color = {0, 200, 100},
args = {'CF', 'Dodatek cf_hello_world załadowany. Użyj /hello'}
})
end)
Wyjaśnienie:
RegisterCommand('hello', ...)– definiuje komendę wpisywaną na czacie.chat:addMessage– wysyła tekst do domyślnego chatu.
server.lua
-- Prosta komenda po stronie serwera: /helloall
RegisterCommand('helloall', function(source, args, raw)
-- source == id gracza; source==0 oznacza konsolę serwera
TriggerClientEvent('chat:addMessage', -1, {
color = {255, 200, 0},
args = {'CF', 'Witajcie wszyscy! (komenda serwerowa /helloall)'}
})
end, true) -- true => komenda „restricted” (do odblokowania w ACE)
Uwaga – uprawnienia (ACE):
Ponieważ daliśmy restricted = true, tylko uprawnione osoby użyją /helloall.
W server.cfg możesz dodać np.:
add_ace group.admin command.helloall allow
add_principal identifier.steam:YOURSTEAMHEX group.admin
Zamień YOURSTEAMHEX na swój identyfikator. Dzięki temu Ty, jako admin, możesz używać /helloall.
5) Włączenie resource’u
Otwórz server.cfg i dodaj linijkę:
ensure cf_hello_world
ensureuruchomi resource, a jeśli padnie – spróbuje włączyć ponownie.
Jeśli masz zależności, ważna jest kolejność wpisów wserver.cfg.
Szybkie komendy w konsoli serwera:
refresh– odświeża listę resource’ów,start cf_hello_world– startuje resource,restart cf_hello_world– restartuje resource,stop cf_hello_world– zatrzymuje resource,status– podaje statusy uruchomionych skryptów.
6) Testowanie w grze — krok po kroku
- Odpal serwer (txAdmin lub ręcznie).
- Uruchom FiveM i połącz się na swój serwer.
- Na czacie wpisz:
/hello– powinna pojawić się wiadomość od klienta./helloall– (jeśli masz uprawnienia) wszyscy gracze zobaczą komunikat.
Gdzie patrzeć, gdy coś nie działa?
- Konsola serwera – błędy
server.lua, manifesty, brak resource’ów. - Konsola klienta (F8) – błędy w
client.lua(np. literówki, nieistniejące eventy). status/ensure– czy resource jest w ogóle załadowany?
7) Najczęstsze błędy i jak je ogarnąć
- Resource „nie istnieje” po
refresh- Sprawdź dokładną ścieżkę folderu (czy na pewno w
resources/...). - Manifest musi nazywać się
fxmanifest.lua(nie.txt).
- Sprawdź dokładną ścieżkę folderu (czy na pewno w
- Komendy nie działają
- Upewnij się, że resource jest włączony (
ensure cf_hello_world). - Dla
/helloall: czy dodałeś ACE (uprawnienia) doserver.cfg?
- Upewnij się, że resource jest włączony (
- Brak wiadomości na czacie
- Upewnij się, że masz uruchomiony resource
chat.
- Upewnij się, że masz uruchomiony resource
- „Zawieszenia” i spadki FPS
- Unikaj pętli
while true dozWait(0)bez potrzeby. - Jeśli musisz, dawaj rozsądne odczekania (
Wait(250),Wait(500)), a logikę wykonuj warunkowo.
- Unikaj pętli
- Kompilacja / kodowanie znaków
- Pliki zapisuj jako UTF-8 (bez BOM). VS Code ma to w prawym dolnym rogu.
- Nazewnictwo
- Nie używaj spacji i polskich znaków w nazwach plików/folderów.
8) Dobre praktyki od pierwszego dnia
- Jeden resource = jedna funkcja (łatwiej debugować).
- Komentuj kod – jutro zapomnisz, czemu ta linia tam jest.
- Loguj mądrze:
print("tu byłem")wserver.lua,print("client startuje")wclient.lua,- a po stronie klienta podglądaj F8.
- Restart zamiast całego serwera –
restart cf_hello_worldskraca czas testów. - Kolejność w
server.cfg– najpierw zależności, potem rzeczy które ich potrzebują. - Git – nawet lokalnie:
git init, commit po każdym kroku. Cofniesz się bez stresu.
9) Debugowanie — szybkie sztuczki
- Czy event w ogóle wywołuje kod? Dorzuć
print(...)w handlerze. - Czy komenda jest zarejestrowana? Wpisz ją z błędem – zobaczysz, czy konsola reaguje.
- Izoluj problem – wytnij 90% kodu, zostaw 10% i sprawdź, czy to działa. Potem dokładamy elementy po jednym.
- Sprawdź konsolę F8 – błędy z klienta zobaczysz tylko tam.
- Zawsze jeden błąd na raz – napraw pierwszy błąd, potem odśwież. Lawina błędów często wynika z jednego drobiazgu.
10) Co dalej? — dwie banalne rozbudowy (kopiuj-wklej)
(A) Blip (ikonka) na mapie
Wstaw na koniec client.lua:
CreateThread(function()
local blip = AddBlipForCoord(-268.0, -957.0, 31.2) -- przykładowe koordy
SetBlipSprite(blip, 280) -- ikonka (np. sklep, szpital itd.)
SetBlipDisplay(blip, 4)
SetBlipScale(blip, 0.8)
SetBlipColour(blip, 2)
SetBlipAsShortRange(blip, true)
BeginTextCommandSetBlipName("STRING")
AddTextComponentString("Mój Pierwszy Blip")
EndTextCommandSetBlipName(blip)
end)
(B) „3D text” gdy jesteś blisko punktu
Dopisujemy do client.lua:
local point = vector3(-268.0, -957.0, 31.2)
local drawDist = 5.0
local function Draw3DText(x, y, z, text)
SetDrawOrigin(x, y, z, 0)
SetTextScale(0.35, 0.35)
SetTextFont(4)
SetTextProportional(1)
SetTextColour(255, 255, 255, 215)
SetTextCentre(true)
BeginTextCommandDisplayText("STRING")
AddTextComponentSubstringPlayerName(text)
EndTextCommandDisplayText(0.0, 0.0)
ClearDrawOrigin()
end
CreateThread(function()
while true do
Wait(0)
local ped = PlayerPedId()
local p = GetEntityCoords(ped)
local dist = #(p - point)
if dist < drawDist then
Draw3DText(point.x, point.y, point.z + 1.0, "~w~Witaj! To Twój ~o~pierwszy~w~ punkt.")
end
end
end)
Tę logikę można łatwo rozbudować (np. naciśnij „E”, żeby wyświetlić menu).
Uwaga na pętle – to mały, lekki rysunek, więcWait(0)jest ok, ale nie rób dziesiątek takich pętli.
11) „Checklist” – zanim powiesz „działa!”
- Folder resource jest w
resources/...(np.[local]/cf_hello_world). - Jest
fxmanifest.luai wskazuje naclient.luaiserver.lua. - W
server.cfgjestensure cf_hello_world. - Resource
chatjest aktywny (do testów z wiadomościami). - Konsola serwera nie wyrzuca błędów przy starcie.
- Po wejściu na serwer:
/hellodziała;/helloall(z ACE) działa.
Podsumowanie
Masz postawiony pierwszy, poprawny resource: wiesz, gdzie leżą pliki, co robi manifest, jak zarejestrować komendy i jak je przetestować. Znasz najczęstsze pułapki i wiesz, gdzie patrzeć, gdy coś pójdzie nie tak. Od tego miejsca płynnie wejdziesz w kolejne tematy (markery, NUI, frameworki ESX/QBCore, zapisy do bazy).
Jeśli chcesz, mogę w tej samej konwencji przygotować wersję do pobrania (DOCX albo PDF) z tym poradnikiem i gotowymi blokami kodu – daj znać, który format wolisz.
