MSCO 2.10.3: bolt stages and part tightness synced, snap to pivot, admin tighten/loosen
- Every bolt (Screw FSM, stage 0-8) and every part's tightness (BoltCheck/Use "Tightness", counted by the tool) is synced as state - before only the bolt turned on other clients, the part stayed loose or tight there - Tightening a part (tool, admin, other player) snaps it exactly onto its pivot (installed parts sit at local 0), except screw-in parts and hinged doors/hoods - Admin VEHICLE tab: TIGHTEN/LOOSEN per part, TIGHTEN ALL/LOOSEN ALL, bolted/loose state - fsmdump "pivots": installed part offsets Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+52
-7
@@ -64,6 +64,8 @@ namespace MSCO
|
||||
// übertragen und über die Stufen-Logik der Schraube angewendet (Position, Dichtung, Zähler des Teils)
|
||||
public FsmState BoltDispatch;
|
||||
public bool InitialSent;
|
||||
public bool Functional; // Schraube schaltet etwas (Ablassschraube): Welt-Autorität gibt den Stand einmal vor
|
||||
public bool Exact; // jede Änderung senden (Schrauben-Stufen, Festigkeit der Teile)
|
||||
}
|
||||
|
||||
readonly Dictionary<int, Var> vars = new Dictionary<int, Var>();
|
||||
@@ -122,14 +124,17 @@ namespace MSCO
|
||||
ResolveSatsuma(objects);
|
||||
foreach (Var v in vars.Values)
|
||||
{
|
||||
// Teil wird fester (eigenes Werkzeug): genau auf seinen Halter setzen (verrutschte Teile, z.B. nach der Sync)
|
||||
if (v.Exact && v.Type == 1 && v.Fsm != null && v.Fsm.FsmName == "BoltCheck" && GetFloat(v) > v.LastF + 0.01f)
|
||||
VehicleAdmin.SnapToPivot(v.Fsm.gameObject);
|
||||
// Fährt/schiebt ein anderer das Fahrzeug, ist seine Version maßgeblich - nichts senden
|
||||
int owner = objects.VehicleOwner(OwnerRoot(v.Root));
|
||||
if (owner != SyncedBody.NoOwner && owner != localId) { if (Changed(v, false)) Remember(v); continue; }
|
||||
|
||||
// Eigenes Fahrzeug: jede Änderung. Freies Fahrzeug: nur deutliche Sprünge (Öl nachfüllen, tanken ...) -
|
||||
// langsames Abdriften (z.B. Abkühlen) rechnet jeder selbst, sonst überschreiben sich alle gegenseitig
|
||||
bool big = owner == SyncedBody.NoOwner && v.BoltDispatch == null;
|
||||
if (v.BoltDispatch != null && worldAuthority && !v.InitialSent)
|
||||
bool big = owner == SyncedBody.NoOwner && !v.Exact;
|
||||
if (v.Functional && worldAuthority && !v.InitialSent)
|
||||
{
|
||||
// Einmal den eigenen Stand vorgeben, damit alle gleich sind (vorher auseinandergelaufene Schrauben)
|
||||
v.InitialSent = true;
|
||||
@@ -198,7 +203,8 @@ namespace MSCO
|
||||
if (!IsTracked(root)) { Forget(fsm); continue; }
|
||||
scanned[fsm] = fsm.transform.parent;
|
||||
Forget(fsm);
|
||||
if (RegisterFunctionalBolt(fsm, root)) continue;
|
||||
RegisterTightness(fsm, root);
|
||||
if (RegisterBolt(fsm, root)) continue;
|
||||
// FSMs, die Größen/Positionen setzen (z.B. Füllstands-Anzeigen), NICHT anfassen: ein übertragener Wert
|
||||
// kann dort eine Größe 0 ergeben - Unity stürzt dann in der Physik ab ("cleaning the mesh failed")
|
||||
if (TouchesTransform(fsm)) continue;
|
||||
@@ -223,7 +229,46 @@ namespace MSCO
|
||||
/// Leck "Oil" ist an). Sonst laufen Schrauben über FsmSync (Ereignisse): ging eins verloren, war die Ablassschraube
|
||||
/// bei einem offen und beim anderen zu - bei ihm lief dann endlos Öl aus (der Ölstand kam ja ständig nach).
|
||||
/// </summary>
|
||||
bool RegisterFunctionalBolt(PlayMakerFSM fsm, string root)
|
||||
/// <summary>
|
||||
/// Festigkeit eines Teils (BoltCheck bzw. bei aufgeschraubten Teilen wie dem Ölfilter "Use"): zählt das Werkzeug
|
||||
/// beim Schrauben hoch - beim Mitspieler drehte sich bisher nur die Schraube, das Teil blieb "lose" bzw. "fest".
|
||||
/// </summary>
|
||||
void RegisterTightness(PlayMakerFSM fsm, string root)
|
||||
{
|
||||
if (fsm.FsmName != "BoltCheck" && fsm.FsmName != "Use") return;
|
||||
FsmFloat tightness = fsm.FsmVariables.FindFsmFloat("Tightness");
|
||||
if (tightness == null) return;
|
||||
if (fsm.FsmName == "Use" && fsm.gameObject.GetComponents<PlayMakerFSM>().Length > 0)
|
||||
{
|
||||
bool screwed = false;
|
||||
foreach (PlayMakerFSM other in fsm.gameObject.GetComponents<PlayMakerFSM>()) if (other.FsmName == "Screw") screwed = true;
|
||||
if (!screwed) return;
|
||||
}
|
||||
string name = FsmSync.PathOf(fsm.transform) + "|" + fsm.FsmName + "|Tightness";
|
||||
int key = Hash(name);
|
||||
Var existing;
|
||||
if (vars.TryGetValue(key, out existing) && existing.Variable == tightness) return;
|
||||
var v = new Var { Key = key, Name = name, Root = root, Variable = tightness, Type = 1, Fsm = fsm, Exact = true };
|
||||
Remember(v);
|
||||
vars[key] = v;
|
||||
List<int> keys;
|
||||
if (!keysByFsm.TryGetValue(fsm, out keys)) keysByFsm[fsm] = keys = new List<int>();
|
||||
keys.Add(key);
|
||||
byte[] stored;
|
||||
if (pending.TryGetValue(key, out stored))
|
||||
{
|
||||
pending.Remove(key);
|
||||
byte[] value = new byte[stored.Length - 1];
|
||||
Array.Copy(stored, 1, value, 0, value.Length);
|
||||
Apply(v, stored[0], value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Jede Schraube (FSM "Screw" mit Stufe 0-8): Stufe als Zustand übertragen, angewendet über die Stufen-Logik der
|
||||
/// Schraube. Schrauben, die etwas schalten (Ablassschraube), gibt die Welt-Autorität nach dem Beitreten einmal vor.
|
||||
/// </summary>
|
||||
bool RegisterBolt(PlayMakerFSM fsm, string root)
|
||||
{
|
||||
if (fsm.FsmName != "Screw") return false;
|
||||
FsmInt stage = fsm.FsmVariables.FindFsmInt("Stage");
|
||||
@@ -243,13 +288,11 @@ namespace MSCO
|
||||
}
|
||||
}
|
||||
catch { return false; }
|
||||
if (!switches) return false;
|
||||
|
||||
string name = FsmSync.PathOf(fsm.transform) + "|" + fsm.FsmName + "|Stage";
|
||||
int key = Hash(name);
|
||||
Var existing;
|
||||
if (vars.TryGetValue(key, out existing) && existing.Variable == stage) return true;
|
||||
var v = new Var { Key = key, Name = name, Root = root, Variable = stage, Type = 2, Fsm = fsm, BoltDispatch = dispatch };
|
||||
var v = new Var { Key = key, Name = name, Root = root, Variable = stage, Type = 2, Fsm = fsm, BoltDispatch = dispatch, Functional = switches, Exact = true };
|
||||
Remember(v);
|
||||
vars[key] = v;
|
||||
List<int> keys;
|
||||
@@ -428,7 +471,9 @@ namespace MSCO
|
||||
case 1:
|
||||
float f = BitConverter.ToSingle(value, 0);
|
||||
if (float.IsNaN(f) || float.IsInfinity(f)) return; // nie ungültige Werte übernehmen
|
||||
bool tighter = v.Exact && v.Fsm != null && v.Fsm.FsmName == "BoltCheck" && f > GetFloat(v) + 0.01f;
|
||||
SetFloat(v, f);
|
||||
if (tighter) VehicleAdmin.SnapToPivot(v.Fsm.gameObject); // vom Mitspieler festgezogen: Teil auf den Halter
|
||||
break;
|
||||
case 2:
|
||||
int n = BitConverter.ToInt32(value, 0);
|
||||
|
||||
Reference in New Issue
Block a user