aether-core: Netzwerk-Race beim Spawn beheben (Charakterauswahl-Crash)

Der Core schaltete Auto-Spawn ab, erzwang aber keinen kontrollierten
Spawn und fasste den Ped sofort an. Dadurch lief die unkontrollierte
Spawn-Erzeugung des spawnmanagers parallel zur Ped-Manipulation von
Core/Character -> zwei Threads schrieben gleichzeitig Netz-State:
"SendNetPacket called from multiple threads" -> Client-Crash beim
Charaktermenue (schwarzer Bildschirm, dann Absturz).

Fix: Auto-Spawn aus, EINMAL kontrolliert via spawnPlayer spawnen, auf
den Callback warten und den Ped erst danach unsichtbar/geparkt setzen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Jerrit Fritzsche 2026-07-27 19:55:06 +02:00
parent 32879ac07b
commit a5c517ff65

View File

@ -19,18 +19,48 @@ CreateThread(function()
Wait(100) Wait(100)
end end
-- Standard-Spawnverhalten von FiveM unterbinden. -- Bildschirm sofort schwarz halten, bevor irgendetwas spawnt
-- Abgesichert, falls spawnmanager nicht laeuft (dann uebernimmt der Core allein). DoScreenFadeOut(0)
local erfolg = pcall(function()
-- WICHTIG: den Spawn deterministisch selbst steuern.
-- Ohne einen kontrollierten Spawn liefert der spawnmanager den Ped
-- unkontrolliert (Auto-Spawn) — dann fasst der Core/Character-Flow den
-- Ped an, WÄHREND die Netzwerk-Erzeugung noch läuft. Zwei Threads
-- schreiben dann gleichzeitig Netz-State:
-- "SendNetPacket ... called from multiple threads" -> Client-Crash.
-- Lösung: Auto-Spawn AUS, EINMAL kontrolliert spawnen, und den Ped erst
-- NACH dem Spawn-Callback anfassen.
local spawnFertig = false
local hatSpawnmanager = pcall(function()
exports.spawnmanager:setAutoSpawn(false) exports.spawnmanager:setAutoSpawn(false)
exports.spawnmanager:spawnPlayer({
x = Config.SpawnPunkt.x,
y = Config.SpawnPunkt.y,
z = Config.SpawnPunkt.z,
heading = Config.SpawnPunkt.heading or 0.0,
model = 'mp_m_freemode_01',
skipFade = true, -- wir steuern den Fade selbst
}, function()
spawnFertig = true
end) end)
if not erfolg then end)
if hatSpawnmanager then
-- Auf den Spawn-Callback warten (mit Sicherheitslimit ~5 s)
local versuche = 0
while not spawnFertig and versuche < 100 do
Wait(50)
versuche = versuche + 1
end
else
Aether.Debug('spawnmanager nicht verfuegbar — Core spawnt eigenstaendig.') Aether.Debug('spawnmanager nicht verfuegbar — Core spawnt eigenstaendig.')
end end
-- Bildschirm schwarz halten, bis der Charakter geladen ist -- Jetzt existiert ein gültiger, gestreamter Ped. Erst JETZT anfassen:
DoScreenFadeOut(0) -- unsichtbar und geparkt halten, bis der Charakter gewählt ist.
SetEntityVisible(PlayerPedId(), false, false) local ped = PlayerPedId()
SetEntityVisible(ped, false, false)
FreezeEntityPosition(ped, true)
Aether.Debug('Client bereit — fordere Spielerdaten an.') Aether.Debug('Client bereit — fordere Spielerdaten an.')
TriggerServerEvent('aether:server:spielerBereit') TriggerServerEvent('aether:server:spielerBereit')