Poradniki

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.lua
  • client.lua
  • server.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_scripts i server_scripts mó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

ensure uruchomi resource, a jeśli padnie – spróbuje włączyć ponownie.
Jeśli masz zależności, ważna jest kolejność wpisów w server.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

  1. Odpal serwer (txAdmin lub ręcznie).
  2. Uruchom FiveM i połącz się na swój serwer.
  3. 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).
  • Komendy nie działają
    • Upewnij się, że resource jest włączony (ensure cf_hello_world).
    • Dla /helloall: czy dodałeś ACE (uprawnienia) do server.cfg?
  • Brak wiadomości na czacie
    • Upewnij się, że masz uruchomiony resource chat.
  • „Zawieszenia” i spadki FPS
    • Unikaj pętli while true do z Wait(0) bez potrzeby.
    • Jeśli musisz, dawaj rozsądne odczekania (Wait(250), Wait(500)), a logikę wykonuj warunkowo.
  • 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") w server.lua,
    • print("client startuje") w client.lua,
    • a po stronie klienta podglądaj F8.
  • Restart zamiast całego serwerarestart cf_hello_world skraca 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ęc Wait(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.lua i wskazuje na client.lua i server.lua.
  • W server.cfg jest ensure cf_hello_world.
  • Resource chat jest aktywny (do testów z wiadomościami).
  • Konsola serwera nie wyrzuca błędów przy starcie.
  • Po wejściu na serwer: /hello dział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.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *