aether-core: Spawn-Race praeziser beheben (Charakterauswahl-Crash)
Der vorige spawnPlayer-Ansatz fixte nur den Direkt-Spawn-Weg (AutoCharakter=true), verschaerfte aber den Auswahl-Weg: OeffneAuswahl teleportiert/versteckt den Ped, waehrend der erzwungene Spawn noch synchronisiert -> zwei Threads schreiben Netz-State -> Crash. Neuer Ansatz: Auto-Spawn so frueh wie moeglich (ab Resource-Start, Retry-Schleife) abschalten und KEINEN eigenen Spawn erzwingen. Der vorhandene GTA-Standard-Ped bleibt in Ruhe; die Charakterauswahl fasst einen fertigen Ped an. Kein zweiter Spawn-Thread -> kein Race. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
0440de16e5
commit
cad096e7a6
@ -13,54 +13,34 @@ Aether.IstGeladen = false
|
|||||||
-- ---------------------------------------------------------------------
|
-- ---------------------------------------------------------------------
|
||||||
-- Startvorgang
|
-- Startvorgang
|
||||||
-- ---------------------------------------------------------------------
|
-- ---------------------------------------------------------------------
|
||||||
|
-- WICHTIG: Auto-Spawn des spawnmanagers so FRÜH wie möglich abschalten —
|
||||||
|
-- bevor er den Spieler von sich aus spawnt. Genau dieser unkontrollierte
|
||||||
|
-- Spawn läuft parallel zur Charakterauswahl (die den Ped teleportiert/
|
||||||
|
-- versteckt): zwei Threads schreiben gleichzeitig Netz-State ->
|
||||||
|
-- "SendNetPacket ... called from multiple threads" -> Client-Crash.
|
||||||
|
-- Wir spawnen NICHT selbst — GTA hat ohnehin einen Standard-Ped. Der bleibt
|
||||||
|
-- in Ruhe, und die Charakterauswahl fasst einen fertigen, ruhenden Ped an.
|
||||||
|
CreateThread(function()
|
||||||
|
for _ = 1, 100 do
|
||||||
|
if pcall(function() exports.spawnmanager:setAutoSpawn(false) end) then break end
|
||||||
|
Wait(0)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
CreateThread(function()
|
CreateThread(function()
|
||||||
-- Warten, bis die Spielwelt bereit ist
|
-- Warten, bis die Spielwelt bereit ist
|
||||||
while not NetworkIsSessionStarted() do
|
while not NetworkIsSessionStarted() do
|
||||||
Wait(100)
|
Wait(100)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Bildschirm sofort schwarz halten, bevor irgendetwas spawnt
|
-- Sicherheitshalber erneut abschalten, falls der spawnmanager eben erst
|
||||||
|
-- bereit wurde (verhindert einen späten Auto-Spawn).
|
||||||
|
pcall(function() exports.spawnmanager:setAutoSpawn(false) end)
|
||||||
|
|
||||||
|
-- Bildschirm schwarz halten und den Ped verstecken, bis der Charakter
|
||||||
|
-- geladen ist. KEIN eigener Spawn -> kein zweiter Spawn-Thread.
|
||||||
DoScreenFadeOut(0)
|
DoScreenFadeOut(0)
|
||||||
|
SetEntityVisible(PlayerPedId(), false, false)
|
||||||
-- 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: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 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.')
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Jetzt existiert ein gültiger, gestreamter Ped. Erst JETZT anfassen:
|
|
||||||
-- unsichtbar und geparkt halten, bis der Charakter gewählt ist.
|
|
||||||
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')
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user