Gutschein verwenden WELCOME um 20% zu sparen

$ USD
  • $ USD
  • € EUR
  • £ GBP
  • $ AUD
  • R$ BRL
  • CHF CHF
  • ¥ JPY
Baue eine benutzerdefinierte FiveM-Handy-App

Eine kleine FiveM-Telefon-App mit NUI entwickeln

Entwickle zunächst eine kleine telefonähnliche NUI-App, um den vollständigen Ablauf aus Öffnen, Nachrichten, Callbacks und Schließen zu lernen. Dieses Beispiel zeigt eine Sitzungsnotiz, die während der Ressourcenlaufzeit erhalten bleibt. Es enthält weder Anrufe noch Nachrichtendienst, Datenbank oder Framework-Abhängigkeit; dafür brauchst du zusätzliche serverseitige Berechtigungsprüfungen und dauerhafte Speicherung.

Drei Dateien erstellen

Erstelle resources/[local]/tutorial_phone/ mit fxmanifest.lua, client.lua und index.html. Das Beispiel richtet sich an die GTA-V-Legacy- gta5 Ressourcenlaufzeit. Prüfe die Enhanced-Migrationshinweise von Cfx.re, bevor du es für eine Enhanced-Installation anpasst.

fxmanifest.lua:

fx_version 'cerulean'
game 'gta5'
ui_page 'index.html'
files { 'index.html' }
client_script 'client.lua'

client.lua:

local visible = false
local ready = false

local function closePhone()
    visible = false
    SetNuiFocus(false, false)
    SendNUIMessage({ action = 'close' })
end

RegisterCommand('tutorial_phone', function()
    if not ready then
        print('Phone UI is loading; try again shortly.')
        return
    end
    if visible then closePhone(); return end
    visible = true
    SetNuiFocus(true, true)
    SendNUIMessage({ action = 'open' })
end, false)

RegisterNUICallback('ready', function(_, cb)
    ready = true
    cb({ ok = true })
end)

RegisterNUICallback('close', function(_, cb)
    closePhone()
    cb({ ok = true })
end)

AddEventHandler('onClientResourceStop', function(name)
    if name == GetCurrentResourceName() and visible then
        SetNuiFocus(false, false)
    end
end)

index.html:

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Session note</title>
<style>
body { margin: 0; background: transparent; font: 18px system-ui; }
#phone { position: fixed; right: 4vw; bottom: 4vh; width: min(320px, 85vw);
  padding: 24px; box-sizing: border-box; color: #fff; background: #18222d;
  border-radius: 20px; }
[hidden] { display: none !important; }
textarea { box-sizing: border-box; width: 100%; min-height: 140px; font: inherit;
  margin: 12px 0; padding: 8px; }
button { font: inherit; padding: 10px 16px; cursor: pointer; }
:focus-visible { outline: 3px solid #67d7ff; outline-offset: 3px; }
</style>
</head>
<body>
<section id="phone" role="dialog" aria-label="Session note" hidden>
  <h1>Session note</h1>
  <label for="note">What will your character do next?</label>
  <textarea id="note" maxlength="500"></textarea>
  <p>This note clears when the resource restarts.</p>
  <button id="close" type="button">Close</button>
  <p id="error" role="status"></p>
</section>
<script>
const phone = document.getElementById('phone');
const note = document.getElementById('note');
const error = document.getElementById('error');
async function call(name) {
  const response = await fetch(`https://${GetParentResourceName()}/${name}`, {
    method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{}'
  });
  if (!response.ok) throw new Error('NUI callback failed');
  return response.json();
}
window.addEventListener('message', ({ data }) => {
  if (data?.action === 'open') {
    phone.hidden = false; error.textContent = ''; note.focus();
  } else if (data?.action === 'close') {
    phone.hidden = true;
  }
});
async function close() {
  try { await call('close'); }
  catch { error.textContent = 'Could not close. Check the F8 console.'; }
}
document.getElementById('close').addEventListener('click', close);
window.addEventListener('keydown', event => {
  if (event.key === 'Escape' && !phone.hidden) { event.preventDefault(); close(); }
});
call('ready').catch(() => console.error('Phone readiness callback failed.'));
</script>
</body>
</html>

Starten und überprüfen

Füge ensure tutorial_phone in die aktive Serverkonfiguration ein. Führe auf deinem Testserver refresh und ensure tutorial_phone aus, verbinde dich und führe danach tutorial_phone in F8 aus. Die App sollte sich öffnen und ihr Notizfeld fokussieren.

Gib eine Notiz ein, schließe die App über die Schaltfläche und öffne sie erneut. Die Notiz sollte für diese Ressourcensitzung erhalten bleiben. Teste Escape, wiederholtes Öffnen und Schließen sowie das Stoppen der geöffneten Ressource; die Spielsteuerung muss wieder freigegeben werden. Erneutes Verbinden oder ein Ressourcen-Neustart erzeugt eine neue UI-Sitzung und löscht die Notiz.

Die NUI-Schnittstelle untersuchen

Der Browser ruft den Ressourcen-Callback unter dem tatsächlichen Namen seiner übergeordneten Ressource auf. Lua antwortet immer über cb, und der Browser behandelt fehlgeschlagene Anfragen. Folge den NUI-Debugging-Anweisungen von Cfx.re , um Konsole und Callback-Anfragen auf deinem Client zu untersuchen.

Echte Telefonfunktionen gezielt ergänzen

Eine vorhandene Telefon-Ressource bietet möglicherweise ein eigenes App-SDK. Nutze diese unterstützte Integration, statt ein zweites vollständiges Telefon auszuführen. Dauerhaft gespeicherte Kontakte brauchen serverseitige Prüfungen des Charakterbesitzes, validierte Längen, parametrisierte Abfragen und eine Migration für das installierte Schema.

Echte Anrufe benötigen die unterstützte Integration der gewählten Sprachressource. Akzeptiere niemals eine beliebige Charakterkennung aus der UI als Zugriffsbeleg und behaupte nicht, ein Kontaktformular sei ein vollständiges, sicheres Telefonsystem.

Referenzdokumentation

Cfx.re — nui-Callbacks · Cfx.re — Ressourcenmanifest