Validate stored vehicle/object poses, show positions in 'vehicles', admin: Satsuma to me
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+57
-2
@@ -102,6 +102,8 @@ namespace MSCO
|
||||
{
|
||||
SyncedBody b;
|
||||
if (!byId.TryGetValue(id, out b) || b.Rb == null || b.OwnerId != SyncedBody.NoOwner) return false;
|
||||
if (!IsValidPose(pos, rot)) return false;
|
||||
if (b.IsVehicle) pos = AboveGround(pos, b.Rb.transform); // gespeicherte Position evtl. knapp im Boden
|
||||
b.Rb.transform.position = pos;
|
||||
b.Rb.transform.rotation = rot;
|
||||
if (!b.Rb.isKinematic)
|
||||
@@ -132,7 +134,8 @@ namespace MSCO
|
||||
if (!b.IsVehicle) continue;
|
||||
string owner = b.OwnerId == SyncedBody.NoOwner ? "free" : IsLocal(b) ? "ME" : "player " + b.OwnerId;
|
||||
lines.Add(b.RootName + " id=" + b.Id + " owner=" + owner + (b.OwnerActive ? " (active)" : "") +
|
||||
(b.Rb == null ? " [rigidbody gone]" : " kinematic=" + b.Rb.isKinematic + " speed=" + b.Rb.velocity.magnitude.ToString("0.0")));
|
||||
(b.Rb == null ? " [rigidbody gone]" : " kinematic=" + b.Rb.isKinematic + " speed=" + b.Rb.velocity.magnitude.ToString("0.0") +
|
||||
" pos=" + b.Rb.position.ToString("F0") + (b.Rb.gameObject.activeInHierarchy ? "" : " [inactive]")));
|
||||
}
|
||||
if (lines.Count == 1) lines.Add("No vehicles registered! (SATSUMA, HAYOSIKO, ... not found as root objects with a Rigidbody)");
|
||||
return lines;
|
||||
@@ -426,7 +429,7 @@ namespace MSCO
|
||||
int id; Vector3 pos; Quaternion rot; Vector3 vel;
|
||||
ReadState(r, out id, out pos, out rot, out vel);
|
||||
SyncedBody b;
|
||||
if (!byId.TryGetValue(id, out b) || b.Rb == null) continue;
|
||||
if (!byId.TryGetValue(id, out b) || b.Rb == null || !IsValidPose(pos, rot)) continue;
|
||||
// Nur dem aktuellen Besitzer folgen (oder freie Objekte übernehmen)
|
||||
if (b.OwnerId != from && b.OwnerId != SyncedBody.NoOwner) continue;
|
||||
SetRemote(b, from, b.OwnerId == from && b.OwnerActive);
|
||||
@@ -442,6 +445,7 @@ namespace MSCO
|
||||
ReadState(r, out id, out pos, out rot, out vel);
|
||||
SyncedBody b;
|
||||
if (!byId.TryGetValue(id, out b) || b.Rb == null || b.OwnerId != from) return;
|
||||
if (!IsValidPose(pos, rot)) { SetFree(b); return; }
|
||||
b.Rb.transform.position = pos;
|
||||
b.Rb.transform.rotation = rot;
|
||||
b.Rb.isKinematic = b.WasKinematic;
|
||||
@@ -457,6 +461,57 @@ namespace MSCO
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Position innerhalb der Karte, Drehung gültig (gleiche Regel wie auf dem Server).</summary>
|
||||
static bool IsValidPose(Vector3 p, Quaternion q)
|
||||
{
|
||||
if (float.IsNaN(p.x) || float.IsNaN(p.y) || float.IsNaN(p.z) || float.IsInfinity(p.x) || float.IsInfinity(p.y) || float.IsInfinity(p.z))
|
||||
return false;
|
||||
if (Mathf.Abs(p.x) > 6000f || Mathf.Abs(p.z) > 6000f || p.y < -200f || p.y > 3000f) return false;
|
||||
float len = Mathf.Sqrt(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w);
|
||||
return len > 0.9f && len < 1.1f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Liegt die Position im Boden, auf die Bodenoberfläche heben. Kurzer Strahl ab 2 m über dem Punkt
|
||||
/// (nicht aufs Garagendach), die eigenen Teile des Fahrzeugs werden ignoriert.
|
||||
/// </summary>
|
||||
static Vector3 AboveGround(Vector3 pos, Transform ignore)
|
||||
{
|
||||
float ground = float.MinValue;
|
||||
foreach (RaycastHit hit in Physics.RaycastAll(pos + Vector3.up * 2f, Vector3.down, 4f))
|
||||
{
|
||||
if (hit.collider.isTrigger || (ignore != null && hit.transform.IsChildOf(ignore))) continue;
|
||||
if (hit.transform.root.name == "PLAYER") continue;
|
||||
ground = Mathf.Max(ground, hit.point.y);
|
||||
}
|
||||
return ground > pos.y - 0.2f ? new Vector3(pos.x, ground + 0.6f, pos.z) : pos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Admin: Fahrzeug (Wurzelname beginnt mit rootPrefix) an eine Position holen. Fährt es gerade ein
|
||||
/// anderer Spieler, geht das nicht. Gibt einen Statustext zurück.
|
||||
/// </summary>
|
||||
public string BringVehicle(string rootPrefix, Vector3 pos, Quaternion rot)
|
||||
{
|
||||
foreach (SyncedBody b in byId.Values)
|
||||
{
|
||||
if (!b.IsVehicle || b.Rb == null || !b.RootName.StartsWith(rootPrefix)) continue;
|
||||
if (IsRemoteOwned(b) && b.OwnerActive) return rootPrefix + " is being driven by another player";
|
||||
Claim(b, false); // wir besitzen es jetzt -> Position geht an alle und an den Server
|
||||
b.Rb.transform.position = AboveGround(pos, b.Rb.transform);
|
||||
b.Rb.transform.rotation = rot;
|
||||
if (!b.Rb.isKinematic)
|
||||
{
|
||||
b.Rb.velocity = Vector3.zero;
|
||||
b.Rb.angularVelocity = Vector3.zero;
|
||||
}
|
||||
b.StillTime = 0f;
|
||||
b.LastSentTime = -100f;
|
||||
return rootPrefix + " is next to you";
|
||||
}
|
||||
return rootPrefix + " not found (mp vehicles shows all vehicles)";
|
||||
}
|
||||
|
||||
static void WriteState(BinaryWriter w, SyncedBody b)
|
||||
{
|
||||
Vector3 p = b.Rb.position;
|
||||
|
||||
Reference in New Issue
Block a user