MSCO 2.10.2: passenger only while moving, drain plug sync, admin VEHICLE tab, profile layout
- Passenger: auto ride-along only when the vehicle moves (speed from its motion, also for kinematic remote cars) - no more getting stuck while working in the engine bay or re-captured - Bolts with a function (drain plug: stage 0-5 = oil leak on) are synced as stage and applied through the bolt's own stage logic; world authority sends its state once after joining. Fixes endless oil leaking when players had the drain plug in different states - Admin menu VEHICLE tab: fluids with FILL/EMPTY, all Database parts with wear/damage, REPAIR/BREAK per part, REPAIR ALL, filter - Server profile: info and players as two equal cards, no wrapping - fsmdump also lists FSM variables Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+75
-3
@@ -60,6 +60,10 @@ namespace MSCO
|
||||
public float LastF;
|
||||
public int LastI;
|
||||
public bool LastB;
|
||||
// Schraube mit Funktion (z.B. Ablassschraube der Ölwanne: offen = Öl läuft aus): die Stufe wird als Zustand
|
||||
// übertragen und über die Stufen-Logik der Schraube angewendet (Position, Dichtung, Zähler des Teils)
|
||||
public FsmState BoltDispatch;
|
||||
public bool InitialSent;
|
||||
}
|
||||
|
||||
readonly Dictionary<int, Var> vars = new Dictionary<int, Var>();
|
||||
@@ -103,7 +107,7 @@ namespace MSCO
|
||||
nextScan = -1f; // erster Suchlauf verteilt, siehe Update
|
||||
}
|
||||
|
||||
public void Update(ObjectSync objects, int localId, Action<MsgType, byte[]> send)
|
||||
public void Update(ObjectSync objects, int localId, Action<MsgType, byte[]> send, bool worldAuthority = false)
|
||||
{
|
||||
if (nextScan < 0f) nextScan = Time.time + 3.1f; // nicht alle Sync-Teile im selben Frame suchen lassen
|
||||
if (Time.time >= nextScan)
|
||||
@@ -124,7 +128,15 @@ namespace MSCO
|
||||
|
||||
// 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;
|
||||
bool big = owner == SyncedBody.NoOwner && v.BoltDispatch == null;
|
||||
if (v.BoltDispatch != null && worldAuthority && !v.InitialSent)
|
||||
{
|
||||
// Einmal den eigenen Stand vorgeben, damit alle gleich sind (vorher auseinandergelaufene Schrauben)
|
||||
v.InitialSent = true;
|
||||
Remember(v);
|
||||
outgoing.Add(v);
|
||||
continue;
|
||||
}
|
||||
if (!Changed(v, big)) continue;
|
||||
Remember(v);
|
||||
outgoing.Add(v);
|
||||
@@ -186,6 +198,7 @@ namespace MSCO
|
||||
if (!IsTracked(root)) { Forget(fsm); continue; }
|
||||
scanned[fsm] = fsm.transform.parent;
|
||||
Forget(fsm);
|
||||
if (RegisterFunctionalBolt(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;
|
||||
@@ -205,6 +218,54 @@ namespace MSCO
|
||||
if (vars.Count != before) MscoLog.Info("[MSCO] Vehicle state: " + vars.Count + " values synced");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Schrauben, deren Stufen etwas ein-/ausschalten (ActivateGameObject - z.B. die Ablassschraube: Stufe 0-5 = das
|
||||
/// 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)
|
||||
{
|
||||
if (fsm.FsmName != "Screw") return false;
|
||||
FsmInt stage = fsm.FsmVariables.FindFsmInt("Stage");
|
||||
if (stage == null) return false;
|
||||
FsmState dispatch = fsm.Fsm.GetState("Stages 2") ?? fsm.Fsm.GetState("Stages");
|
||||
if (dispatch == null) return false;
|
||||
bool switches = false;
|
||||
try
|
||||
{
|
||||
foreach (FsmState state in fsm.FsmStates)
|
||||
{
|
||||
if (!state.ActionsLoaded) state.LoadActions();
|
||||
if (state.Actions == null) continue;
|
||||
foreach (FsmStateAction a in state.Actions)
|
||||
if (a != null && a.GetType().Name == "ActivateGameObject") { switches = true; break; }
|
||||
if (switches) break;
|
||||
}
|
||||
}
|
||||
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 };
|
||||
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);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static readonly string[] TransformActionWords = { "Scale", "Position", "Rotate", "Rotation", "Translate", "Parent" };
|
||||
|
||||
static bool TouchesTransform(PlayMakerFSM fsm)
|
||||
@@ -369,7 +430,18 @@ namespace MSCO
|
||||
if (float.IsNaN(f) || float.IsInfinity(f)) return; // nie ungültige Werte übernehmen
|
||||
SetFloat(v, f);
|
||||
break;
|
||||
case 2: ((FsmInt)v.Variable).Value = BitConverter.ToInt32(value, 0); break;
|
||||
case 2:
|
||||
int n = BitConverter.ToInt32(value, 0);
|
||||
if (v.BoltDispatch != null)
|
||||
{
|
||||
if (n < 0 || n > 8 || ((FsmInt)v.Variable).Value == n) { Remember(v); return; }
|
||||
((FsmInt)v.Variable).Value = n;
|
||||
if (v.Fsm != null && v.Fsm.gameObject.activeInHierarchy) FsmSync.SwitchStateSilently(v.Fsm, v.BoltDispatch);
|
||||
if (FsmSync.Debug) MscoLog.Info("[MSCO] << BOLT " + v.Name + " -> " + n);
|
||||
break;
|
||||
}
|
||||
((FsmInt)v.Variable).Value = n;
|
||||
break;
|
||||
default: ((FsmBool)v.Variable).Value = value[0] != 0; break;
|
||||
}
|
||||
Remember(v); // nicht als eigene Änderung zurückschicken
|
||||
|
||||
Reference in New Issue
Block a user