Server gets the current save game from a player in the game (on join and every few minutes) instead of replaying actions; vehicle fire/smoke synced, also for parked cars
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+44
-3
@@ -40,6 +40,7 @@ namespace MSCO
|
||||
public readonly Dictionary<int, Light> Lights = new Dictionary<int, Light>();
|
||||
public readonly Dictionary<int, AudioSource> Audio = new Dictionary<int, AudioSource>();
|
||||
public readonly Dictionary<int, Transform> Dials = new Dictionary<int, Transform>();
|
||||
public readonly Dictionary<int, ParticleSystem> Particles = new Dictionary<int, ParticleSystem>();
|
||||
}
|
||||
|
||||
class Snapshot
|
||||
@@ -48,6 +49,7 @@ namespace MSCO
|
||||
public readonly Dictionary<int, bool> Lights = new Dictionary<int, bool>();
|
||||
public readonly Dictionary<int, AudioState> Audio = new Dictionary<int, AudioState>();
|
||||
public readonly Dictionary<int, Quaternion> Dials = new Dictionary<int, Quaternion>();
|
||||
public readonly Dictionary<int, bool> Particles = new Dictionary<int, bool>();
|
||||
}
|
||||
|
||||
readonly Dictionary<int, Components> components = new Dictionary<int, Components>();
|
||||
@@ -62,13 +64,17 @@ namespace MSCO
|
||||
|
||||
// ---------------------------------------------------------------- Senden
|
||||
|
||||
public void Update(ObjectSync objects, Action<MsgType, byte[]> send, float dt)
|
||||
public void Update(ObjectSync objects, Action<MsgType, byte[]> send, float dt, bool worldAuthority)
|
||||
{
|
||||
sendTimer += dt;
|
||||
if (sendTimer < SendInterval) return;
|
||||
sendTimer = 0f;
|
||||
|
||||
foreach (SyncedBody b in objects.LocalVehicles())
|
||||
// Eigene Fahrzeuge (fahren/schieben) und - wenn wir die Welt vorgeben - auch freie, geparkte Fahrzeuge:
|
||||
// sonst würde z.B. ein brennendes, abgestelltes Auto nur bei einem Spieler brennen
|
||||
List<SyncedBody> vehicles = objects.LocalVehicles();
|
||||
if (worldAuthority) vehicles.AddRange(objects.FreeVehicles());
|
||||
foreach (SyncedBody b in vehicles)
|
||||
{
|
||||
Components c = GetComponents(b);
|
||||
if (c == null) continue;
|
||||
@@ -104,6 +110,16 @@ namespace MSCO
|
||||
w.Write(d.Key);
|
||||
w.Write(q.x); w.Write(q.y); w.Write(q.z); w.Write(q.w);
|
||||
}
|
||||
// Partikel-Effekte (Feuer, Rauch, Dampf, Funken): läuft / läuft nicht
|
||||
int particleCount = 0;
|
||||
foreach (ParticleSystem ps in c.Particles.Values) if (ps != null) particleCount++;
|
||||
w.Write(particleCount);
|
||||
foreach (KeyValuePair<int, ParticleSystem> ps in c.Particles)
|
||||
{
|
||||
if (ps.Value == null) continue;
|
||||
w.Write(ps.Key);
|
||||
w.Write(ps.Value.gameObject.activeInHierarchy && ps.Value.isPlaying);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -132,6 +148,11 @@ namespace MSCO
|
||||
if (!float.IsNaN(q.x) && !float.IsNaN(q.w)) s.Dials[key] = q;
|
||||
}
|
||||
}
|
||||
if (r.BaseStream.Length - r.BaseStream.Position >= 4)
|
||||
{
|
||||
int particles = r.ReadInt32();
|
||||
for (int i = 0; i < particles; i++) s.Particles[r.ReadInt32()] = r.ReadBoolean();
|
||||
}
|
||||
incoming[id] = s;
|
||||
}
|
||||
|
||||
@@ -142,7 +163,7 @@ namespace MSCO
|
||||
{
|
||||
if (Time.time - kv.Value.ReceivedAt > ApplyTimeout) continue;
|
||||
SyncedBody b = objects.Get(kv.Key);
|
||||
if (b == null || !objects.IsRemoteOwnedBody(b)) continue;
|
||||
if (b == null || objects.IsLocalBody(b)) continue; // eigene Fahrzeuge simulieren wir selbst
|
||||
Components c = GetComponents(b);
|
||||
if (c == null) continue;
|
||||
|
||||
@@ -156,6 +177,11 @@ namespace MSCO
|
||||
AudioSource src;
|
||||
if (c.Audio.TryGetValue(a.Key, out src) && src != null) SetAudio(src, a.Value);
|
||||
}
|
||||
foreach (KeyValuePair<int, bool> p in kv.Value.Particles)
|
||||
{
|
||||
ParticleSystem ps;
|
||||
if (c.Particles.TryGetValue(p.Key, out ps) && ps != null) SetParticles(ps, p.Value, c.Root);
|
||||
}
|
||||
float t = Mathf.Clamp01(Time.deltaTime * DialSmoothing);
|
||||
foreach (KeyValuePair<int, Quaternion> d in kv.Value.Dials)
|
||||
{
|
||||
@@ -179,6 +205,18 @@ namespace MSCO
|
||||
if (!t.gameObject.activeSelf) t.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
static void SetParticles(ParticleSystem ps, bool playing, Transform root)
|
||||
{
|
||||
if (playing)
|
||||
{
|
||||
// Effekte hängen oft an einem abgeschalteten Objekt (z.B. "Fire"), das die Spiel-Logik aktiviert
|
||||
for (Transform t = ps.transform; t != null && t != root; t = t.parent)
|
||||
if (!t.gameObject.activeSelf) t.gameObject.SetActive(true);
|
||||
if (!ps.isPlaying) ps.Play();
|
||||
}
|
||||
else if (ps.isPlaying) ps.Stop();
|
||||
}
|
||||
|
||||
static void SetAudio(AudioSource src, AudioState state)
|
||||
{
|
||||
if (!src.gameObject.activeInHierarchy) return;
|
||||
@@ -206,6 +244,9 @@ namespace MSCO
|
||||
seen.Clear();
|
||||
foreach (Transform t in b.Rb.GetComponentsInChildren<Transform>(true))
|
||||
if (IsDial(t.name)) c.Dials[Key(t, c.Root, seen)] = t;
|
||||
seen.Clear();
|
||||
foreach (ParticleSystem ps in b.Rb.GetComponentsInChildren<ParticleSystem>(true))
|
||||
c.Particles[Key(ps.transform, c.Root, seen)] = ps;
|
||||
components[b.Id] = c;
|
||||
return c;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user