Disconnect/kick prompt with reason, reconnect after world reset with retries; stop mass 'consumed' deletes on scene reload

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-27 16:31:40 +02:00
co-authored by Claude Opus 5.5
parent 90c1af4513
commit 31e630dccb
4 changed files with 137 additions and 38 deletions
+23 -6
View File
@@ -16,6 +16,7 @@ namespace MSCO
public int Id;
public string Path;
public Rigidbody Rb;
public string Name;
public GameObject Go; // zum Unterscheiden: nur Rigidbody weg (angebaut) oder ganzes Objekt weg (verbraucht)
public Vector3 LastPos;
public bool IsVehicle;
@@ -101,6 +102,23 @@ namespace MSCO
public void MarkNetworkCreated(GameObject go) { if (go != null) networkCreated.Add(go); }
/// <summary>
/// Verschwundene Items melden (gegessen, getrunken, verbraucht) - nur wenn das ganze Objekt weg ist (nicht nur der
/// Rigidbody wie beim Anbauen), es ein Item ist und es bei uns passiert ist. Verschwinden viele auf einmal, wird
/// gerade die Szene entladen (Neu laden, Hauptmenü) - dann NICHTS melden, sonst löscht man bei allen die Welt.
/// </summary>
void ReportConsumed(Transform player)
{
if (ItemDestroyed == null || removeList.Count == 0) return;
if (player == null || removeList.Count > 2 || Time.time - loadTime < 30f) return;
foreach (SyncedBody b in removeList)
{
if (b.Go != null || b.IsVehicle || b.Name == null || !b.Name.EndsWith("(itemx)")) continue;
if (IsLocal(b) || (b.LastPos - lastPlayerPos).sqrMagnitude < LocalEventRange * LocalEventRange)
ItemDestroyed(b);
}
}
/// <summary>Gibt es dieses Objekt bei uns schon an dieser Stelle? (dann nicht nochmal erzeugen)</summary>
public bool HasNear(int id, Vector3 pos, float range)
{
@@ -113,6 +131,8 @@ namespace MSCO
{
SyncedBody b;
if (!byId.TryGetValue(id, out b)) return false;
// Nur echte Items (Essen, Getränke ...) - nie Fahrzeuge oder Teile, egal was ein anderer meldet
if (b.IsVehicle || b.Name == null || !b.Name.EndsWith("(itemx)")) return false;
if (b.Go != null) UnityEngine.Object.Destroy(b.Go);
Unregister(b);
return true;
@@ -307,11 +327,6 @@ namespace MSCO
if (b.OwnerId == SyncedBody.NoOwner && ((b.Id ^ frame) & 3) != 0 && b != held && b != driven) continue;
if (b.Rb == null)
{
// Ganzes Objekt weg (gegessen, getrunken, verbraucht) - nicht nur der Rigidbody (Teil angebaut).
// Nur melden, wenn es bei uns passiert ist: wir besaßen es oder standen daneben.
if (b.Go == null && !b.IsVehicle && ItemDestroyed != null
&& (IsLocal(b) || (b.LastPos - lastPlayerPos).sqrMagnitude < LocalEventRange * LocalEventRange))
ItemDestroyed(b);
removeList.Add(b);
continue;
}
@@ -350,6 +365,7 @@ namespace MSCO
else if (Time.time - b.LastRecvTime > RemoteTimeout) SetFree(b);
}
}
ReportConsumed(player);
foreach (SyncedBody b in removeList) Unregister(b);
Held = held != null && held.Rb != null && IsLocal(held) ? held : null;
@@ -895,6 +911,7 @@ namespace MSCO
Path = path,
Rb = c.Key,
Go = c.Key.gameObject,
Name = c.Key.gameObject.name,
LastPos = c.Key.position,
IsVehicle = c.Value,
RootName = c.Key.transform.root.name
@@ -906,7 +923,7 @@ namespace MSCO
// Neues Item nach dem ersten Suchlauf, bei uns in der Nähe und nicht übers Netz entstanden:
// wahrscheinlich gekauft / ausgepackt / geliefert - den anderen melden
bool isItem = !b.IsVehicle && b.Go.name.EndsWith("(itemx)");
if (ScanComplete && isItem && ItemAppeared != null && !networkCreated.Contains(b.Go)
if (ScanComplete && isItem && ItemAppeared != null && !networkCreated.Contains(b.Go) && Time.time - loadTime > 30f
&& (b.LastPos - lastPlayerPos).sqrMagnitude < LocalEventRange * LocalEventRange)
ItemAppeared(b);
}