Beta Release
This commit is contained in:
+122
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using HutongGames.PlayMaker;
|
||||
using MSCLoader;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MSCO
|
||||
{
|
||||
/// <summary>
|
||||
/// Türen, Tore, Hauben, Klappen (Garagentor, Haustüren, Autotüren ...). Die Mod beobachtet die
|
||||
/// PlayMaker-FSMs dieser Objekte: Wechselt eine bei uns in einen neuen Zustand (z.B. "Open door"),
|
||||
/// wird dieser Zustand an die anderen geschickt und dort ebenfalls ausgelöst. Unabhängig davon,
|
||||
/// wie der Spieler das Objekt bedient hat (Klick, Taste, Hand-FSM ...).
|
||||
/// </summary>
|
||||
public class DoorSync
|
||||
{
|
||||
static readonly string[] Keywords = { "door", "gate", "hood", "bonnet", "trunk", "lid", "hatch" };
|
||||
|
||||
const float Cooldown = 1.5f; // Folge-Zustände der Animation nicht nochmal senden
|
||||
const float RescanInterval = 10f; // neue Objekte (z.B. angebaute Autotüren) aufnehmen
|
||||
|
||||
class Tracked
|
||||
{
|
||||
public string Key;
|
||||
public PlayMakerFSM Fsm;
|
||||
public string LastState;
|
||||
public float QuietUntil;
|
||||
}
|
||||
|
||||
readonly Dictionary<string, Tracked> byKey = new Dictionary<string, Tracked>();
|
||||
float nextScan;
|
||||
|
||||
public int Count { get { return byKey.Count; } }
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
byKey.Clear();
|
||||
nextScan = 0f;
|
||||
}
|
||||
|
||||
public void Update(Action<MsgType, byte[]> send)
|
||||
{
|
||||
float now = Time.realtimeSinceStartup;
|
||||
if (now >= nextScan)
|
||||
{
|
||||
nextScan = now + RescanInterval;
|
||||
Scan();
|
||||
}
|
||||
|
||||
foreach (Tracked t in byKey.Values)
|
||||
{
|
||||
if (t.Fsm == null) continue;
|
||||
string state = t.Fsm.ActiveStateName;
|
||||
if (state == t.LastState) continue;
|
||||
t.LastState = state;
|
||||
|
||||
if (now < t.QuietUntil) continue; // Folge einer eigenen oder fremden Aktion
|
||||
FsmState s = t.Fsm.Fsm.GetState(state);
|
||||
if (s == null || FsmSync.ChecksInputPublic(s)) continue; // nur "Maus zeigt drauf" o.ä.
|
||||
|
||||
t.QuietUntil = now + Cooldown;
|
||||
string key = t.Key;
|
||||
send(MsgType.DoorState, NetSession.Build(w => { w.Write(key); w.Write(state); }));
|
||||
if (FsmSync.Debug) ModConsole.Print("[MSCO] >> DOOR " + key + " -> " + state);
|
||||
}
|
||||
}
|
||||
|
||||
public void Apply(BinaryReader r)
|
||||
{
|
||||
ApplyState(r.ReadString(), r.ReadString());
|
||||
}
|
||||
|
||||
/// <summary>Zustand übernehmen (von einem Mitspieler oder aus dem Server-Snapshot).</summary>
|
||||
public void ApplyState(string key, string state)
|
||||
{
|
||||
Tracked t;
|
||||
if (!byKey.TryGetValue(key, out t) || t.Fsm == null)
|
||||
{
|
||||
Scan(); // Objekt vielleicht erst seit kurzem aktiv
|
||||
if (!byKey.TryGetValue(key, out t) || t.Fsm == null)
|
||||
{
|
||||
if (FsmSync.Debug) ModConsole.Warning("[MSCO] << DOOR not found: " + key);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (t.Fsm.ActiveStateName == state) return;
|
||||
FsmState target = t.Fsm.Fsm.GetState(state);
|
||||
if (target == null) return;
|
||||
t.QuietUntil = Time.realtimeSinceStartup + Cooldown; // Folge-Zustände nicht zurückschicken
|
||||
t.LastState = state;
|
||||
FsmSync.SwitchStateSilently(t.Fsm, target);
|
||||
if (FsmSync.Debug) ModConsole.Print("[MSCO] << DOOR " + key + " -> " + state);
|
||||
}
|
||||
|
||||
void Scan()
|
||||
{
|
||||
foreach (PlayMakerFSM fsm in SceneCache.Fsms(5f))
|
||||
{
|
||||
if (fsm == null) continue;
|
||||
string root = fsm.transform.root.name;
|
||||
if (root == "PLAYER" || root.StartsWith("MSCO_")) continue;
|
||||
if (!Matches(fsm.gameObject.name) && !Matches(fsm.FsmName) && !Matches(fsm.transform.parent != null ? fsm.transform.parent.name : "")) continue;
|
||||
|
||||
string key = FsmSync.PathOf(fsm.transform) + "|" + fsm.FsmName;
|
||||
Tracked t;
|
||||
if (byKey.TryGetValue(key, out t) && t.Fsm == fsm) continue;
|
||||
byKey[key] = new Tracked { Key = key, Fsm = fsm, LastState = fsm.ActiveStateName };
|
||||
}
|
||||
}
|
||||
|
||||
static bool Matches(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name)) return false;
|
||||
string lower = name.ToLower();
|
||||
foreach (string k in Keywords)
|
||||
if (lower.Contains(k)) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user