Decompiled source of SLTCore v0.2.0
Mods/SLTCore.Fusion.dll
Decompiled a week agousing System; using System.Buffers.Binary; using System.Collections.Concurrent; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Threading; using LabFusion.Entities; using LabFusion.Network; using LabFusion.Network.Serialization; using LabFusion.SDK.Modules; using MelonLoader; using Microsoft.CodeAnalysis; using SLTCore.Core; using SLTCore.Fusion; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(FusionBridgeMod), "SLTCore Fusion Bridge", "0.2.0", "CraftyDev", null)] [assembly: MelonGame("Stress Level Zero", "BONELAB")] [assembly: MelonAdditionalDependencies(new string[] { "SLTCore", "LabFusion" })] [assembly: AssemblyVersion("0.2.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace SLTCore.Fusion { public sealed class FusionBridgeMod : MelonMod { private SLTFusionTransport? _transport; public override void OnInitializeMelon() { try { ModuleMessageManager.RegisterHandler<SLTFusionMessage>(); _transport = new SLTFusionTransport(); SLTFusionMessage.Transport = _transport; if (SLTAPI.Service != null) { SLTAPI.Service.AttachTransport((ISLTTransport)(object)_transport); } else { SLTAPI.Available += Attach; } ((MelonBase)this).LoggerInstance.Msg("SLTCore Fusion transport registered. Built against Fusion 1.14.3; multiplayer headset tests are still required."); } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Error("Fusion API mismatch; navigation will remain disabled in multiplayer: " + ex.Message); } } private void Attach(SLTService service) { if (_transport != null) { service.AttachTransport((ISLTTransport)(object)_transport); } } public override void OnUpdate() { _transport?.Drain(); } public override void OnDeinitializeMelon() { SLTAPI.Available -= Attach; SLTFusionMessage.Transport = null; } } public static class FusionAgentAuthority { public static bool CanDrive(NetworkEntity? entity) { if (!NetworkInfo.HasServer) { return true; } if (NetworkInfo.IsHost && entity != null && entity.IsRegistered && !entity.IsDestroyed) { return entity.IsOwner; } return false; } public static string AgentId(NetworkEntity entity, string sharedSpawnToken) { if (entity == null || !entity.IsRegistered || string.IsNullOrWhiteSpace(sharedSpawnToken) || sharedSpawnToken.Length > 48) { throw new ArgumentException("A registered entity and a shared per-spawn token are required"); } return "fusion:" + entity.ID + ":" + sharedSpawnToken; } } public sealed class SLTBlob : INetSerializable { public byte[] Bytes = Array.Empty<byte>(); public int? GetSize() { return 4 + Bytes.Length; } public void Serialize(INetSerializer serializer) { serializer.SerializeValue(ref Bytes); } } public sealed class SLTFusionMessage : ModuleMessageHandler { internal static SLTFusionTransport? Transport; protected override bool OnPreRelayMessage(ReceivedMessage received) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Invalid comparison between Unknown and I4 MessageRoute route = ((ReceivedMessage)(ref received)).Route; if ((int)((MessageRoute)(ref route)).Type != 1 || !Unwrap(((ReceivedMessage)(ref received)).Bytes, out byte[] bytes)) { return false; } SLTPacket val = default(SLTPacket); if (WireCodec.TryDecode(bytes, ref val)) { return (int)val.Kind == 1; } return false; } protected override void OnHandleMessage(ReceivedMessage received) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Invalid comparison between Unknown and I4 SLTFusionTransport transport = Transport; if (transport == null || !Unwrap(((ReceivedMessage)(ref received)).Bytes, out byte[] bytes)) { return; } bool flag = ((ReceivedMessage)(ref received)).Sender == 0; if (NetworkInfo.IsHost) { int num; if (((ReceivedMessage)(ref received)).IsServerHandled) { MessageRoute route = ((ReceivedMessage)(ref received)).Route; num = (((int)((MessageRoute)(ref route)).Type != 1) ? 1 : 0); } else { num = 1; } if (((uint)num | (flag ? 1u : 0u)) != 0 || !((ReceivedMessage)(ref received)).Sender.HasValue) { return; } } else if (!flag || ((ReceivedMessage)(ref received)).IsServerHandled) { return; } transport.Queue(bytes, flag, ((ReceivedMessage)(ref received)).Sender); } internal static bool Unwrap(byte[] source, out byte[] bytes) { bytes = Array.Empty<byte>(); if (source == null || source.Length < 4 || source.Length > 16388) { return false; } int num = BinaryPrimitives.ReadInt32BigEndian(source.AsSpan(0, 4)); if (num < 0 || num != source.Length - 4 || num > 16384) { return false; } bytes = source.AsSpan(4, num).ToArray(); return true; } } internal sealed class SLTFusionTransport : ISLTTransport { private readonly ConcurrentQueue<(byte[] bytes, bool host, byte? sender)> _incoming = new ConcurrentQueue<(byte[], bool, byte?)>(); private int _queued; public AuthorityMode Mode { get { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) try { return (AuthorityMode)(NetworkInfo.HasServer ? (NetworkInfo.IsHost ? 1 : 2) : 0); } catch { return (AuthorityMode)3; } } } public string Description => "Fusion ModuleMessage API; LabFusion " + typeof(NetworkInfo).Assembly.GetName().Version; public event Action<byte[], bool, byte?>? Received; internal void Queue(byte[] bytes, bool host, byte? sender) { if (Interlocked.Increment(ref _queued) > 64) { Interlocked.Decrement(ref _queued); } else { _incoming.Enqueue((bytes, host, sender)); } } internal void Drain() { int num = 0; (byte[], bool, byte?) result; while (num++ < 16 && _incoming.TryDequeue(out result)) { Interlocked.Decrement(ref _queued); this.Received?.Invoke(result.Item1, result.Item2, result.Item3); } } public void Broadcast(byte[] bytes) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (NetworkInfo.IsHost && bytes.Length <= 16384) { MessageRelay.RelayModule<SLTFusionMessage, SLTBlob>(new SLTBlob { Bytes = bytes }, CommonMessageRoutes.ReliableToClients); } } public void SendToHost(byte[] bytes) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (NetworkInfo.IsClient && bytes.Length <= 16384) { MessageRelay.RelayModule<SLTFusionMessage, SLTBlob>(new SLTBlob { Bytes = bytes }, CommonMessageRoutes.ReliableToServer); } } public void SendToPeer(byte peer, byte[] bytes) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (NetworkInfo.IsHost && peer != 0 && bytes.Length <= 16384) { MessageRelay.RelayModule<SLTFusionMessage, SLTBlob>(new SLTBlob { Bytes = bytes }, new MessageRoute(peer, (NetworkChannel)0)); } } } }
Mods/SLTCore.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text.Json; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSLZ.Marrow; using MelonLoader; using Microsoft.CodeAnalysis; using SLTCore; using SLTCore.Core; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(SLTMod), "SLTCore", "0.2.0", "CraftyDev", null)] [assembly: MelonGame("Stress Level Zero", "BONELAB")] [assembly: AssemblyVersion("0.2.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace SLTCore { public interface ISLTAgent { string Id { get; } V3 Feet { get; } AgentProfile Profile { get; } Transform Root { get; } bool HasMovementAuthority { get; } void OnNavigation(PathResult result); void OnReplicatedNavigation(PathResult result) { } void OnMapChanged(long revision) { } void OnAuthorityChanged(bool authoritative) { } } public interface ISLTTransport { AuthorityMode Mode { get; } string Description { get; } event Action<byte[], bool, byte?> Received; void Broadcast(byte[] bytes); void SendToHost(byte[] bytes); void SendToPeer(byte peer, byte[] bytes); } public static class SLTAPI { public const string Version = "0.2.0"; public const string FullName = "Sentry Logic Track Core"; public static SLTService? Service { get; internal set; } public static bool Ready => Service != null; public static event Action<SLTService>? Available; internal static void Announce(SLTService service) { Service = service; if (SLTAPI.Available == null) { return; } Delegate[] invocationList = SLTAPI.Available.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { Action<SLTService> action = (Action<SLTService>)invocationList[i]; try { action(service); } catch (Exception ex) { MelonLogger.Warning("SLTCore consumer startup failed: " + ex.Message); } } } } public sealed class SLTService { private sealed class Registration : IDisposable { private readonly SLTService _service; public readonly List<int> Ignored = new List<int>(); public ISLTAgent Agent { get; } public Registration(SLTService service, ISLTAgent agent) { _service = service; Agent = agent; } public void Dispose() { _service.Unregister(this); } } private sealed class Pending { public PathRequest Request; public SearchJob Job; public Action<PathResult> Callback; } private readonly int _thread = Environment.CurrentManagedThreadId; private readonly SLTConfig _config; private readonly Instance _log; private readonly string _directory; private readonly WorldMap _map; private readonly QueryBudget _budget = new QueryBudget(); private readonly ObstacleTracker _obstacles; private readonly UnityWorld _world; private readonly MapScheduler _mapping; private readonly Dictionary<string, Registration> _agents = new Dictionary<string, Registration>(StringComparer.Ordinal); private readonly List<Pending> _requests = new List<Pending>(); private readonly Queue<OpeningScan> _openingJobs = new Queue<OpeningScan>(); private readonly List<OpeningResult> _openings = new List<OpeningResult>(); private readonly List<V3> _foci = new List<V3>(); private readonly Dictionary<string, (V3 center, double expires)> _interests = new Dictionary<string, (V3, double)>(StringComparer.Ordinal); private readonly Dictionary<string, PathResult> _published = new Dictionary<string, PathResult>(StringComparer.Ordinal); private readonly Queue<(byte[] bytes, byte? peer)> _outgoing = new Queue<(byte[], byte?)>(); private readonly Dictionary<byte, double> _helloRates = new Dictionary<byte, double>(); private readonly ReplicaGate _replica = new ReplicaGate(); private ISLTTransport? _transport; private readonly AuthorityProbe _authority = new AuthorityProbe(); private AuthorityMode _mode = (AuthorityMode)3; private Guid _session = Guid.NewGuid(); private uint _sequence; private long _requestId; private int _jobCursor; private int _focusCursor; private double _nextFocus; private double _nextObstacle; private double _nextDiagnostic; private double _nextHello; private double _nextSurvey; private double _nextEvict; private double _nextNetworkWindow; private long _lastAnnouncedRevision; private int _networkBytes; private int _slowFrames; private int _saturations; private double _frameAverage; private double _nextInvalidate; private string _scene = "startup"; private double _now; private readonly List<int> _localRigIgnored = new List<int>(); private Transform? _lastLocalRig; public AuthorityMode Authority => _mode; public bool IsAuthoritative { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 AuthorityMode mode = _mode; return (int)mode == 1 || (int)mode == 0; } } public long Revision => _map.Revision; public int MappedSurfaces => _map.NodeCount; public int PendingColumns => _mapping.Pending; public event Action<long>? MapChanged; public event Action<ObstacleInfo>? ObstacleChanged; public event Action<OpeningResult>? OpeningObserved; public event Action<PathResult>? ReplicatedRoute; public SLTService(SLTConfig config, Instance log, string directory) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Expected O, but got Unknown _config = config; _log = log; _directory = directory; _map = new WorldMap(config.CellSize, config.BandHeight); _obstacles = new ObstacleTracker(config.MaxTrackedObstacles); _world = new UnityWorld(config, _budget, _obstacles); _mapping = new MapScheduler(_map, config); _obstacles.Dirty += InvalidateRegion; _obstacles.Changed += delegate(ObstacleInfo info) { Safely(delegate { this.ObstacleChanged?.Invoke(info); }); }; _budget.Reset(config.PhysicsQueriesPerFrame); } private void CheckThread() { if (Environment.CurrentManagedThreadId != _thread) { throw new InvalidOperationException("SLTCore APIs must be called on the Unity main thread"); } } public IDisposable RegisterAgent(ISLTAgent agent) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) CheckThread(); if (agent != null && !string.IsNullOrWhiteSpace(agent.Id) && agent.Id.Length <= 96 && agent.Profile.IsValid) { V3 feet = agent.Feet; if (((V3)(ref feet)).IsFinite) { if (_agents.ContainsKey(agent.Id)) { throw new InvalidOperationException("Agent ID is already registered: " + agent.Id); } if (_agents.Count >= _config.MaxRegisteredAgents) { throw new InvalidOperationException("Agent registration limit reached"); } Registration registration = new Registration(this, agent); if (Object.op_Implicit((Object)(object)agent.Root)) { foreach (Collider componentsInChild in ((Component)agent.Root).GetComponentsInChildren<Collider>(true)) { if (Object.op_Implicit((Object)(object)componentsInChild)) { registration.Ignored.Add(((Object)componentsInChild).GetInstanceID()); _obstacles.Ignore(componentsInChild, ignored: true); } } } _agents.Add(agent.Id, registration); _mapping.Endpoint(agent.Feet); Safely(delegate { agent.OnAuthorityChanged(IsAuthoritative && agent.HasMovementAuthority); }); return registration; } } throw new ArgumentException("Agent requires a stable ID, valid profile, and feet position"); } private void Unregister(Registration registration) { CheckThread(); if (!_agents.TryGetValue(registration.Agent.Id, out Registration value) || value != registration) { return; } CancelAgent(registration.Agent.Id); foreach (int item in registration.Ignored) { _obstacles.IgnoreId(item, ignored: false); } _agents.Remove(registration.Agent.Id); _published.Remove(registration.Agent.Id); } public long RequestPath(string agentId, V3 start, NavigationTarget target, AgentProfile profile, Action<PathResult> callback, bool allowPartial = false) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) CheckThread(); if (callback == null) { throw new ArgumentNullException("callback"); } V3 goal = default(V3); if (target == null || !target.TryGetPosition(ref goal)) { long id = ++_requestId; if (!string.IsNullOrWhiteSpace(agentId)) { CancelAgent(agentId); } Safely(delegate { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown callback(new PathResult(id, agentId ?? "", (PathStatus)12, Revision, (IReadOnlyList<Waypoint>)null, "The AI mod's chosen destination is unavailable")); }); return id; } return RequestPath(agentId, start, goal, profile, callback, allowPartial); } public long RequestPath(string agentId, V3 start, V3 goal, AgentProfile profile, Action<PathResult> callback, bool allowPartial = false) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Expected O, but got Unknown //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) CheckThread(); if (callback == null) { throw new ArgumentNullException("callback"); } long id = ++_requestId; PathRequest val = new PathRequest { RequestId = id, AgentId = agentId, Start = start, Goal = goal, Profile = profile, AllowPartial = allowPartial }; if (!val.IsValid) { Safely(delegate { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown callback(new PathResult(id, agentId ?? "", (PathStatus)4, Revision, (IReadOnlyList<Waypoint>)null, "")); }); return id; } if (!IsAuthoritative) { Safely(delegate { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown callback(new PathResult(id, agentId, (PathStatus)9, Revision, (IReadOnlyList<Waypoint>)null, "Only the authority plans executable routes")); }); return id; } if (!_agents.TryGetValue(agentId, out Registration value) || !value.Agent.HasMovementAuthority) { Safely(delegate { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown callback(new PathResult(id, agentId, (PathStatus)9, Revision, (IReadOnlyList<Waypoint>)null, "Register the NPC and verify its ownership first")); }); return id; } CancelAgent(agentId); if (_requests.Count >= _config.MaxQueuedPaths) { Safely(delegate { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown callback(new PathResult(id, agentId, (PathStatus)10, Revision, (IReadOnlyList<Waypoint>)null, "")); }); return id; } PathRequest val2 = val.Copy(); _requests.Add(new Pending { Request = val2, Job = new SearchJob(_map, (IWorldQuery)(object)_world, val2, _now, _config.MaxSearchVisits), Callback = callback }); _mapping.Endpoint(start); _mapping.Endpoint(goal); return id; } public void CancelAgent(string agentId) { CheckThread(); Pending[] array = _requests.Where((Pending r) => r.Request.AgentId == agentId).ToArray(); foreach (Pending pending in array) { _requests.Remove(pending); pending.Job.Cancel(); Safely(delegate { pending.Callback(pending.Job.Result); }); } } public LinkCheck ValidateNextSegment(V3 feet, Waypoint next, AgentProfile profile) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) CheckThread(); if (!IsAuthoritative) { return new LinkCheck((LinkState)0, (MoveKind)0, 0f); } MoveKind kind = ((Waypoint)(ref next)).Kind; if ((int)kind == 4 || (int)kind == 5 || (int)kind == 6 || (int)kind == 7) { return new LinkCheck((LinkState)0, ((Waypoint)(ref next)).Kind, 0f); } return _world.CheckTraversal(feet, ((Waypoint)(ref next)).Feet, profile); } public void RegisterTraversalLink(TraversalLink link) { CheckThread(); _map.AddLink(link); } public void SetInterestPoint(string id, V3 center, float lifetimeSeconds = 15f) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) CheckThread(); if (string.IsNullOrWhiteSpace(id) || id.Length > 96 || !((V3)(ref center)).IsFinite || ((V3)(ref center)).Length > 50000f || !float.IsFinite(lifetimeSeconds) || lifetimeSeconds < 1f || lifetimeSeconds > 60f) { throw new ArgumentException("Invalid interest point"); } if (_interests.Count >= 8 && !_interests.ContainsKey(id)) { throw new InvalidOperationException("Interest point limit reached"); } _interests[id] = (center, _now + (double)lifetimeSeconds); _mapping.Focus(center); _nextFocus = 0.0; } public void RemoveInterestPoint(string id) { CheckThread(); _interests.Remove(id); _nextFocus = 0.0; } public void RemoveTraversalLink(string id) { CheckThread(); _map.RemoveLink(id); } public void RegisterObstacle(Collider collider, string stableId, ObstacleKind kind, bool confirmedBreakable = false) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) CheckThread(); _obstacles.Register(collider, stableId, kind, confirmedBreakable); } public void UnregisterObstacle(string stableId) { CheckThread(); _obstacles.Unregister(stableId); } public IReadOnlyList<ObstacleInfo> GetObstacles(V3 center, float radius = 12f) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) CheckThread(); if (!((V3)(ref center)).IsFinite || !float.IsFinite(radius) || radius < 0f || radius > 50f) { throw new ArgumentException("Invalid query"); } return _obstacles.Nearby(center, radius); } public IReadOnlyList<OpeningResult> GetOpenings(V3 center, float radius = 12f) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) CheckThread(); return _openings.Where((OpeningResult o) => _now - o.ObservedAt < (double)_config.MaxMapAgeSeconds && V3.Distance(o.Center, center) <= radius).ToArray(); } public void ProbeOpening(V3 center, V3 normal, Action<OpeningResult> callback, float width = 3f, float height = 3f, float depth = 1f, float resolution = 0.15f) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) CheckThread(); if (callback == null) { throw new ArgumentNullException("callback"); } if (!IsAuthoritative) { throw new InvalidOperationException("Opening measurements run on the authority"); } if (_openingJobs.Count >= 8) { throw new InvalidOperationException("Opening probe queue is full"); } _openingJobs.Enqueue(new OpeningScan(center, normal, width, height, depth, resolution, callback)); } public void NotifyWorldChanged(Bounds bounds) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) CheckThread(); V3 val = ((Bounds)(ref bounds)).center.SLT(); if (((V3)(ref val)).IsFinite) { val = ((Bounds)(ref bounds)).size.SLT(); if (((V3)(ref val)).IsFinite) { Vector3 size = ((Bounds)(ref bounds)).size; if (!(((Vector3)(ref size)).sqrMagnitude > 10000f)) { InvalidateRegion(bounds); return; } } } throw new ArgumentException("Dirty bounds must be finite and local (size length <= 100 m)"); } private void InvalidateRegion(Bounds bounds) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) _mapping.Dirty(bounds); foreach (OpeningScan openingJob in _openingJobs) { openingJob.Invalidate(bounds); } _openings.RemoveAll(delegate(OpeningResult opening) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) Bounds val = bounds; ((Bounds)(ref val)).Expand(MathF.Max(opening.Width, opening.Height)); return ((Bounds)(ref val)).Contains(opening.Center.Unity()); }); } public V3 GetCrowdSeparation(string agentId, float range = 1.2f) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) CheckThread(); if (!_agents.TryGetValue(agentId, out Registration value) || !float.IsFinite(range) || range <= 0f || range > 5f) { return default(V3); } V3 val = default(V3); foreach (Registration value2 in _agents.Values) { if (value2 != value) { V3 val2 = value.Agent.Feet - value2.Agent.Feet; float horizontalLength = ((V3)(ref val2)).HorizontalLength; if (horizontalLength > 0.001f && horizontalLength < range && MathF.Abs(val2.Y) < 0.7f) { val += new V3(val2.X, 0f, val2.Z) / horizontalLength * (1f - horizontalLength / range); } } } if (!(((V3)(ref val)).Length > 1f)) { return val; } return ((V3)(ref val)).Normalized; } public bool? HasLineOfSight(V3 from, V3 to) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) CheckThread(); if (!((V3)(ref from)).IsFinite || !((V3)(ref to)).IsFinite || V3.Distance(from, to) > 100f) { return false; } if (!_budget.Take(1)) { return null; } V3 v = to - from; RaycastHit nearest; return ((V3)(ref v)).Length < 0.001f || !_world.Ray(from.Unity(), v.Unity() / ((V3)(ref v)).Length, ((V3)(ref v)).Length, out nearest); } public void AttachTransport(ISLTTransport transport) { CheckThread(); if (_transport != null) { _transport.Received -= Receive; } _transport = transport; _transport.Received += Receive; _nextHello = 0.0; _log.Msg("Replication transport attached: " + transport.Description); } public void SceneChanged(string scene) { CheckThread(); _scene = ((scene.Length <= 128) ? scene : scene.Substring(0, 128)); ResetNavigation(clearAgents: true); _nextFocus = 0.0; _nextHello = 0.0; } private void ResetNavigation(bool clearAgents) { Pending[] array = _requests.ToArray(); _requests.Clear(); _map.Clear(); _mapping.Clear(); _openingJobs.Clear(); _openings.Clear(); _foci.Clear(); _interests.Clear(); _published.Clear(); _outgoing.Clear(); _helloRates.Clear(); _session = Guid.NewGuid(); _sequence = 0u; _replica.Reset(_scene); _lastAnnouncedRevision = Revision; Pending[] array2 = array; foreach (Pending p in array2) { Safely(delegate { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown p.Callback(new PathResult(p.Request.RequestId, p.Request.AgentId, (PathStatus)9, Revision, (IReadOnlyList<Waypoint>)null, "Scene or authority changed")); }); } if (clearAgents) { _agents.Clear(); _obstacles.Clear(); _localRigIgnored.Clear(); _lastLocalRig = null; } } public unsafe void Tick() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Invalid comparison between Unknown and I4 //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Invalid comparison between Unknown and I4 //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_05a9: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_0741: Unknown result type (might be due to invalid IL or missing references) //IL_0747: Invalid comparison between Unknown and I4 //IL_061e: Unknown result type (might be due to invalid IL or missing references) //IL_0623: Unknown result type (might be due to invalid IL or missing references) //IL_074a: Unknown result type (might be due to invalid IL or missing references) //IL_074f: Unknown result type (might be due to invalid IL or missing references) //IL_0756: Unknown result type (might be due to invalid IL or missing references) //IL_0771: Expected O, but got Unknown //IL_0637: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_0344: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0353: Unknown result type (might be due to invalid IL or missing references) //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_0378: Unknown result type (might be due to invalid IL or missing references) //IL_0380: Unknown result type (might be due to invalid IL or missing references) CheckThread(); _now = Time.realtimeSinceStartupAsDouble; _obstacles.Now = _now; AuthorityMode val = _transport?.Mode ?? _authority.Read(_now); if (_transport == null && ((int)val == 1 || (int)val == 2)) { val = (AuthorityMode)3; } if (_mode != val) { _mode = val; ResetNavigation(clearAgents: false); _log.Msg("Navigation authority: " + ((object)(*(AuthorityMode*)(&val))/*cast due to .constrained prefix*/).ToString()); Registration[] array = _agents.Values.ToArray(); foreach (Registration reg in array) { Safely(delegate { reg.Agent.OnAuthorityChanged(IsAuthoritative && reg.Agent.HasMovementAuthority); }); } } if (!_config.Enabled) { return; } double num = _config.FrameBudgetMilliseconds * ((Time.unscaledDeltaTime > 0.022f) ? 0.55 : 1.0); Stopwatch stopwatch = Stopwatch.StartNew(); _budget.Reset(_config.PhysicsQueriesPerFrame); RefreshLocalRigIgnore(); if (IsAuthoritative) { V3 feet; if (_now >= _nextFocus) { _nextFocus = _now + 2.0; _foci.Clear(); Registration[] array2 = _agents.Values.ToArray(); int num2; for (num2 = 0; num2 < array2.Length; num2++) { if (_foci.Count >= 7) { break; } Registration reg2 = array2[(_focusCursor + num2) % array2.Length]; if (Object.op_Implicit((Object)(object)reg2.Agent.Root)) { feet = reg2.Agent.Feet; if (((V3)(ref feet)).IsFinite && !_foci.Any((V3 f) => V3.Distance(f, reg2.Agent.Feet) < 2f)) { _foci.Add(reg2.Agent.Feet); } } } if (array2.Length != 0) { _focusCursor = (_focusCursor + Math.Max(1, num2)) % array2.Length; } string[] array3 = (from p in _interests where p.Value.expires <= _now select p.Key).ToArray(); foreach (string key in array3) { _interests.Remove(key); } foreach (var value in _interests.Values) { _foci.Add(value.center); } Camera main = Camera.main; if (Object.op_Implicit((Object)(object)main)) { _foci.Add((((Component)main).transform.position - Vector3.up * 1.5f).SLT()); } foreach (V3 focus in _foci) { _mapping.Focus(focus); } } if (_now >= _nextObstacle) { _nextObstacle = _now + 0.25; _obstacles.Tick(); } _budget.SetLimit(_config.ScanQueriesPerFrame); _mapping.Tick(_world, _now, num * 0.45); _budget.SetLimit(_config.PhysicsQueriesPerFrame - _config.MovementQueryReserve); TickPaths(stopwatch, num * 0.85); if (_openingJobs.TryPeek(out OpeningScan opening) && stopwatch.Elapsed.TotalMilliseconds < num && opening.Step(_world, _now, Math.Max(0.02, num - stopwatch.Elapsed.TotalMilliseconds))) { _openingJobs.Dequeue(); OpeningResult result = opening.Result; if (result.Found) { if (_openings.Count >= 128) { _openings.RemoveAt(0); } _openings.Add(result); } Safely(delegate { opening.Callback(result); }); Safely(delegate { this.OpeningObserved?.Invoke(result); }); } if (_now >= _nextSurvey && _openingJobs.Count < 2 && _foci.Count > 0 && stopwatch.Elapsed.TotalMilliseconds < num) { _nextSurvey = _now + 2.0; Survey(_foci[(int)_now % _foci.Count]); } if (_now >= _nextEvict) { _nextEvict = _now + 5.0; List<V3> list = new List<V3>(_foci); foreach (Registration value2 in _agents.Values) { if (Object.op_Implicit((Object)(object)value2.Agent.Root)) { feet = value2.Agent.Feet; if (((V3)(ref feet)).IsFinite) { list.Add(value2.Agent.Feet); } } } _map.Evict(_now, (double)_config.MaxMapAgeSeconds, (IReadOnlyList<V3>)list, _config.ScanRadius + 8f, _config.MaxColumns); } if (Revision != _lastAnnouncedRevision && _now >= _nextInvalidate) { _nextInvalidate = _now + 0.5; _lastAnnouncedRevision = Revision; Safely(delegate { this.MapChanged?.Invoke(Revision); }); Registration[] array = _agents.Values.ToArray(); foreach (Registration reg3 in array) { Safely(delegate { reg3.Agent.OnMapChanged(Revision); }); } if ((int)_mode == 1) { EnqueuePacket(new SLTPacket { Kind = (PacketKind)4, Revision = Revision }); } } } _budget.SetLimit(_config.PhysicsQueriesPerFrame); TickNetwork(); double totalMilliseconds = stopwatch.Elapsed.TotalMilliseconds; _frameAverage = ((_frameAverage == 0.0) ? totalMilliseconds : (_frameAverage * 0.97 + totalMilliseconds * 0.03)); if (totalMilliseconds > num * 2.0) { _slowFrames++; } if (_budget.Saturated) { _saturations++; } if (_config.WriteDiagnostics && _now >= _nextDiagnostic) { _nextDiagnostic = _now + 15.0; WriteDiagnostics(); } } private void TickPaths(Stopwatch clock, double limit) { //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Invalid comparison between Unknown and I4 //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Expected O, but got Unknown int num = 0; while (_requests.Count > 0 && num < _config.MaxConcurrentPaths && clock.Elapsed.TotalMilliseconds < limit) { _jobCursor %= _requests.Count; Pending pending = _requests[_jobCursor]; num++; if (!_agents.TryGetValue(pending.Request.AgentId, out Registration agent) || !agent.Agent.HasMovementAuthority) { _requests.RemoveAt(_jobCursor); Safely(delegate { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown pending.Callback(new PathResult(pending.Request.RequestId, pending.Request.AgentId, (PathStatus)9, Revision, (IReadOnlyList<Waypoint>)null, "")); }); continue; } pending.Job.Step(_now, (double)_config.MaxMapAgeSeconds, 8, Math.Min(0.25, Math.Max(0.02, limit - clock.Elapsed.TotalMilliseconds))); if (!pending.Job.Done) { _jobCursor++; continue; } _requests.RemoveAt(_jobCursor); PathResult result = pending.Job.Result; _published[result.AgentId] = result; Safely(delegate { pending.Callback(result); }); Safely(delegate { agent.Agent.OnNavigation(result); }); if ((int)_mode == 1) { EnqueuePacket(new SLTPacket { Kind = (PacketKind)3, Route = result, Revision = Revision }); } } if (_requests.Count > 0) { _jobCursor = (_jobCursor + 1) % _requests.Count; } } private void RefreshLocalRigIgnore() { Camera main = Camera.main; if (!Object.op_Implicit((Object)(object)main)) { return; } RigManager componentInParent = ((Component)main).GetComponentInParent<RigManager>(); if (!Object.op_Implicit((Object)(object)componentInParent) || (Object)(object)_lastLocalRig == (Object)(object)((Component)componentInParent).transform) { return; } foreach (int item in _localRigIgnored) { _obstacles.IgnoreId(item, ignored: false); } _localRigIgnored.Clear(); _lastLocalRig = ((Component)componentInParent).transform; foreach (Collider componentsInChild in ((Component)componentInParent).GetComponentsInChildren<Collider>(true)) { if (Object.op_Implicit((Object)(object)componentsInChild)) { _localRigIgnored.Add(((Object)componentsInChild).GetInstanceID()); _obstacles.Ignore(componentsInChild, ignored: true); } } } private void Survey(V3 feet) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02ed: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) if (!_budget.Take(16)) { return; } Vector3 val = feet.Unity(); Vector3[] array = (Vector3[])(object)new Vector3[4] { Vector3.forward, Vector3.right, Vector3.back, Vector3.left }; RaycastHit nearest2; foreach (Vector3 val2 in array) { RaycastHit nearest; bool flag = _world.Ray(val + Vector3.up * 0.35f, val2, 3f, out nearest); bool num = _world.Ray(val + Vector3.up * 1.35f, val2, 3f, out nearest2); RaycastHit nearest3; bool flag2 = _world.Ray(val + Vector3.up * 2.5f, val2, 3f, out nearest3); if (!num && ((flag && Object.op_Implicit((Object)(object)((RaycastHit)(ref nearest)).collider)) || (flag2 && Object.op_Implicit((Object)(object)((RaycastHit)(ref nearest3)).collider)))) { RaycastHit val3 = ((flag && Object.op_Implicit((Object)(object)((RaycastHit)(ref nearest)).collider)) ? nearest : nearest3); Vector3 v = val + val2 * ((RaycastHit)(ref val3)).distance + Vector3.up * 1.35f; ProbeOpening(v.SLT(), ((RaycastHit)(ref val3)).normal.SLT(), delegate { }, 3f, 3f, 0.6f); return; } Vector3 val4 = val + val2 * 1.1f; if (!_world.Support(val4, 0.3f, 2f, 65f, out nearest2)) { ProbeOpening(val4.SLT(), Vector3.up.SLT(), delegate { }, 3f, 3f, 0.4f); return; } } if (_world.Ray(val + Vector3.up * 0.4f, Vector3.up, 5f, out var nearest4) && Object.op_Implicit((Object)(object)((RaycastHit)(ref nearest4)).collider)) { Vector3 val5 = val + Vector3.right; if (!_world.Ray(val5 + Vector3.up * 0.4f, Vector3.up, 5f, out nearest2)) { ProbeOpening(new V3(val5.x, ((RaycastHit)(ref nearest4)).point.y, val5.z), Vector3.down.SLT(), delegate { }, 3f, 3f, 0.6f); } } } private void TickNetwork() { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Invalid comparison between Unknown and I4 //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown if (_transport == null) { return; } AuthorityMode mode = _mode; if ((int)mode == 0 || (int)mode == 3) { return; } if (_now >= _nextHello) { _nextHello = _now + 3.0; if ((int)_mode == 1) { EnqueuePacket(new SLTPacket { Kind = (PacketKind)2, Revision = Revision }); } else { _transport.SendToHost(WireCodec.Encode(new SLTPacket { Kind = (PacketKind)1, Scene = _scene })); } } if (_now >= _nextNetworkWindow) { _nextNetworkWindow = _now + 1.0; _networkBytes = 0; } (byte[], byte?) result; while (_outgoing.TryPeek(out result) && _networkBytes + result.Item1.Length <= _config.MaxNetworkBytesPerSecond) { _outgoing.Dequeue(); _networkBytes += result.Item1.Length; if (result.Item2.HasValue) { _transport.SendToPeer(result.Item2.Value, result.Item1); } else { _transport.Broadcast(result.Item1); } } } private void EnqueuePacket(SLTPacket packet, byte? target = null) { packet.Scene = _scene; packet.Session = _session; packet.Sequence = ++_sequence; if (_outgoing.Count >= 64) { _outgoing.Dequeue(); } try { _outgoing.Enqueue((WireCodec.Encode(packet), target)); } catch (ArgumentException ex) { _log.Warning("Replication payload rejected: " + ex.Message); } } private void Receive(byte[] bytes, bool fromHost, byte? sender) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Invalid comparison between Unknown and I4 //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Invalid comparison between Unknown and I4 //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Invalid comparison between Unknown and I4 //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Invalid comparison between Unknown and I4 //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Invalid comparison between Unknown and I4 //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown CheckThread(); SLTPacket packet = default(SLTPacket); if (!WireCodec.TryDecode(bytes, ref packet) || packet.Scene != _scene) { return; } if ((int)_mode == 1 && (int)packet.Kind == 1 && sender.HasValue) { if (_helloRates.TryGetValue(sender.Value, out var value) && _now - value < 2.0) { return; } _helloRates[sender.Value] = _now; EnqueuePacket(new SLTPacket { Kind = (PacketKind)2, Revision = Revision }, sender); { foreach (PathResult value2 in _published.Values) { EnqueuePacket(new SLTPacket { Kind = (PacketKind)3, Route = value2, Revision = Revision }, sender); } return; } } if ((int)_mode != 2 || !_replica.Accept(packet, fromHost)) { return; } if ((int)packet.Kind == 3 && packet.Route != null) { PathResult route = packet.Route; if (_agents.TryGetValue(route.AgentId, out Registration agent)) { Safely(delegate { agent.Agent.OnReplicatedNavigation(route); }); } Safely(delegate { this.ReplicatedRoute?.Invoke(route); }); } else if ((int)packet.Kind == 4) { Safely(delegate { this.MapChanged?.Invoke(packet.Revision); }); } } private void Safely(Action callback) { try { callback(); } catch (Exception ex) { _log.Warning("Consumer callback failed: " + ex.GetType().Name + ": " + ex.Message); } } public void WriteDiagnostics() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) CheckThread(); try { var value = new { version = "0.2.0", releaseStatus = "Compiled preview; headset verification required", gameVersion = Application.version, unityVersion = Application.unityVersion, platform = ((object)Application.platform/*cast due to .constrained prefix*/).ToString(), scene = _scene, authority = ((object)Unsafe.As<AuthorityMode, AuthorityMode>(ref _mode)/*cast due to .constrained prefix*/).ToString(), transport = (_transport?.Description ?? "None"), runtime = RuntimeInformation.FrameworkDescription, architecture = RuntimeInformation.ProcessArchitecture.ToString(), bonelibRequired = false, assemblies = (from a in (from a in AppDomain.CurrentDomain.GetAssemblies() select a.GetName()).Where(delegate(AssemblyName a) { string name = a.Name; int num; switch (name) { default: num = ((!(name == "SLTCore.Fusion")) ? 1 : 0); break; case "MelonLoader": case "LabFusion": case "BoneLib": case "SLTCore": num = 0; break; } return num == 0; }) group a by a.Name).ToDictionary((IGrouping<string, AssemblyName> g) => g.Key, (IGrouping<string, AssemblyName> g) => string.Join(", ", g.Select((AssemblyName a) => a.Version?.ToString()).Distinct())), mappedSurfaces = _map.NodeCount, columns = _map.ColumnCount, queuedColumns = _mapping.Pending, pendingPaths = _requests.Count, registeredAgents = _agents.Count, trackedObstacles = _obstacles.Count, openingProbes = _openingJobs.Count, observedOpenings = _openings.Count, mapRevision = Revision, meanFrameWorkMs = _frameAverage, budgetOverruns = _slowFrames, saturatedPhysicsBuffers = _saturations, physicsQueryReservationsLastFrame = _budget.Used }; File.WriteAllText(Path.Combine(_directory, "diagnostics.json"), JsonSerializer.Serialize(value, SLTConfig.Json)); } catch (Exception ex) { _log.Warning("Could not write diagnostics: " + ex.Message); } } internal void Shutdown() { ResetNavigation(clearAgents: true); if (_transport != null) { _transport.Received -= Receive; } } } internal sealed class AuthorityProbe { private double _next; private AuthorityMode _cached; public AuthorityMode Read(double now) { //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) if (now < _next) { return _cached; } _next = now + 0.5; try { Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "LabFusion"); if (assembly == null) { AuthorityMode result = (AuthorityMode)0; _cached = (AuthorityMode)0; return result; } Type type = assembly.GetType("LabFusion.Network.NetworkInfo"); AuthorityMode result2; if (type == null) { result2 = (AuthorityMode)3; _cached = (AuthorityMode)3; return result2; } object obj = Read("HasServer"); if (!(obj is bool)) { result2 = (AuthorityMode)3; _cached = (AuthorityMode)3; return result2; } if (!(bool)obj) { result2 = (AuthorityMode)0; _cached = (AuthorityMode)0; return result2; } if (!((Read("IsHost") ?? Read("IsServer")) is bool flag)) { result2 = (AuthorityMode)3; _cached = (AuthorityMode)3; return result2; } int num = (flag ? 1 : 2); result2 = (AuthorityMode)num; _cached = (AuthorityMode)num; return result2; object? Read(string name) { object obj3 = type.GetProperty(name, BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj3 == null) { FieldInfo? field = type.GetField(name, BindingFlags.Static | BindingFlags.Public); if ((object)field == null) { return null; } obj3 = field.GetValue(null); } return obj3; } } catch { AuthorityMode result2 = (AuthorityMode)3; _cached = (AuthorityMode)3; return result2; } } } internal static class UnityConvert { public static Vector3 Unity(this V3 v) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(v.X, v.Y, v.Z); } public static V3 SLT(this Vector3 v) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new V3(v.x, v.y, v.z); } } internal sealed class UnityWorld : IWorldQuery { internal readonly SLTConfig Config; internal readonly QueryBudget Budget; internal readonly ObstacleTracker Obstacles; private readonly Il2CppStructArray<RaycastHit> _hits = new Il2CppStructArray<RaycastHit>(48L); private readonly Il2CppReferenceArray<Collider> _overlaps = new Il2CppReferenceArray<Collider>(48L); internal const float Skin = 0.045f; public UnityWorld(SLTConfig config, QueryBudget budget, ObstacleTracker obstacles) { Config = config; Budget = budget; Obstacles = obstacles; } internal bool Ignored(Collider c) { if (Object.op_Implicit((Object)(object)c) && c.enabled && !c.isTrigger) { return Obstacles.IsIgnored(c); } return true; } internal bool Ray(Vector3 from, Vector3 direction, float distance, out RaycastHit nearest, int? mask = null) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) nearest = default(RaycastHit); int num = Physics.RaycastNonAlloc(from, direction, _hits, distance, mask ?? Config.CollisionMask, (QueryTriggerInteraction)1); if (num == ((Il2CppArrayBase<RaycastHit>)(object)_hits).Length) { Budget.Saturated = true; return true; } float num2 = float.MaxValue; bool result = false; for (int i = 0; i < num; i++) { RaycastHit val = ((Il2CppArrayBase<RaycastHit>)(object)_hits)[i]; if (!Ignored(((RaycastHit)(ref val)).collider)) { Obstacles.Observe(((RaycastHit)(ref val)).collider); if (((RaycastHit)(ref val)).distance < num2) { nearest = val; num2 = ((RaycastHit)(ref val)).distance; result = true; } } } return result; } internal bool BodyClear(Vector3 feet, float radius, float height, float lift = 0f) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) float num = radius + 0.045f + lift; float num2 = MathF.Max(num, height - radius + lift); int num3 = Physics.OverlapCapsuleNonAlloc(feet + Vector3.up * num, feet + Vector3.up * num2, radius, _overlaps, Config.CollisionMask, (QueryTriggerInteraction)1); if (num3 == ((Il2CppArrayBase<Collider>)(object)_overlaps).Length) { Budget.Saturated = true; return false; } bool result = true; for (int i = 0; i < num3; i++) { Collider c = ((Il2CppArrayBase<Collider>)(object)_overlaps)[i]; if (!Ignored(c)) { Obstacles.Observe(c); result = false; } } return result; } private bool Sweep(Vector3 feet, Vector3 destination, float radius, float height, float lift) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) Vector3 val = destination - feet; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude < 0.001f) { return true; } float num = radius + 0.045f + lift; float num2 = MathF.Max(num, height - radius + lift); int num3 = Physics.CapsuleCastNonAlloc(feet + Vector3.up * num, feet + Vector3.up * num2, radius, val / magnitude, _hits, magnitude, Config.CollisionMask, (QueryTriggerInteraction)1); if (num3 == ((Il2CppArrayBase<RaycastHit>)(object)_hits).Length) { Budget.Saturated = true; return false; } for (int i = 0; i < num3; i++) { RaycastHit val2 = ((Il2CppArrayBase<RaycastHit>)(object)_hits)[i]; if (!Ignored(((RaycastHit)(ref val2)).collider)) { Obstacles.Observe(((RaycastHit)(ref val2)).collider); return false; } } return true; } internal bool Support(Vector3 p, float above, float below, float slope, out RaycastHit hit) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (Ray(p + Vector3.up * above, Vector3.down, above + below, out hit, Config.FloorMask) && Object.op_Implicit((Object)(object)((RaycastHit)(ref hit)).collider) && ((RaycastHit)(ref hit)).normal.y >= MathF.Cos(slope * (float)Math.PI / 180f)) { if (!Config.AllowDynamicFloors && Object.op_Implicit((Object)(object)((RaycastHit)(ref hit)).collider.attachedRigidbody)) { return ((RaycastHit)(ref hit)).collider.attachedRigidbody.isKinematic; } return true; } return false; } public LinkCheck CheckTraversal(V3 from, V3 to, AgentProfile p) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_03f2: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_0404: Unknown result type (might be due to invalid IL or missing references) //IL_0407: Invalid comparison between Unknown and I4 //IL_037d: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_035a: Unknown result type (might be due to invalid IL or missing references) //IL_035c: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0416: Unknown result type (might be due to invalid IL or missing references) //IL_03d4: Unknown result type (might be due to invalid IL or missing references) //IL_038e: Unknown result type (might be due to invalid IL or missing references) //IL_03ca: Unknown result type (might be due to invalid IL or missing references) if (!p.IsValid || !((V3)(ref from)).IsFinite || !((V3)(ref to)).IsFinite) { return new LinkCheck((LinkState)0, (MoveKind)0, 0f); } V3 val = to - from; float horizontalLength = ((V3)(ref val)).HorizontalLength; if (horizontalLength > 2.5f || MathF.Abs(val.Y) > MathF.Max(p.MaxDrop, 2f)) { return new LinkCheck((LinkState)0, (MoveKind)0, 0f); } int num = Math.Max(1, (int)MathF.Ceiling(horizontalLength / MathF.Min(0.18f, p.Radius))); int count = (num + 1) * 3 + 7; if (!Budget.Take(count)) { return new LinkCheck((LinkState)2, (MoveKind)0, 0f); } Vector3 val2 = from.Unity(); Vector3 val3 = to.Unity(); float lift = p.Radius * 0.35f; bool num2 = BodyClear(val2, p.Radius, p.Height, lift) && BodyClear(val3, p.Radius, p.Height, lift); bool flag = !num2; float height = (num2 ? p.Height : p.CrouchHeight); if (flag && (!p.CanCrouch || !BodyClear(val2, p.Radius, height, lift) || !BodyClear(val3, p.Radius, height, lift))) { return new LinkCheck((LinkState)0, (MoveKind)0, 0f); } float y = val.Y; MoveKind val4 = (MoveKind)(flag ? 1 : 0); bool num3 = y > 0.06f && y <= p.StepHeight + 0.01f; bool flag2 = y < -0.06f && 0f - y <= p.MaxDrop + 0.01f; Vector3 val5 = val2; Vector3 val6 = val3; if (num3) { val5 += Vector3.up * y; if (!Sweep(val2, val5, p.Radius, height, lift) || !BodyClear(val5, p.Radius, height, lift)) { return new LinkCheck((LinkState)0, (MoveKind)0, 0f); } if (!flag) { val4 = (MoveKind)2; } } else if (flag2) { val6 += Vector3.up * (0f - y); if (!Sweep(val6, val3, p.Radius, height, lift) || !BodyClear(val6, p.Radius, height, lift)) { return new LinkCheck((LinkState)0, (MoveKind)0, 0f); } if (!flag) { val4 = (MoveKind)3; } } if (!Sweep(val5, val6, p.Radius, height, lift)) { return new LinkCheck((LinkState)0, (MoveKind)0, 0f); } Vector3 val7 = (Vector3)((horizontalLength > 0.001f) ? (new Vector3((0f - val.Z) / horizontalLength, 0f, val.X / horizontalLength) * p.Radius * 0.75f) : new Vector3(p.Radius * 0.75f, 0f, 0f)); float? num4 = null; for (int i = 0; i <= num; i++) { Vector3 val8 = Vector3.Lerp(val2, val3, (float)i / (float)num); float above = p.StepHeight + 0.12f; float below = MathF.Max(0.18f, flag2 ? (0f - y + 0.05f) : 0.18f); if (!Support(val8, above, below, p.MaxSlopeDegrees, out var hit) || !Support(val8 + val7, above, below, p.MaxSlopeDegrees, out var hit2) || !Support(val8 - val7, above, below, p.MaxSlopeDegrees, out hit2)) { return new LinkCheck((LinkState)0, (MoveKind)0, 0f); } if (num4.HasValue) { float num5 = ((RaycastHit)(ref hit)).point.y - num4.Value; if (num5 > p.StepHeight + 0.025f || 0f - num5 > p.MaxDrop + 0.025f) { return new LinkCheck((LinkState)0, (MoveKind)0, 0f); } } num4 = ((RaycastHit)(ref hit)).point.y; } return new LinkCheck((LinkState)1, val4, (flag ? 0.18f : 0f) + (((int)val4 == 3) ? 0.35f : 0f)); } internal RaycastHit[] ColumnHits(ColumnKey key, WorldMap map, out bool overflow) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) Vector3 val = map.ColumnCenter(key).Unity(); val.y = (float)(((ColumnKey)(ref key)).Band + 1) * map.BandHeight + 0.02f; int num = Physics.RaycastNonAlloc(val, Vector3.down, _hits, map.BandHeight + 0.04f, Config.FloorMask, (QueryTriggerInteraction)1); overflow = num == ((Il2CppArrayBase<RaycastHit>)(object)_hits).Length; if (overflow) { Budget.Saturated = true; return Array.Empty<RaycastHit>(); } List<RaycastHit> list = new List<RaycastHit>(num); for (int i = 0; i < num; i++) { RaycastHit item = ((Il2CppArrayBase<RaycastHit>)(object)_hits)[i]; if (!Ignored(((RaycastHit)(ref item)).collider) && !(((RaycastHit)(ref item)).normal.y < 0.42f) && !(map.ColumnAt(((RaycastHit)(ref item)).point.SLT()) != key)) { Obstacles.Observe(((RaycastHit)(ref item)).collider); list.Add(item); } } list.Sort((RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).point.y.CompareTo(((RaycastHit)(ref b)).point.y)); return list.ToArray(); } internal Surface? SurfaceAt(RaycastHit hit, WorldMap map) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)((RaycastHit)(ref hit)).collider)) { return null; } Vector3 point = ((RaycastHit)(ref hit)).point; Rigidbody attachedRigidbody = ((RaycastHit)(ref hit)).collider.attachedRigidbody; bool flag = Object.op_Implicit((Object)(object)attachedRigidbody) && !attachedRigidbody.isKinematic; if (flag && !Config.AllowDynamicFloors) { return null; } float minimumMappedRadius = Config.MinimumMappedRadius; if (!BodyClear(point, minimumMappedRadius, Config.MinimumMappedHeight, minimumMappedRadius * 0.35f)) { return null; } Vector3[] array = (Vector3[])(object)new Vector3[4] { Vector3.right * minimumMappedRadius, Vector3.left * minimumMappedRadius, Vector3.forward * minimumMappedRadius, Vector3.back * minimumMappedRadius }; foreach (Vector3 val in array) { if (!Support(point + val, 0.25f, 0.2f, 65f, out var _)) { return null; } } float num = Config.MaxMeasuredHeadroom; if (Ray(point + Vector3.up * 0.025f, Vector3.up, num, out var nearest)) { if (!Object.op_Implicit((Object)(object)((RaycastHit)(ref nearest)).collider)) { return null; } num = ((RaycastHit)(ref nearest)).distance + 0.025f; } return new Surface(map.KeyAt(point.SLT()), point.SLT(), ((RaycastHit)(ref hit)).normal.y, num, flag); } internal bool OpeningPixelFree(Vector3 point, Vector3 normal, float radius, float depth) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) Vector3 val = point - normal * depth * 0.5f; int num = Physics.OverlapSphereNonAlloc(val, radius, _overlaps, Config.CollisionMask, (QueryTriggerInteraction)1); if (num == ((Il2CppArrayBase<Collider>)(object)_overlaps).Length) { Budget.Saturated = true; return false; } for (int i = 0; i < num; i++) { if (!Ignored(((Il2CppArrayBase<Collider>)(object)_overlaps)[i])) { return false; } } num = Physics.SphereCastNonAlloc(val, radius, normal, _hits, depth, Config.CollisionMask, (QueryTriggerInteraction)1); if (num == ((Il2CppArrayBase<RaycastHit>)(object)_hits).Length) { Budget.Saturated = true; return false; } for (int j = 0; j < num; j++) { RaycastHit val2 = ((Il2CppArrayBase<RaycastHit>)(object)_hits)[j]; if (!Ignored(((RaycastHit)(ref val2)).collider)) { ObstacleTracker obstacles = Obstacles; val2 = ((Il2CppArrayBase<RaycastHit>)(object)_hits)[j]; obstacles.Observe(((RaycastHit)(ref val2)).collider); return false; } } return true; } } internal sealed class ColumnScan { private readonly ColumnKey _key; private RaycastHit[]? _hits; private int _index; private readonly List<Surface> _surfaces = new List<Surface>(); public ColumnScan(ColumnKey key) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) _key = key; } public bool Step(UnityWorld world, WorldMap map, double now) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) if (_hits == null) { if (!world.Budget.Take(1)) { return false; } _hits = world.ColumnHits(_key, map, out var _); } while (_index < _hits.Length && _surfaces.Count < 24) { if (!world.Budget.Take(6)) { return false; } Surface val = world.SurfaceAt(_hits[_index++], map); if (val != null) { _surfaces.Add(val); } } map.Replace(_key, _surfaces, now); return true; } } public sealed class ObstacleInfo { public string Id { get; internal set; } = ""; public V3 Center { get; internal set; } public V3 Size { get; internal set; } public ObstacleKind Kind { get; internal set; } public bool ConfirmedBreakable { get; internal set; } public bool IsActive { get; internal set; } public double ObservedAt { get; internal set; } } internal sealed class ObstacleTracker { private sealed class Entry { public Collider Collider; public ObstacleInfo Info = new ObstacleInfo(); public Bounds Last; public Quaternion Rotation; public double LastSeen; public bool Persistent; } private readonly Dictionary<int, Entry> _tracked = new Dictionary<int, Entry>(); private readonly Dictionary<int, double> _checked = new Dictionary<int, double>(); private readonly Dictionary<int, int> _ignored = new Dictionary<int, int>(); private readonly int _limit; private int _cursor; public double Now { get; set; } public int Count => _tracked.Count; public event Action<Bounds>? Dirty; public event Action<ObstacleInfo>? Changed; public ObstacleTracker(int limit) { _limit = limit; } public bool IsIgnored(Collider c) { if (Object.op_Implicit((Object)(object)c)) { return _ignored.ContainsKey(((Object)c).GetInstanceID()); } return false; } public void Ignore(Collider c, bool ignored) { if (Object.op_Implicit((Object)(object)c)) { IgnoreId(((Object)c).GetInstanceID(), ignored); } } public void IgnoreId(int id, bool ignored) { _ignored.TryGetValue(id, out var value); if (ignored) { _ignored[id] = value + 1; _tracked.Remove(id); } else if (value <= 1) { _ignored.Remove(id); } else { _ignored[id] = value - 1; } } public void Observe(Collider c) { if (!Object.op_Implicit((Object)(object)c) || IsIgnored(c)) { return; } int instanceID = ((Object)c).GetInstanceID(); double value2; if (_tracked.TryGetValue(instanceID, out Entry value)) { value.LastSeen = Now; } else if (_tracked.Count < _limit && (!_checked.TryGetValue(instanceID, out value2) || !(Now - value2 < 5.0))) { if (_checked.Count >= _limit * 4) { _checked.Clear(); } _checked[instanceID] = Now; bool num = Object.op_Implicit((Object)(object)c.attachedRigidbody); ObjectDestructible componentInParent = ((Component)c).GetComponentInParent<ObjectDestructible>(); if (num || Object.op_Implicit((Object)(object)componentInParent)) { Track(c, "local:" + instanceID, (ObstacleKind)((!Object.op_Implicit((Object)(object)componentInParent)) ? 1 : 3), Object.op_Implicit((Object)(object)componentInParent)); } } } public void Register(Collider collider, string stableId, ObstacleKind kind, bool confirmedBreakable) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)collider) || string.IsNullOrWhiteSpace(stableId) || stableId.Length > 96) { throw new ArgumentException("Invalid obstacle registration"); } if (_tracked.Count >= _limit && !_tracked.ContainsKey(((Object)collider).GetInstanceID())) { throw new InvalidOperationException("Obstacle registration limit reached"); } Track(collider, stableId, kind, confirmedBreakable); _tracked[((Object)collider).GetInstanceID()].Persistent = true; } private void Track(Collider c, string id, ObstacleKind kind, bool confirmed) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) if (_tracked.Count < _limit || _tracked.ContainsKey(((Object)c).GetInstanceID())) { Bounds bounds = c.bounds; _tracked[((Object)c).GetInstanceID()] = new Entry { Collider = c, Last = bounds, Rotation = ((Component)c).transform.rotation, LastSeen = Now, Info = new ObstacleInfo { Id = id, Center = ((Bounds)(ref bounds)).center.SLT(), Size = ((Bounds)(ref bounds)).size.SLT(), Kind = kind, ConfirmedBreakable = confirmed, IsActive = (c.enabled && ((Component)c).gameObject.activeInHierarchy), ObservedAt = Now } }; } } public void Tick(int max = 32) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) int num = 0; int[] array = _tracked.Keys.ToArray(); if (array.Length == 0) { return; } int num2 = _cursor % array.Length; int num3 = 0; while (num3 < array.Length && num < max) { int key = array[(num2 + num3) % array.Length]; Entry entry = _tracked[key]; Collider collider = entry.Collider; bool flag = Object.op_Implicit((Object)(object)collider) && collider.enabled && ((Component)collider).gameObject.activeInHierarchy; Bounds val = (flag ? collider.bounds : entry.Last); Vector3 val2 = ((Bounds)(ref val)).center - ((Bounds)(ref entry.Last)).center; int num4; if (!(((Vector3)(ref val2)).sqrMagnitude > 0.0009f)) { val2 = ((Bounds)(ref val)).size - ((Bounds)(ref entry.Last)).size; if (!(((Vector3)(ref val2)).sqrMagnitude > 0.0009f)) { num4 = ((flag && Quaternion.Angle(((Component)collider).transform.rotation, entry.Rotation) > 2f) ? 1 : 0); goto IL_00ff; } } num4 = 1; goto IL_00ff; IL_00ff: bool flag2 = (byte)num4 != 0; if (flag != entry.Info.IsActive || flag2) { Bounds last = entry.Last; ((Bounds)(ref last)).Encapsulate(val); ((Bounds)(ref last)).Expand(0.75f); this.Dirty?.Invoke(last); entry.Last = val; entry.Info.Center = ((Bounds)(ref val)).center.SLT(); entry.Info.Size = ((Bounds)(ref val)).size.SLT(); entry.Info.IsActive = flag; entry.Info.ObservedAt = Now; if (flag) { entry.Rotation = ((Component)collider).transform.rotation; } this.Changed?.Invoke(entry.Info); } if (!Object.op_Implicit((Object)(object)collider) || (Now - entry.LastSeen > 45.0 && !entry.Persistent)) { _tracked.Remove(key); } num3++; num++; } _cursor = num2 + num; } public void Unregister(string stableId) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) KeyValuePair<int, Entry>[] array = _tracked.Where<KeyValuePair<int, Entry>>((KeyValuePair<int, Entry> p) => p.Value.Info.Id == stableId).ToArray(); for (int num = 0; num < array.Length; num++) { KeyValuePair<int, Entry> keyValuePair = array[num]; this.Dirty?.Invoke(keyValuePair.Value.Last); _tracked.Remove(keyValuePair.Key); } } public IReadOnlyList<ObstacleInfo> Nearby(V3 center, float radius) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) return (from e in _tracked.Values where V3.Distance(e.Info.Center, center) <= radius select new ObstacleInfo { Id = e.Info.Id, Center = e.Info.Center, Size = e.Info.Size, Kind = e.Info.Kind, ConfirmedBreakable = e.Info.ConfirmedBreakable, IsActive = e.Info.IsActive, ObservedAt = e.Info.ObservedAt }).ToArray(); } public void Clear() { _tracked.Clear(); _checked.Clear(); _ignored.Clear(); _cursor = 0; } } public sealed class SLTConfig { internal static readonly JsonSerializerOptions Json = new JsonSerializerOptions { WriteIndented = true, PropertyNameCaseInsensitive = true }; public bool Enabled { get; set; } = true; public float CellSize { get; set; } = 0.5f; public float ScanRadius { get; set; } = 8f; public float BandHeight { get; set; } = 6f; public float RescanSeconds { get; set; } = 10f; public float MaxMapAgeSeconds { get; set; } = 30f; public double FrameBudgetMilliseconds { get; set; } = 1.2; public int PhysicsQueriesPerFrame { get; set; } = 128; public int ScanQueriesPerFrame { get; set; } = 48; public int MovementQueryReserve { get; set; } = 48; public int MaxColumns { get; set; } = 7000; public int MaxTrackedObstacles { get; set; } = 512; public int MaxRegisteredAgents { get; set; } = 32; public int MaxConcurrentPaths { get; set; } = 4; public int MaxQueuedPaths { get; set; } = 48; public int MaxSearchVisits { get; set; } = 4096; public int CollisionMask { get; set; } = -5; public int FloorMask { get; set; } = -5; public bool AllowDynamicFloors { get; set; } public float MinimumMappedRadius { get; set; } = 0.15f; public float MinimumMappedHeight { get; set; } = 0.45f; public float MaxMeasuredHeadroom { get; set; } = 4f; public int MaxNetworkBytesPerSecond { get; set; } = 24576; public bool WriteDiagnostics { get; set; } = true; public void Clamp() { CellSize = F(CellSize, 0.3f, 1.2f, 0.5f); ScanRadius = F(ScanRadius, 3f, 16f, 8f); BandHeight = F(BandHeight, 3f, 10f, 6f); RescanSeconds = F(RescanSeconds, 3f, 60f, 10f); MaxMapAgeSeconds = F(MaxMapAgeSeconds, RescanSeconds + 5f, 120f, 30f); FrameBudgetMilliseconds = (double.IsFinite(FrameBudgetMilliseconds) ? Math.Clamp(FrameBudgetMilliseconds, 0.2, 3.0) : 1.2); PhysicsQueriesPerFrame = Math.Clamp(PhysicsQueriesPerFrame, 32, 384); MovementQueryReserve = Math.Clamp(MovementQueryReserve, 8, PhysicsQueriesPerFrame / 2); ScanQueriesPerFrame = Math.Clamp(ScanQueriesPerFrame, 8, PhysicsQueriesPerFrame - MovementQueryReserve - 8); MaxColumns = Math.Clamp(MaxColumns, 500, 20000); MaxTrackedObstacles = Math.Clamp(MaxTrackedObstacles, 32, 2048); MaxRegisteredAgents = Math.Clamp(MaxRegisteredAgents, 1, 64); MaxConcurrentPaths = Math.Clamp(MaxConcurrentPaths, 1, 8); MaxQueuedPaths = Math.Clamp(MaxQueuedPaths, 1, 128); MaxSearchVisits = Math.Clamp(MaxSearchVisits, 128, 16000); MinimumMappedRadius = F(MinimumMappedRadius, 0.1f, 0.3f, 0.15f); MinimumMappedHeight = F(MinimumMappedHeight, MinimumMappedRadius * 2f, 0.9f, 0.45f); MaxMeasuredHeadroom = F(MaxMeasuredHeadroom, 2f, 6f, 4f); MaxNetworkBytesPerSecond = Math.Clamp(MaxNetworkBytesPerSecond, 4096, 65536); static float F(float v, float min, float max, float fallback) { if (!float.IsFinite(v)) { return fallback; } return Math.Clamp(v, min, max); } } public static SLTConfig Load(string path, Instance log) { SLTConfig sLTConfig; try { sLTConfig = (File.Exists(path) ? (JsonSerializer.Deserialize<SLTConfig>(File.ReadAllText(path), Json) ?? new SLTConfig()) : new SLTConfig()); } catch (Exception ex) { log.Warning("Config could not be read; using defaults: " + ex.Message); sLTConfig = new SLTConfig(); } sLTConfig.Clamp(); Directory.CreateDirectory(Path.GetDirectoryName(path)); File.WriteAllText(path, JsonSerializer.Serialize(sLTConfig, Json)); return sLTConfig; } } internal sealed class QueryBudget { public int Used { get; private set; } public int Limit { get; private set; } public bool Saturated { get; set; } public void Reset(int limit) { Used = 0; Limit = limit; Saturated = false; } public void SetLimit(int limit) { Limit = limit; } public bool Take(int count) { if (Used + count > Limit) { return false; } Used += count; return true; } } public sealed class SLTMod : MelonMod { public override void OnInitializeMelon() { string text = Path.Combine(MelonUtils.UserDataDirectory, "SLTCore"); Directory.CreateDirectory(text); SLTAPI.Announce(new SLTService(SLTConfig.Load(Path.Combine(text, "config.json"), ((MelonBase)this).LoggerInstance), ((MelonBase)this).LoggerInstance, text)); ((MelonBase)this).LoggerInstance.Msg("SLTCore 0.2.0 preview loaded. Navigation framework; NPC integration is required. BoneLib is optional."); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { SLTAPI.Service?.SceneChanged(sceneName); } public override void OnUpdate() { SLTAPI.Service?.Tick(); } public override void OnDeinitializeMelon() { SLTAPI.Service?.Shutdown(); SLTAPI.Service = null; } } public static class NavigationTargets { public static NavigationTarget TrackTransform(Transform target, V3 worldOffset = default(V3)) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!((V3)(ref worldOffset)).IsFinite) { throw new ArgumentException("Offset must be finite", "worldOffset"); } return NavigationTarget.Resolve((Func<V3?>)(() => (!Object.op_Implicit((Object)(object)target)) ? ((V3?)null) : new V3?(target.position.SLT() + worldOffset))); } } internal sealed class MapScheduler { private readonly WorldMap _map; private readonly SLTConfig _config; private readonly Queue<ColumnKey> _urgent = new Queue<ColumnKey>(); private readonly HashSet<ColumnKey> _urgentSet = new HashSet<ColumnKey>(); private readonly Queue<ColumnKey> _normal = new Queue<ColumnKey>(); private readonly HashSet<ColumnKey> _normalSet = new HashSet<ColumnKey>(); private readonly List<IEnumerator<ColumnKey>> _areas = new List<IEnumerator<ColumnKey>>(); private ColumnScan? _active; private ColumnKey _activeKey; private int _areaCursor; public int Pending => _urgentSet.Count + _normalSet.Count; public MapScheduler(WorldMap map, SLTConfig config) { _map = map; _config = config; } public void Focus(V3 p) { //IL_0020: Unknown result type (might be due to invalid IL or missing refe
UserLibs/SLTCore.Core.dll
Decompiled a week agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace SLTCore.Core { public abstract class NavigationTarget { private sealed class FixedTarget : NavigationTarget { private readonly V3 _position; public FixedTarget(V3 position) { _position = position; } public override bool TryGetPosition(out V3 feetPosition) { feetPosition = _position; return true; } } private sealed class ResolvedTarget : NavigationTarget { private readonly Func<V3?> _resolver; public ResolvedTarget(Func<V3?> resolver) { _resolver = resolver; } public override bool TryGetPosition(out V3 feetPosition) { feetPosition = default(V3); try { V3? v = _resolver(); if (!v.HasValue || !Usable(v.Value)) { return false; } feetPosition = v.Value; return true; } catch { return false; } } } public abstract bool TryGetPosition(out V3 feetPosition); public static NavigationTarget At(V3 feetPosition) { if (!Usable(feetPosition)) { throw new ArgumentException("A finite destination within world limits is required", "feetPosition"); } return new FixedTarget(feetPosition); } public static NavigationTarget Resolve(Func<V3?> resolver) { if (resolver == null) { throw new ArgumentNullException("resolver"); } return new ResolvedTarget(resolver); } private static bool Usable(V3 p) { if (p.IsFinite) { return p.Length < 50000f; } return false; } } public enum PacketKind : byte { SessionRequest = 1, Session, Route, Invalidate } public sealed class SLTPacket { public PacketKind Kind { get; set; } public Guid Session { get; set; } public uint Sequence { get; set; } public string Scene { get; set; } = ""; public long Revision { get; set; } public PathResult? Route { get; set; } } public static class WireCodec { public const ushort Protocol = 1; public const int MaxPacketBytes = 16384; public const int MaxWaypoints = 512; private const uint Magic = 1129598035u; private static readonly UTF8Encoding Utf8 = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); public static byte[] Encode(SLTPacket p) { using MemoryStream memoryStream = new MemoryStream(); using BinaryWriter binaryWriter = new BinaryWriter(memoryStream, Utf8, leaveOpen: true); binaryWriter.Write(1129598035u); binaryWriter.Write((ushort)1); binaryWriter.Write((byte)p.Kind); binaryWriter.Write(p.Session.ToByteArray()); binaryWriter.Write(p.Sequence); Text(binaryWriter, p.Scene, 128); binaryWriter.Write(p.Revision); if (p.Kind == PacketKind.Route) { PathResult pathResult = p.Route ?? throw new ArgumentException("Missing route"); if (pathResult.Points.Count > 512) { throw new ArgumentException("Route too long"); } binaryWriter.Write(pathResult.RequestId); Text(binaryWriter, pathResult.AgentId, 96); binaryWriter.Write((byte)pathResult.Status); binaryWriter.Write(pathResult.Revision); Text(binaryWriter, pathResult.Reason, 192); binaryWriter.Write((ushort)pathResult.Points.Count); foreach (Waypoint point in pathResult.Points) { if (!point.Feet.IsFinite || point.Feet.Length > 50000f || !Enum.IsDefined(typeof(MoveKind), point.Kind)) { throw new ArgumentException("Invalid waypoint"); } binaryWriter.Write(point.Feet.X); binaryWriter.Write(point.Feet.Y); binaryWriter.Write(point.Feet.Z); binaryWriter.Write((byte)point.Kind); Text(binaryWriter, point.ActionId, 96); } } if (memoryStream.Length > 16384) { throw new ArgumentException("Packet exceeds limit"); } return memoryStream.ToArray(); } public static bool TryDecode(byte[] bytes, out SLTPacket packet) { packet = new SLTPacket(); if (bytes == null || bytes.Length < 35 || bytes.Length > 16384) { return false; } try { using MemoryStream memoryStream = new MemoryStream(bytes, writable: false); using BinaryReader binaryReader = new BinaryReader(memoryStream, Utf8); if (binaryReader.ReadUInt32() != 1129598035 || binaryReader.ReadUInt16() != 1) { return false; } PacketKind packetKind = (PacketKind)binaryReader.ReadByte(); if (!Enum.IsDefined(typeof(PacketKind), packetKind)) { return false; } byte[] array = binaryReader.ReadBytes(16); if (array.Length != 16) { return false; } Guid session = new Guid(array); uint sequence = binaryReader.ReadUInt32(); string scene = Text(binaryReader, 128); long revision = binaryReader.ReadInt64(); SLTPacket sLTPacket = new SLTPacket { Kind = packetKind, Session = session, Sequence = sequence, Scene = scene, Revision = revision }; if (packetKind == PacketKind.Route) { long num = binaryReader.ReadInt64(); string text = Text(binaryReader, 96); PathStatus pathStatus = (PathStatus)binaryReader.ReadByte(); long revision2 = binaryReader.ReadInt64(); string reason = Text(binaryReader, 192); int num2 = binaryReader.ReadUInt16(); if (!Enum.IsDefined(typeof(PathStatus), pathStatus) || num < 1 || string.IsNullOrWhiteSpace(text) || num2 > 512 || num2 * 15 > memoryStream.Length - memoryStream.Position) { return false; } List<Waypoint> list = new List<Waypoint>(num2); for (int i = 0; i < num2; i++) { V3 feet = new V3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()); MoveKind moveKind = (MoveKind)binaryReader.ReadByte(); string actionId = Text(binaryReader, 96); if (!feet.IsFinite || feet.Length > 50000f || !Enum.IsDefined(typeof(MoveKind), moveKind)) { return false; } list.Add(new Waypoint(feet, moveKind, actionId)); } if ((pathStatus == PathStatus.Complete || pathStatus == PathStatus.Partial) && num2 == 0) { return false; } sLTPacket.Route = new PathResult(num, text, pathStatus, revision2, list, reason); } if (memoryStream.Position != memoryStream.Length) { return false; } packet = sLTPacket; return true; } catch (Exception ex) when (ex is IOException || ex is ArgumentException || ex is OverflowException) { return false; } } private static void Text(BinaryWriter writer, string text, int max) { byte[] bytes = Utf8.GetBytes(text); if (text.Length > max || bytes.Length > max * 4) { throw new ArgumentException("Text exceeds protocol limit"); } writer.Write((ushort)bytes.Length); writer.Write(bytes); } private static string Text(BinaryReader reader, int max) { int num = reader.ReadUInt16(); if (num > max * 4) { throw new InvalidDataException("Text exceeds protocol limit"); } byte[] array = reader.ReadBytes(num); if (array.Length != num) { throw new EndOfStreamException(); } string text = Utf8.GetString(array); if (text.Length > max) { throw new InvalidDataException(); } return text; } } public sealed class ReplicaGate { private readonly Dictionary<string, uint> _last = new Dictionary<string, uint>(StringComparer.Ordinal); private uint? _lastInvalidate; public Guid Session { get; private set; } public string Scene { get; private set; } = ""; public void Reset(string scene) { Scene = scene; Session = Guid.Empty; _last.Clear(); _lastInvalidate = null; } public bool Accept(SLTPacket packet, bool fromHost) { if (!fromHost || packet.Scene != Scene || packet.Session == Guid.Empty) { return false; } if (packet.Kind == PacketKind.Session) { if (Session != packet.Session) { Session = packet.Session; _last.Clear(); _lastInvalidate = null; } return true; } if (packet.Session != Session || Session == Guid.Empty) { return false; } if (packet.Kind == PacketKind.Invalidate) { if (_lastInvalidate.HasValue && (int)(packet.Sequence - _lastInvalidate.Value) <= 0) { return false; } _lastInvalidate = packet.Sequence; return true; } if (packet.Kind != PacketKind.Route || packet.Route == null) { return false; } string agentId = packet.Route.AgentId; if (_last.TryGetValue(agentId, out var value) && (int)(packet.Sequence - value) <= 0) { return false; } if (_last.Count >= 64 && !_last.ContainsKey(agentId)) { return false; } _last[agentId] = packet.Sequence; return true; } } public readonly struct V3 : IEquatable<V3> { public readonly float X; public readonly float Y; public readonly float Z; public bool IsFinite { get { if (float.IsFinite(X) && float.IsFinite(Y)) { return float.IsFinite(Z); } return false; } } public float Length => MathF.Sqrt(X * X + Y * Y + Z * Z); public float HorizontalLength => MathF.Sqrt(X * X + Z * Z); public V3 Normalized { get { if (!(Length > 1E-05f)) { return default(V3); } return this / Length; } } public V3(float x, float y, float z) { X = x; Y = y; Z = z; } public static V3 operator +(V3 a, V3 b) { return new V3(a.X + b.X, a.Y + b.Y, a.Z + b.Z); } public static V3 operator -(V3 a, V3 b) { return new V3(a.X - b.X, a.Y - b.Y, a.Z - b.Z); } public static V3 operator *(V3 a, float b) { return new V3(a.X * b, a.Y * b, a.Z * b); } public static V3 operator /(V3 a, float b) { return new V3(a.X / b, a.Y / b, a.Z / b); } public static float Distance(V3 a, V3 b) { return (a - b).Length; } public bool Equals(V3 b) { if (X.Equals(b.X) && Y.Equals(b.Y)) { return Z.Equals(b.Z); } return false; } public override bool Equals(object? o) { if (o is V3 b) { return Equals(b); } return false; } public override int GetHashCode() { return HashCode.Combine(X, Y, Z); } public override string ToString() { return $"({X:0.00}, {Y:0.00}, {Z:0.00})"; } } public readonly record struct ColumnKey(int X, int Z, int Band); public readonly record struct NodeKey(int X, int Y, int Z); public enum MoveKind : byte { Walk, Crouch, Step, Drop, Jump, Climb, Break, Custom } public enum LinkState : byte { Blocked, Clear, Deferred } public enum PathStatus : byte { Complete, Partial, NoPath, AwaitingMap, InvalidRequest, Cancelled, TimedOut, MapChanged, TooComplex, AuthorityUnavailable, Busy, TooLong, TargetUnavailable } public enum OpeningKind : byte { Wall, Floor, Ceiling } public enum ObstacleKind : byte { Solid, Movable, BreakableCandidate, ConfirmedBreakable, Door, Glass } public enum AuthorityMode : byte { SinglePlayer, Host, Client, Unknown } public sealed class AgentProfile { public float Radius { get; set; } = 0.28f; public float Height { get; set; } = 1.75f; public float CrouchHeight { get; set; } = 1.05f; public float StepHeight { get; set; } = 0.3f; public float MaxSlopeDegrees { get; set; } = 42f; public float MaxDrop { get; set; } = 0.4f; public bool CanCrouch { get; set; } = true; public bool CanBreak { get; set; } public bool CanJump { get; set; } public bool CanClimb { get; set; } public float ExtraCost { get; set; } public bool IsValid { get { if (float.IsFinite(Radius) && Radius >= 0.1f && Radius <= 2f && float.IsFinite(Height) && Height >= Radius * 2f && Height <= 5f && float.IsFinite(CrouchHeight) && CrouchHeight >= Radius * 2f && CrouchHeight <= Height && float.IsFinite(StepHeight) && StepHeight >= 0f && StepHeight <= 1f && float.IsFinite(MaxSlopeDegrees) && MaxSlopeDegrees >= 0f && MaxSlopeDegrees <= 65f && float.IsFinite(MaxDrop) && MaxDrop >= 0f && MaxDrop <= 4f && float.IsFinite(ExtraCost) && ExtraCost >= 0f) { return ExtraCost <= 100f; } return false; } } public AgentProfile Copy() { return (AgentProfile)MemberwiseClone(); } public bool Allows(MoveKind kind) { return kind switch { MoveKind.Crouch => CanCrouch, MoveKind.Break => CanBreak, MoveKind.Jump => CanJump, MoveKind.Climb => CanClimb, MoveKind.Custom => false, _ => true, }; } } public sealed class Surface { public NodeKey Key { get; } public V3 Feet { get; } public float NormalY { get; } public float Headroom { get; } public bool Dynamic { get; } public Surface(NodeKey key, V3 feet, float normalY, float headroom, bool dynamic = false) { Key = key; Feet = feet; NormalY = normalY; Headroom = headroom; Dynamic = dynamic; } public bool Fits(AgentProfile p) { if (NormalY >= MathF.Cos(p.MaxSlopeDegrees * (float)Math.PI / 180f)) { return Headroom + 0.01f >= (p.CanCrouch ? p.CrouchHeight : p.Height); } return false; } internal bool Equivalent(Surface other) { if (Key == other.Key && V3.Distance(Feet, other.Feet) < 0.01f && MathF.Abs(Headroom - other.Headroom) < 0.03f && MathF.Abs(NormalY - other.NormalY) < 0.02f) { return Dynamic == other.Dynamic; } return false; } } public readonly record struct Waypoint(V3 Feet, MoveKind Kind = MoveKind.Walk, string ActionId = ""); public sealed class PathResult { public long RequestId { get; } public string AgentId { get; } public PathStatus Status { get; } public long Revision { get; } public IReadOnlyList<Waypoint> Points { get; } public string Reason { get; } public bool CanExecute { get { if (Status != PathStatus.Complete) { return Status == PathStatus.Partial; } return true; } } public PathResult(long requestId, string agentId, PathStatus status, long revision, IReadOnlyList<Waypoint>? points = null, string reason = "") { RequestId = requestId; AgentId = agentId; Status = status; Revision = revision; IReadOnlyList<Waypoint> readOnlyList2; if (points != null) { IReadOnlyList<Waypoint> readOnlyList = new List<Waypoint>(points).AsReadOnly(); readOnlyList2 = readOnlyList; } else { IReadOnlyList<Waypoint> readOnlyList = Array.Empty<Waypoint>(); readOnlyList2 = readOnlyList; } Points = readOnlyList2; Reason = reason; } } public sealed class PathRequest { public long RequestId { get; set; } public string AgentId { get; set; } = ""; public V3 Start { get; set; } public V3 Goal { get; set; } public AgentProfile Profile { get; set; } = new AgentProfile(); public bool AllowPartial { get; set; } public bool IsValid { get { if (RequestId > 0 && !string.IsNullOrWhiteSpace(AgentId) && AgentId.Length <= 96 && Start.IsFinite && Goal.IsFinite && Start.Length < 50000f && Goal.Length < 50000f && V3.Distance(Start, Goal) <= 150f && Profile != null) { return Profile.IsValid; } return false; } } public PathRequest Copy() { return new PathRequest { RequestId = RequestId, AgentId = AgentId, Start = Start, Goal = Goal, Profile = (Profile?.Copy() ?? new AgentProfile { Radius = float.NaN }), AllowPartial = AllowPartial }; } } public sealed class TraversalLink { public string Id { get; } public V3 From { get; } public V3 To { get; } public MoveKind Kind { get; } public float Width { get; } public float Height { get; } public float Cost { get; } public bool Bidirectional { get; } public TraversalLink(string id, V3 from, V3 to, MoveKind kind, float width, float height, float extraCost = 3f, bool bidirectional = false) { if (string.IsNullOrWhiteSpace(id) || id.Length > 96 || !from.IsFinite || !to.IsFinite || !float.IsFinite(width) || !float.IsFinite(height) || width <= 0f || height <= 0f || !float.IsFinite(extraCost) || extraCost < 0f) { throw new ArgumentException("Invalid traversal link"); } Id = id; From = from; To = to; Kind = kind; Width = width; Height = height; Cost = V3.Distance(from, to) + extraCost; Bidirectional = bidirectional; } } public readonly record struct LinkCheck(LinkState State, MoveKind Kind = MoveKind.Walk, float ExtraCost = 0f); public interface IWorldQuery { LinkCheck CheckTraversal(V3 from, V3 to, AgentProfile profile); } public sealed class OpeningResult { public V3 Center { get; init; } public V3 Normal { get; init; } public float Width { get; init; } public float Height { get; init; } public float Resolution { get; init; } public OpeningKind Kind { get; init; } public bool Found { get; init; } public bool Truncated { get; init; } public bool Invalidated { get; init; } public double ObservedAt { get; init; } public bool Fits(AgentProfile p) { if (Found && Width >= p.Radius * 2f) { return Height >= ((Kind != OpeningKind.Wall) ? (p.Radius * 2f) : (p.CanCrouch ? p.CrouchHeight : p.Height)); } return false; } } public sealed class SearchJob { private readonly WorldMap _map; private readonly IWorldQuery _world; private readonly PathRequest _request; private readonly PriorityQueue<NodeKey, float> _open = new PriorityQueue<NodeKey, float>(); private readonly Dictionary<NodeKey, float> _g = new Dictionary<NodeKey, float>(); private readonly Dictionary<NodeKey, (NodeKey parent, MoveKind kind, string action)> _parents = new Dictionary<NodeKey, (NodeKey, MoveKind, string)>(); private readonly HashSet<NodeKey> _closed = new HashSet<NodeKey>(); private Surface? _start; private Surface? _goal; private Surface? _current; private Surface? _closest; private List<(Surface node, MoveKind? special, string id, float cost)>? _neighbors; private int _neighborIndex; private long _revision; private int _restarts; private readonly int _maxVisits; private readonly double _created; private double _now; private double _maxAge; public PathResult? Result { get; private set; } public bool Done => Result != null; public int Visited => _closed.Count; public SearchJob(WorldMap map, IWorldQuery world, PathRequest request, double now, int maxVisits = 4096) { _map = map; _world = world; _request = request.Copy(); _maxVisits = maxVisits; _created = now; if (!_request.IsValid) { Finish(PathStatus.InvalidRequest, "Invalid request or profile"); } } public void Cancel() { if (!Done) { Finish(PathStatus.Cancelled, "Superseded or cancelled"); } } public void Step(double now, double maxAge, int maxQueries, double maxMilliseconds) { if (Done) { return; } _now = now; _maxAge = maxAge; if (now - _created > 12.0) { Finish(PathStatus.TimedOut, "Mapping or search deadline exceeded"); return; } if (_start == null) { _start = _map.Nearest(_request.Start, _request.Profile, now, maxAge); _goal = _map.Nearest(_request.Goal, _request.Profile, now, maxAge); if (_start == null || _goal == null) { _start = null; return; } _revision = _map.Revision; _g[_start.Key] = 0f; _open.Enqueue(_start.Key, Heuristic(_start)); _closest = _start; LinkCheck linkCheck = _world.CheckTraversal(_request.Start, _start.Feet, _request.Profile); LinkCheck linkCheck2 = _world.CheckTraversal(_goal.Feet, _request.Goal, _request.Profile); if (linkCheck.State == LinkState.Deferred || linkCheck2.State == LinkState.Deferred) { Restart(); return; } if (linkCheck.State != LinkState.Clear || linkCheck2.State != LinkState.Clear) { Finish(PathStatus.NoPath, "Endpoint connector blocked"); return; } } if (!_map.TryGet(_start.Key, out Surface node) || !_map.TryGet(_goal.Key, out Surface node2) || !node.Fits(_request.Profile) || !node2.Fits(_request.Profile) || (_current != null && !_map.TryGet(_current.Key, out Surface _))) { if (++_restarts > 128) { Finish(PathStatus.MapChanged, "Geometry changed throughout search"); } else { Restart(); } return; } Stopwatch stopwatch = Stopwatch.StartNew(); int num = 0; while (num < maxQueries && stopwatch.Elapsed.TotalMilliseconds < maxMilliseconds) { if (_current == null) { NodeKey element = default(NodeKey); bool flag = false; float priority; while (_open.TryDequeue(out element, out priority)) { if (!_closed.Contains(element)) { flag = true; break; } } if (!flag) { if (_revision != _map.Revision && ++_restarts <= 128) { Restart(); } else { CompleteOrPartial(PathStatus.NoPath, "No connected route in the observed area"); } break; } if (!_map.TryGet(element, out _current)) { Restart(); break; } if (!_map.IsFresh(_current, now, maxAge)) { Finish(PathStatus.MapChanged, "Surface observations expired"); break; } if (_current.Key == _goal.Key) { MakePath(_current, PathStatus.Complete); break; } _closed.Add(element); if (_closed.Count >= _maxVisits) { CompleteOrPartial(PathStatus.TooComplex, "Search visit limit reached"); break; } if (Heuristic(_current) < Heuristic(_closest)) { _closest = _current; } _neighbors = new List<(Surface, MoveKind?, string, float)>(); _neighborIndex = 0; foreach (Surface item in _map.Neighbors(_current, _request.Profile, now, maxAge)) { _neighbors.Add((item, null, "", 0f)); } foreach (TraversalLink value2 in _map.Links.Values) { if (!_request.Profile.Allows(value2.Kind) || value2.Width < _request.Profile.Radius * 2f || value2.Height < (_request.Profile.CanCrouch ? _request.Profile.CrouchHeight : _request.Profile.Height)) { continue; } bool flag2 = V3.Distance(_current.Feet, value2.From) <= _map.CellSize * 0.8f; bool flag3 = value2.Bidirectional && V3.Distance(_current.Feet, value2.To) <= _map.CellSize * 0.8f; if (flag2 || flag3) { Surface surface = _map.Nearest(flag2 ? value2.To : value2.From, _request.Profile, now, maxAge, _map.CellSize * 0.8f, 0.25f); if (surface != null) { _neighbors.Add((surface, value2.Kind, value2.Id, value2.Cost)); } } } } if (_neighborIndex >= _neighbors.Count) { _current = null; continue; } (Surface, MoveKind?, string, float) tuple = _neighbors[_neighborIndex]; if (!_map.TryGet(tuple.Item1.Key, out Surface node4) || !node4.Fits(_request.Profile)) { _neighborIndex++; continue; } tuple.Item1 = node4; if (_closed.Contains(tuple.Item1.Key)) { _neighborIndex++; continue; } LinkCheck linkCheck3; if (tuple.Item2.HasValue) { linkCheck3 = new LinkCheck(LinkState.Clear, tuple.Item2.Value); } else { linkCheck3 = _world.CheckTraversal(_current.Feet, tuple.Item1.Feet, _request.Profile); num++; } if (linkCheck3.State == LinkState.Deferred) { break; } _neighborIndex++; if (linkCheck3.State == LinkState.Clear) { float num2 = MathF.Max(V3.Distance(_current.Feet, tuple.Item1.Feet), tuple.Item4) + MathF.Max(0f, linkCheck3.ExtraCost) + _request.Profile.ExtraCost; float num3 = _g[_current.Key] + num2; if (!_g.TryGetValue(tuple.Item1.Key, out var value) || !(num3 >= value)) { _g[tuple.Item1.Key] = num3; _parents[tuple.Item1.Key] = (_current.Key, linkCheck3.Kind, tuple.Item3); _open.Enqueue(tuple.Item1.Key, num3 + Heuristic(tuple.Item1)); } } } } private float Heuristic(Surface node) { return V3.Distance(node.Feet, _goal.Feet); } private void Restart() { _start = (_goal = (_current = (_closest = null))); _neighbors = null; _open.Clear(); _g.Clear(); _parents.Clear(); _closed.Clear(); } private void CompleteOrPartial(PathStatus failure, string reason) { if (_request.AllowPartial && _closest != null && _start != null && _closest.Key != _start.Key) { MakePath(_closest, PathStatus.Partial); } else { Finish(failure, reason); } } private void MakePath(Surface end, PathStatus status) { List<Waypoint> list = new List<Waypoint>(); NodeKey key = end.Key; int num = 0; (NodeKey, MoveKind, string) value; while (_parents.TryGetValue(key, out value)) { if (++num > 512) { Finish(PathStatus.TooLong, "Route exceeds 512 waypoints; request a nearer goal"); return; } if (!_map.TryGet(key, out Surface node) || !node.Fits(_request.Profile) || !_map.IsFresh(node, _now, _maxAge) || (value.Item3.Length > 0 && !_map.Links.ContainsKey(value.Item3))) { if (++_restarts <= 128) { Restart(); } else { Finish(PathStatus.MapChanged, "Route repeatedly changed"); } return; } list.Add(new Waypoint(node.Feet, value.Item2, value.Item3)); (key, _, _) = value; } list.Add(new Waypoint(_start.Feet)); list.Reverse(); if (V3.Distance(_request.Start, list[0].Feet) > 0.03f) { list.Insert(0, new Waypoint(_request.Start)); } if (status == PathStatus.Complete) { if (V3.Distance(list[list.Count - 1].Feet, _request.Goal) > 0.03f) { list.Add(new Waypoint(_request.Goal)); } } if (list.Count > 512) { Finish(PathStatus.TooLong, "Route exceeds wire waypoint limit"); } else { Result = new PathResult(_request.RequestId, _request.AgentId, status, _map.Revision, list); } } private void Finish(PathStatus status, string reason) { Result = new PathResult(_request.RequestId, _request.AgentId, status, _map.Revision, null, reason); } } public readonly record struct GridRectangle(int Left, int Bottom, int Right, int Top) { public int Width => Right - Left + 1; public int Height => Top - Bottom + 1; } public static class OpeningMath { public static GridRectangle? Measure(bool[,] free, int seedX, int seedY) { int length = free.GetLength(0); int length2 = free.GetLength(1); if (seedX < 0 || seedY < 0 || seedX >= length || seedY >= length2 || !free[seedX, seedY]) { return null; } GridRectangle value = new GridRectangle(seedX, seedY, seedX, seedY); for (int num = seedY; num >= 0; num--) { int num2 = 0; int num3 = length - 1; for (int i = num; i < length2 && free[seedX, i]; i++) { int num4 = seedX; int j = seedX; while (num4 > 0 && free[num4 - 1, i]) { num4--; } for (; j + 1 < length && free[j + 1, i]; j++) { } num2 = Math.Max(num2, num4); num3 = Math.Min(num3, j); if (i >= seedY && (num3 - num2 + 1) * (i - num + 1) > value.Width * value.Height) { value = new GridRectangle(num2, num, num3, i); } } } return value; } } public sealed class WorldMap { private sealed class Column { public List<Surface> Nodes = new List<Surface>(); public double ObservedAt; } private readonly Dictionary<ColumnKey, Column> _columns = new Dictionary<ColumnKey, Column>(); private readonly Dictionary<NodeKey, Surface> _nodes = new Dictionary<NodeKey, Surface>(); private readonly Dictionary<(int, int), List<Surface>> _horizontal = new Dictionary<(int, int), List<Surface>>(); public Dictionary<string, TraversalLink> Links { get; } = new Dictionary<string, TraversalLink>(StringComparer.Ordinal); public float CellSize { get; } public float BandHeight { get; } public long Revision { get; private set; } public int NodeCount => _nodes.Count; public int ColumnCount => _columns.Count; public WorldMap(float cellSize = 0.5f, float bandHeight = 6f) { if (cellSize < 0.2f || cellSize > 2f || bandHeight < 2f || !float.IsFinite(cellSize) || !float.IsFinite(bandHeight)) { throw new ArgumentOutOfRangeException("cellSize"); } CellSize = cellSize; BandHeight = bandHeight; } public ColumnKey ColumnAt(V3 p) { return new ColumnKey((int)MathF.Floor(p.X / CellSize), (int)MathF.Floor(p.Z / CellSize), (int)MathF.Floor(p.Y / BandHeight)); } public NodeKey KeyAt(V3 p) { return new NodeKey((int)MathF.Floor(p.X / CellSize), (int)MathF.Round(p.Y / 0.04f), (int)MathF.Floor(p.Z / CellSize)); } public V3 ColumnCenter(ColumnKey c) { return new V3(((float)c.X + 0.5f) * CellSize, (float)c.Band * BandHeight, ((float)c.Z + 0.5f) * CellSize); } public bool TryGet(NodeKey key, out Surface node) { return _nodes.TryGetValue(key, out node); } public double LastScanned(ColumnKey key) { if (!_columns.TryGetValue(key, out Column value)) { return double.NegativeInfinity; } return value.ObservedAt; } public void Replace(ColumnKey key, List<Surface> nodes, double observedAt) { if (!double.IsFinite(observedAt)) { throw new ArgumentOutOfRangeException("observedAt"); } if (nodes.Count > 24 || nodes.Any((Surface n) => !n.Feet.IsFinite || n.Headroom < 0f || !float.IsFinite(n.Headroom) || n.Key != KeyAt(n.Feet) || ColumnAt(n.Feet) != key)) { throw new ArgumentException("Invalid column surfaces"); } nodes = (from n in nodes group n by n.Key into g select g.First() into n orderby n.Feet.Y select n).ToList(); if (_columns.TryGetValue(key, out Column value) && value.Nodes.Count == nodes.Count && value.Nodes.Zip(nodes).All(((Surface First, Surface Second) pair) => pair.First.Equivalent(pair.Second))) { value.ObservedAt = observedAt; return; } if (value != null) { RemoveNodes(key, value.Nodes); } _columns[key] = new Column { Nodes = nodes, ObservedAt = observedAt }; if (!_horizontal.TryGetValue((key.X, key.Z), out List<Surface> value2)) { value2 = (_horizontal[(key.X, key.Z)] = new List<Surface>()); } foreach (Surface node in nodes) { _nodes[node.Key] = node; value2.Add(node); } Revision++; } private void RemoveNodes(ColumnKey key, List<Surface> nodes) { foreach (Surface node in nodes) { _nodes.Remove(node.Key); } if (!_horizontal.TryGetValue((key.X, key.Z), out List<Surface> value)) { return; } value.RemoveAll((Surface n) => nodes.Exists((Surface old) => old.Key == n.Key)); if (value.Count == 0) { _horizontal.Remove((key.X, key.Z)); } } public bool IsFresh(Surface node, double now, double maxAge) { return now - LastScanned(ColumnAt(node.Feet)) <= maxAge; } public Surface? Nearest(V3 point, AgentProfile profile, double now, double maxAge, float horizontal = 0.9f, float vertical = 0.8f) { Surface result = null; float num = float.MaxValue; ColumnKey columnKey = ColumnAt(point); int num2 = (int)MathF.Ceiling(horizontal / CellSize); for (int i = columnKey.X - num2; i <= columnKey.X + num2; i++) { for (int j = columnKey.Z - num2; j <= columnKey.Z + num2; j++) { if (!_horizontal.TryGetValue((i, j), out List<Surface> value)) { continue; } foreach (Surface item in value) { V3 v = item.Feet - point; if (!(v.HorizontalLength > horizontal) && !(MathF.Abs(v.Y) > vertical) && item.Fits(profile) && IsFresh(item, now, maxAge)) { float length = v.Length; if (length < num) { result = item; num = length; } } } } } return result; } public List<Surface> Neighbors(Surface node, AgentProfile profile, double now, double maxAge) { List<Surface> list = new List<Surface>(12); for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { if ((i == 0 && j == 0) || !_horizontal.TryGetValue((node.Key.X + i, node.Key.Z + j), out List<Surface> value)) { continue; } foreach (Surface item in value) { float num = item.Feet.Y - node.Feet.Y; float horizontalLength = (item.Feet - node.Feet).HorizontalLength; float y = MathF.Tan(profile.MaxSlopeDegrees * (float)Math.PI / 180f) * horizontalLength; if (!(num > MathF.Max(profile.StepHeight, y) + 0.03f) && !(num < 0f - MathF.Max(profile.MaxDrop, y) - 0.03f) && item.Fits(profile) && IsFresh(item, now, maxAge)) { list.Add(item); } } } } return list; } public void AddLink(TraversalLink link) { if (Links.Count >= 512 && !Links.ContainsKey(link.Id)) { throw new InvalidOperationException("Traversal link limit reached"); } Links[link.Id] = link; Revision++; } public bool RemoveLink(string id) { bool num = Links.Remove(id); if (num) { Revision++; } return num; } public int Evict(double now, double maxAge, IReadOnlyList<V3> foci, float radius, int hardColumnLimit) { List<ColumnKey> list = new List<ColumnKey>(); foreach (KeyValuePair<ColumnKey, Column> column in _columns) { V3 p = ColumnCenter(column.Key); if (!foci.Any((V3 f) => (new V3(p.X, f.Y, p.Z) - f).Length <= radius && MathF.Abs(p.Y - f.Y) <= BandHeight * 2f) || now - column.Value.ObservedAt > maxAge) { list.Add(column.Key); } } foreach (ColumnKey item in list) { RemoveNodes(item, _columns[item].Nodes); _columns.Remove(item); } if (_columns.Count > hardColumnLimit) { ColumnKey[] array = (from keyValuePair in _columns.OrderBy<KeyValuePair<ColumnKey, Column>, double>((KeyValuePair<ColumnKey, Column> keyValuePair) => keyValuePair.Value.ObservedAt).Take(_columns.Count - hardColumnLimit) select keyValuePair.Key).ToArray(); foreach (ColumnKey columnKey in array) { RemoveNodes(columnKey, _columns[columnKey].Nodes); _columns.Remove(columnKey); list.Add(columnKey); } } if (list.Count != 0) { Revision++; } return list.Count; } public void Clear() { _columns.Clear(); _nodes.Clear(); _horizontal.Clear(); Links.Clear(); Revision++; } } }