public static void BeginTracking(ITrackable target) { if (!_trackedTargets.ContainsKey(target)) { var position = target.Position; var space = _worldToTrack.SpaceArchitect.GetContainingSpace(position); var initialPositionData = new PositionData(space, position); var chunk = _worldToTrack.ChunkArchitect.GetContainingChunk(position); if (chunk != null) { initialPositionData.Chunk = chunk; } else { var builder = _worldToTrack.ChunkArchitect.GetContainingBuilder(position); initialPositionData.Builder = builder; } _trackedTargets.Add(target, initialPositionData); _log.Info($"Now tracking {target} at initial position {initialPositionData}."); if (_trackedTargets.Count == 1) { _log.Info("Starting position update coroutine."); _updateMethod = Instance.StartCoroutine(PositionUpdate()); } } }
private static IEnumerator PositionUpdate() { while (true) { foreach (var trackedTarget in _trackedTargets.ToList()) { var target = trackedTarget.Key; var oldPositionData = trackedTarget.Value; var position = target.Position; var space = oldPositionData.Space; // See if any spaces contain this position if (space == null || !space.Contains(position)) { space = _worldToTrack.SpaceArchitect.GetContainingSpace(position) ?? null; } var newPositionData = new PositionData(space, position); // See if we are still in the same chunk (if any) if (oldPositionData.Chunk == null || !oldPositionData.Chunk.Contains(position)) { // Else see what chunk we are in newPositionData.Chunk = _worldToTrack.ChunkArchitect.GetContainingChunk(position); } else { newPositionData.Chunk = oldPositionData.Chunk; } // If we aren't in a chunk, we must be in a builder if (newPositionData.Chunk == null) { newPositionData.Builder = _worldToTrack.ChunkArchitect.GetContainingBuilder(position); } // If the position has changed, it is an update, so call everyone if (oldPositionData != newPositionData) { if (_onPositionChangedCallbacks.TryGetValue(target, out var callbacksToCall)) { // Duplicate the list briefly, so that any callbacks that remove things from the list don't interrupt execution foreach (var callback in callbacksToCall.ToList()) { callback?.Invoke(target, oldPositionData, newPositionData); } } _trackedTargets[target] = newPositionData; } } yield return(_positionUpdateTick); } }