Charakterauswahl: Vorschau-Crash, Blackscreen und Debug beheben
- Vorschau (3D-Ped/Kamera) in einen eigenen, verzoegerten Thread mit Laufnummer-Schutz ausgelagert. Damit laeuft die vernetzte Ped-Erzeugung nicht mehr zeitgleich mit dem Spieler-Teleport der Auswahl -> behebt "SendNetPacket called from multiple threads" (Crash beim Oeffnen). - Blackscreen nach dem Spawn behoben: der Fade wird nun allein vom Core gesteuert (Fade-out zu Beginn von spielerGeladen, Fade-in am Ende); SchliesseAuswahl blendet nicht mehr selbst -> kein Fade-Konflikt mehr. - Temporaere [AETHER-DEBUG]-Ausgaben wieder entfernt. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
cad096e7a6
commit
11cc043b6c
@ -18,8 +18,6 @@ local PARKPLATZ = { x = -1037.7, y = -2737.6, z = 20.2 }
|
||||
--- @param charaktere table Liste der Charaktere
|
||||
--- @param maxSlots number Maximale Anzahl Charaktere
|
||||
local function OeffneAuswahl(charaktere, maxSlots)
|
||||
print(('[AETHER-DEBUG] client OeffneAuswahl: %d Charaktere')
|
||||
:format(charaktere and #charaktere or -1))
|
||||
auswahlOffen = true
|
||||
|
||||
-- Eigenen Spieler unsichtbar parken — sichtbar ist nur der Vorschau-Ped
|
||||
@ -31,7 +29,6 @@ local function OeffneAuswahl(charaktere, maxSlots)
|
||||
-- 3D-Vorschau mit dem Aussehen des ersten Charakters starten
|
||||
local erstes = charaktere and charaktere[1] or nil
|
||||
Vorschau.Starten(erstes and erstes.aussehen or nil, 'koerper')
|
||||
print('[AETHER-DEBUG] client OeffneAuswahl: Vorschau gestartet, beende Ladebildschirm')
|
||||
|
||||
-- Ladebildschirm beenden, damit die Auswahl sichtbar wird
|
||||
ShutdownLoadingScreen()
|
||||
@ -53,10 +50,9 @@ local function SchliesseAuswahl()
|
||||
|
||||
SendNuiMessage(json.encode({ aktion = 'schliessen' }))
|
||||
SetNuiFocus(false, false)
|
||||
|
||||
DoScreenFadeOut(400)
|
||||
Wait(400)
|
||||
Vorschau.Beenden()
|
||||
-- Bewusst KEIN Fade hier: der Core blendet nach dem Spawn ein. Ein Fade
|
||||
-- an dieser Stelle kollidiert mit dem Core-Fade -> Blackscreen.
|
||||
end
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
|
||||
@ -22,6 +22,9 @@ local vorschauKamera= nil -- Handle der Kamera
|
||||
local aktuellesModell = nil -- Aktuell geladenes Ped-Modell (fuer Geschlechtswechsel)
|
||||
local aktuelleDrehung = 0.0 -- Zusaetzliche Drehung durch den Spieler
|
||||
local aktuellerModus = 'koerper'
|
||||
-- Laufnummer: entwertet noch laufende, verzoegerte Starts, wenn zwischendurch
|
||||
-- beendet oder neu gestartet wird.
|
||||
local aktuellerLauf = 0
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- Interne Helfer
|
||||
@ -79,6 +82,17 @@ end
|
||||
--- @param aussehen table|nil Startaussehen (bestimmt auch das Geschlecht)
|
||||
--- @param modus string|nil Startansicht ('gesicht' | 'koerper')
|
||||
function Vorschau.Starten(aussehen, modus)
|
||||
aktuellerLauf = aktuellerLauf + 1
|
||||
local lauf = aktuellerLauf
|
||||
|
||||
-- WICHTIG: Ped und Kamera in einem EIGENEN Thread mit kurzer Verzoegerung
|
||||
-- erzeugen. Sonst laeuft die (vernetzte) Ped-Erzeugung im selben Moment wie
|
||||
-- der Spieler-Ped-Teleport der Auswahl -> zwei Threads schreiben Netz-State
|
||||
-- ("SendNetPacket ... called from multiple threads") -> Client-Crash.
|
||||
CreateThread(function()
|
||||
Wait(250)
|
||||
if lauf ~= aktuellerLauf then return end -- inzwischen beendet/neu gestartet
|
||||
|
||||
-- Umgebung laden, damit der Ped nicht durch den Boden faellt
|
||||
RequestCollisionAtCoord(VORSCHAU_POS.x, VORSCHAU_POS.y, VORSCHAU_POS.z)
|
||||
|
||||
@ -88,6 +102,7 @@ function Vorschau.Starten(aussehen, modus)
|
||||
print('^1[Aether]^7 Vorschau-Modell konnte nicht geladen werden: ' .. modellName)
|
||||
return
|
||||
end
|
||||
if lauf ~= aktuellerLauf then SetModelAsNoLongerNeeded(modell); return end
|
||||
|
||||
-- Ped nur lokal erzeugen (nicht im Netzwerk sichtbar)
|
||||
vorschauPed = CreatePed(4, modell, VORSCHAU_POS.x, VORSCHAU_POS.y, VORSCHAU_POS.z,
|
||||
@ -110,6 +125,10 @@ function Vorschau.Starten(aussehen, modus)
|
||||
SetzeKameraAuf(modus or 'koerper', false)
|
||||
SetCamActive(vorschauKamera, true)
|
||||
RenderScriptCams(true, false, 0, true, true)
|
||||
|
||||
-- Falls waehrenddessen beendet wurde: sofort wieder aufraeumen
|
||||
if lauf ~= aktuellerLauf then Vorschau.Beenden() end
|
||||
end)
|
||||
end
|
||||
|
||||
--- Uebertraegt ein Aussehen auf den Vorschau-Ped.
|
||||
@ -167,6 +186,9 @@ end
|
||||
|
||||
--- Beendet die Vorschau und raeumt Ped und Kamera auf
|
||||
function Vorschau.Beenden()
|
||||
-- Noch laufende, verzoegerte Starts entwerten
|
||||
aktuellerLauf = aktuellerLauf + 1
|
||||
|
||||
if vorschauKamera then
|
||||
RenderScriptCams(false, false, 0, true, true)
|
||||
DestroyCam(vorschauKamera, false)
|
||||
|
||||
@ -111,13 +111,10 @@ end
|
||||
-- Auswahl anzeigen (wird vom Core ausgeloest)
|
||||
-- ---------------------------------------------------------------------
|
||||
AddEventHandler('aether:server:charakterAuswahlNoetig', function(quelle)
|
||||
print(('[AETHER-DEBUG] character-server: charakterAuswahlNoetig empfangen fuer %s')
|
||||
:format(tostring(quelle)))
|
||||
local lizenz = HoleLizenz(quelle)
|
||||
if not lizenz then print('[AETHER-DEBUG] character-server: keine Lizenz!'); return end
|
||||
if not lizenz then return end
|
||||
TriggerClientEvent('aether:character:zeigeAuswahl', quelle,
|
||||
BaueListe(lizenz), Config.MaxCharaktere)
|
||||
print('[AETHER-DEBUG] character-server: zeigeAuswahl an Client gesendet')
|
||||
end)
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
|
||||
@ -52,6 +52,11 @@ end)
|
||||
RegisterNetEvent('aether:client:spielerGeladen', function(daten)
|
||||
Aether.SpielerDaten = daten
|
||||
|
||||
-- Waehrend des Spawns schwarz halten (versteckt Modellwechsel und den
|
||||
-- Schnitt von der Auswahl-Kamera). Der Fade wird am Ende wieder geoeffnet
|
||||
-- — der Core steuert den Fade allein, damit es keinen Konflikt gibt.
|
||||
DoScreenFadeOut(0)
|
||||
|
||||
-- Passendes Standardmodell laden (bis der Charakter-Ersteller migriert ist)
|
||||
local modellName = Config.StandardPed[daten.geschlecht] or Config.StandardPed.m
|
||||
local modell = GetHashKey(modellName)
|
||||
|
||||
@ -87,8 +87,6 @@ end
|
||||
RegisterNetEvent('aether:server:spielerBereit', function()
|
||||
local quelle = source
|
||||
local lizenz = HoleLizenz(quelle)
|
||||
print(('[AETHER-DEBUG] spielerBereit: quelle=%s lizenz=%s AutoCharakter=%s')
|
||||
:format(tostring(quelle), lizenz and 'ok' or 'nil', tostring(Config.AutoCharakter)))
|
||||
if not lizenz then return end
|
||||
|
||||
-- Bereits geladen? Dann nichts tun (schuetzt vor doppeltem Laden)
|
||||
@ -96,7 +94,6 @@ RegisterNetEvent('aether:server:spielerBereit', function()
|
||||
|
||||
-- Standardweg: `aether-character` zeigt die Charakterauswahl
|
||||
if not Config.AutoCharakter then
|
||||
print('[AETHER-DEBUG] spielerBereit: triggere charakterAuswahlNoetig')
|
||||
TriggerEvent('aether:server:charakterAuswahlNoetig', quelle)
|
||||
return
|
||||
end
|
||||
|
||||
Loading…
Reference in New Issue
Block a user