Stuck bodies are placed on top instead of being reset into the same spot (no fling loop); reset message shown in-game before reconnecting; server: backups / restore-save
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+15
-1
@@ -545,6 +545,9 @@ namespace MSCO
|
||||
string lastServerHost, lastServerName;
|
||||
int lastServerPort, lastServerMax;
|
||||
string reconnectMessage; // gesetzt, wenn der Server uns neu verbinden lässt
|
||||
float reconnectHoldUntil; // so lange die Meldung noch im Spiel zeigen
|
||||
string centerMessage; // große Meldung in der Bildmitte
|
||||
float centerMessageUntil;
|
||||
float reconnectAt;
|
||||
|
||||
void ConnectToServer(string host, int port, string displayName, int maxPlayers)
|
||||
@@ -811,6 +814,7 @@ namespace MSCO
|
||||
|
||||
if (session.IsClosed)
|
||||
{
|
||||
if (Time.realtimeSinceStartup < reconnectHoldUntil) return; // Meldung erst lesen lassen
|
||||
OnSessionEnded(session.CloseReason);
|
||||
return;
|
||||
}
|
||||
@@ -1144,8 +1148,11 @@ namespace MSCO
|
||||
// Server hat die Welt zurückgesetzt o.ä.: Meldung zeigen, ins Menü, dann automatisch neu verbinden
|
||||
reconnectMessage = r.ReadString();
|
||||
overlays.AddChat("", reconnectMessage, true);
|
||||
// Groß in der Bildmitte zeigen und erst nach kurzer Zeit ins Menü wechseln - sonst sieht man nichts
|
||||
centerMessage = reconnectMessage;
|
||||
centerMessageUntil = Time.realtimeSinceStartup + 3f;
|
||||
reconnectHoldUntil = Time.realtimeSinceStartup + 2.5f;
|
||||
session.Close("Reconnecting");
|
||||
OnSessionEnded(session.CloseReason);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1774,6 +1781,13 @@ namespace MSCO
|
||||
|
||||
if (Time.realtimeSinceStartup < savingMessageUntil)
|
||||
GUI.Label(new Rect(0, Screen.height / 2f - 40, Screen.width, 80), "SAVING GAME...", savingStyle);
|
||||
if (centerMessage != null && Time.realtimeSinceStartup < centerMessageUntil)
|
||||
{
|
||||
int oldSize = savingStyle.fontSize;
|
||||
savingStyle.fontSize = 30;
|
||||
GUI.Label(new Rect(0, Screen.height / 2f - 40, Screen.width, 80), centerMessage.ToUpper(), savingStyle);
|
||||
savingStyle.fontSize = oldSize;
|
||||
}
|
||||
|
||||
if (session != null) DrawHud();
|
||||
DrawPing();
|
||||
|
||||
+29
-12
@@ -34,6 +34,7 @@ namespace MSCO
|
||||
// Wie oft kurz hintereinander weggeschleudert (steckt es in etwas fest?)
|
||||
public int RunawayCount;
|
||||
public float RunawayWindowStart;
|
||||
public float LastRunawayLog = -100f;
|
||||
|
||||
public Vector3 TargetPos;
|
||||
public Quaternion TargetRot;
|
||||
@@ -554,27 +555,43 @@ namespace MSCO
|
||||
if (rb.isKinematic || rb.velocity.sqrMagnitude < RunawaySpeed * RunawaySpeed) return;
|
||||
rb.velocity = Vector3.zero;
|
||||
rb.angularVelocity = Vector3.zero;
|
||||
b.NoMotionClaimUntil = Time.time + HandoverCooldown;
|
||||
|
||||
// Mehrmals kurz hintereinander: das Objekt steckt in etwas fest (z.B. abgebautes Teil im Auto).
|
||||
// Dann nicht wieder an dieselbe Stelle setzen, sondern nach oben heraus heben.
|
||||
// Wird es kurz hintereinander wieder weggeschleudert, steckt es in etwas fest (z.B. loses Teil im Auto).
|
||||
// NICHT an die alte Stelle zurücksetzen (dort steckt es ja) - sondern von oben auf die nächste freie Fläche.
|
||||
if (Time.time - b.RunawayWindowStart > 5f) { b.RunawayWindowStart = Time.time; b.RunawayCount = 0; }
|
||||
b.RunawayCount++;
|
||||
bool stuck = b.RunawayCount >= 3;
|
||||
bool stuck = b.RunawayCount >= 2;
|
||||
if (stuck)
|
||||
{
|
||||
PlaceOnTop(rb);
|
||||
b.RunawayCount = 0;
|
||||
}
|
||||
rb.Sleep();
|
||||
|
||||
// Nicht das Log fluten: pro Objekt höchstens alle 30 s melden
|
||||
if (Time.time - b.LastRunawayLog > 30f)
|
||||
{
|
||||
b.LastRunawayLog = Time.time;
|
||||
MscoLog.Warning("Stopped " + b.RootName + " - it was flung away by the physics" + (stuck ? " (was stuck, placed on top)" : ""));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Objekt von oben auf die höchste Fläche an seiner Stelle legen (eigene Collider und Spieler ignoriert).</summary>
|
||||
static void PlaceOnTop(Rigidbody rb)
|
||||
{
|
||||
Bounds bounds = new Bounds(rb.worldCenterOfMass, Vector3.zero);
|
||||
foreach (Collider c in rb.GetComponentsInChildren<Collider>()) bounds.Encapsulate(c.bounds);
|
||||
rb.transform.position += Vector3.up * (bounds.size.y + 1.5f);
|
||||
b.RunawayCount = 0;
|
||||
}
|
||||
else if (IsLocal(b) && b.LastSentTime > 0f && IsValidPose(b.LastSentPos, b.LastSentRot))
|
||||
Vector3 from = new Vector3(bounds.center.x, bounds.max.y + 50f, bounds.center.z);
|
||||
float top = float.MinValue;
|
||||
foreach (RaycastHit hit in Physics.RaycastAll(from, Vector3.down, 120f))
|
||||
{
|
||||
rb.transform.position = b.LastSentPos;
|
||||
rb.transform.rotation = b.LastSentRot;
|
||||
if (hit.collider.isTrigger || hit.transform.IsChildOf(rb.transform) || hit.transform.root.name == "PLAYER") continue;
|
||||
if (hit.point.y > top) top = hit.point.y;
|
||||
}
|
||||
b.NoMotionClaimUntil = Time.time + HandoverCooldown;
|
||||
if (b.RunawayCount <= 1 || stuck)
|
||||
MscoLog.Warning("[MSCO] Stopped " + b.RootName + " - it was flung away by the physics" + (stuck ? " (stuck, lifted out)" : ""));
|
||||
if (top == float.MinValue) return;
|
||||
float lift = top + bounds.extents.y + 0.3f - bounds.center.y;
|
||||
rb.transform.position += Vector3.up * lift;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user