/// <summary> /// Search every possible ore detector for materials. /// </summary> /// <param name="requester">Must be able to control OreDetector and have same NetworkStorage</param> /// <param name="oreType">Voxel materials to search for</param> public static void SearchForMaterial(ShipControllerBlock requester, byte[] oreType, OreSearchComplete onComplete) { Vector3D position = requester.CubeBlock.GetPosition(); RelayStorage storage = requester.NetworkStorage; Static.m_thread.EnqueueAction(() => { List <OreDetector> oreDetectors = ResourcePool <List <OreDetector> > .Get(); Registrar.ForEach((OreDetector detector) => { if (detector.Block.IsWorking && requester.CubeBlock.canControlBlock(detector.Block) && detector.m_netClient.GetStorage() == storage) { oreDetectors.Add(detector); } }); IOrderedEnumerable <OreDetector> sorted = oreDetectors.OrderBy(detector => Vector3D.DistanceSquared(position, detector.Block.GetPosition())); foreach (OreDetector detector in sorted) { if (detector.GetOreLocations(position, oreType, onComplete)) { return; } } oreDetectors.Clear(); ResourcePool <List <OreDetector> > .Return(oreDetectors); onComplete(false, null, null, null); }); }
/// <summary> /// Add the spheres that prevent autopilot from getting stuck between objects. /// </summary> /// <remarks> /// For every cluster, adds a sphere that includes the centre of every sphere in the cluster. /// </remarks> public void AddMiddleSpheres() { for (int indexO = Clusters.Count - 1; indexO >= 0; indexO--) { List <RepulseSphere> cluster = Clusters[indexO]; if (cluster.Count < 2) { continue; } Vector3D[] points = new Vector3D[cluster.Count]; for (int indexI = cluster.Count - 1; indexI >= 0; indexI--) { points[indexI] = cluster[indexI].Centre; } BoundingSphereD sphere = BoundingSphereD.CreateFromPoints(points); RepulseSphere repulse = new RepulseSphere() { Centre = sphere.Center, FixedRadius = sphere.Radius }; #if DEBUG List <IMyEntity> entities; ResourcePool.Get(out entities); foreach (RepulseSphere rs in cluster) { entities.AddArray(rs.Entities); } repulse.Entities = entities.ToArray(); entities.Clear(); ResourcePool.Return(entities); #endif cluster.Add(repulse); } }
private void DisplyAutopilotStatus() { //Log.DebugLog("Building autopilot list", "DisplyAutopilotStatus()", Logger.severity.TRACE); RelayStorage store = m_networkClient.GetStorage(); if (store == null) { m_textPanel.WritePublicText("No network connection"); return; } List <SortableAutopilot> autopilots = ResourcePool <List <SortableAutopilot> > .Get(); Vector3D mypos = m_block.GetPosition(); Registrar.ForEach <AutopilotTerminal>(ap => { IRelayPart relayPart; if (RelayClient.TryGetRelayPart((IMyCubeBlock)ap.m_block, out relayPart) && relayPart.GetStorage() == store && m_block.canControlBlock(ap.m_block)) { autopilots.Add(new SortableAutopilot(ap, mypos)); } }); autopilots.Sort(); StringBuilder displayText = new StringBuilder(); displayText.Append(timeString); displayText.Append(DateTime.Now.ToLongTimeString()); displayText.AppendLine(); int count = 0; foreach (SortableAutopilot ap in autopilots) { displayText.Append(tab); displayText.Append(ap.Autopilot.m_block.CubeGrid.DisplayName); displayText.Append(tab); displayText.Append(PrettySI.makePretty(ap.Distance)); displayText.AppendLine("m"); ap.Autopilot.AppendingCustomInfo(displayText); displayText.AppendLine(); count++; if (count >= 5) { break; } } autopilots.Clear(); ResourcePool <List <SortableAutopilot> > .Return(autopilots); string displayString = displayText.ToString(); //Log.DebugLog("Writing to panel: " + m_textPanel.DisplayNameText + ":\n\t" + displayString, "DisplyAutopilotStatus()", Logger.severity.TRACE); m_textPanel.WritePublicText(displayText.ToString()); }
/// <summary> /// <para>For each LastSeen add to this storage or updates an existing LastSeen. LastSeen will be pushed to connected storages.</para> /// </summary> /// <param name="seen">Collection of LastSeen entitites.</param> public void Receive(ICollection <LastSeen> seen) { HashSet <RelayStorage> sendToSet = ResourcePool <HashSet <RelayStorage> > .Get(); try { AddStorage(sendToSet, this); foreach (RelayStorage sto in sendToSet) { using (sto.lock_lastSeen.AcquireExclusiveUsing()) foreach (LastSeen s in seen) { sto.in_Receive(s); } if (sto.m_nextClean_lastSeen <= Globals.UpdateCount) { Log.DebugLog("Running cleanup on last seen", Logger.severity.INFO); sto.ForEachLastSeen(s => { }); } } } finally { sendToSet.Clear(); ResourcePool <HashSet <RelayStorage> > .Return(sendToSet); } }
/// <summary> /// <para>Add a Message to this storage. Message will be pushed to connected storages.</para> /// <para>Not optimized for use within a loop.</para> /// </summary> /// <param name="msg">Message to receive.</param> public void Receive(Message msg) { HashSet <RelayStorage> sendToSet = ResourcePool <HashSet <RelayStorage> > .Get(); try { AddStorage(sendToSet, this); foreach (RelayStorage sto in sendToSet) { using (sto.lock_messages.AcquireExclusiveUsing()) sto.in_Receive(msg); if (sto.m_nextClean_message <= Globals.UpdateCount) { Log.DebugLog("Running cleanup on message", Logger.severity.INFO); sto.ForEachMessage(s => { }); } } } finally { sendToSet.Clear(); ResourcePool <HashSet <RelayStorage> > .Return(sendToSet); } }
/// <summary> /// Send _outgoing immediately. /// </summary> private void SendOutgoing() { const int maxSize = 4088; List <byte> bytes; ResourcePool.Get(out bytes); AddIdAndValue(bytes); int initCount = bytes.Count; if (initCount > maxSize) { alwaysLog("Cannot send message, value is too large. byte count: " + initCount + ", value: " + _outgoing.Value); _outgoing = null; return; } for (int entityIdIndex = _outgoing.EntityId.Count - 1; entityIdIndex >= 0; --entityIdIndex) { ByteConverter.AppendBytes(bytes, _outgoing.EntityId[entityIdIndex]); if (bytes.Count > maxSize) { traceLog("Over max size, splitting message"); SendOutgoing(bytes); AddIdAndValue(bytes); } } SendOutgoing(bytes); _outgoing = null; bytes.Clear(); ResourcePool.Return(bytes); }
protected override FrameworkElement CreateMarkerCore(object dataItem) { if (template == null) { throw new InvalidOperationException(Strings.Exceptions.TemplateShouldNotBeNull); } FrameworkElement marker = pool.Get(); if (marker == null) { marker = (FrameworkElement)template.LoadContent(); } return(marker); }
private void OnOreSearchComplete(bool success, IMyVoxelBase foundVoxel, string oreName, IEnumerable <Vector3D> positions) { Log.DebugLog("success: " + success + ", foundVoxel: " + foundVoxel + ", oreName: " + oreName, Logger.severity.DEBUG); if (!success) { Log.DebugLog("No ore target found", Logger.severity.INFO); m_navSet.OnTaskComplete_NavRot(); m_navSet.Settings_Commands.Complaint = InfoString.StringId.NoOreFound; return; } m_targetVoxel = foundVoxel; m_oreName = oreName; if (m_approachFinders != null) { m_approachFinders.Clear(); } else { ResourcePool.Get(out m_approachFinders); } Vector3D centre = TargetVoxel.GetCentre(); double minSpace = 4d * m_grid.LocalVolume.Radius; foreach (Vector3D pos in positions) { Vector3D deposit = pos; if (deposit == centre) { deposit += 1; } m_approachFinders.Add(new DepositFreeSpace(TargetVoxel, ref deposit, minSpace)); if (m_approachFinders.Count == MaxDeposits) { break; } } Log.DebugLog("Created " + m_approachFinders.Count + " finders for " + oreName); m_stage = Stage.GetApproach; }
private void ProcessPoolResources(ResourcePool <Course> pool) { Parallel.For(1, 100, (i, loopState) => { var course = pool.Get(); try { Console.WriteLine($"Student Name: {course.GetStudentById(i)}"); } finally { pool.Return(course); } if (_cancellationTokenSource.Token.IsCancellationRequested) { loopState.Stop(); } }); }
/// <summary> /// Send a LastSeen to one or more NetworkStorage. Faster than looping through the collection and invoking Receive() for each one. /// </summary> public static void Receive(ICollection <RelayStorage> storage, LastSeen seen) { HashSet <RelayStorage> sendToSet = ResourcePool <HashSet <RelayStorage> > .Get(); try { foreach (RelayStorage sto in storage) { AddStorage(sendToSet, sto); } foreach (RelayStorage sto in sendToSet) { using (sto.lock_lastSeen.AcquireExclusiveUsing()) sto.in_Receive(seen); } } finally { sendToSet.Clear(); ResourcePool <HashSet <RelayStorage> > .Return(sendToSet); } }
private static void RequestValues() { if (MyAPIGateway.Multiplayer.IsServer) { throw new Exception("Cannot request values, this is the server"); } List <byte> bytes; ResourcePool.Get(out bytes); bytes.Clear(); ByteConverter.AppendBytes(bytes, MessageHandler.SubMod.SyncRequest); ByteConverter.AppendBytes(bytes, MyAPIGateway.Multiplayer.MyId); Logger.DebugLog("requesting values from server"); if (!MyAPIGateway.Multiplayer.SendMessageToServer(MessageHandler.ModId, bytes.ToArray())) { Logger.AlwaysLog("Failed to send message, length: " + bytes.Count, Logger.severity.ERROR); } bytes.Clear(); ResourcePool.Return(bytes); }
public Manager(MathboxRenderer mathboxRenderer) { MathboxRenderer = mathboxRenderer; Pool = new ResourcePool(mathboxRenderer); WIP = Pool.Get(); }
/// <summary> /// Check opts, load/unload /// </summary> public void Update100() { if (m_holoEntities.Count != 0 && DateTime.UtcNow >= m_clearAllAt) { Log.DebugLog("clearing all holo entities"); foreach (SeenHolo sh in m_holoEntities.Values) { Log.DebugLog("removing " + sh.Seen.Entity.EntityId + "from m_holoEntities (clear all)"); OnRemove(sh); } m_holoEntities.Clear(); } if (!Enabled) { return; } Vector3D playerPos = MyAPIGateway.Session.Player.GetPosition(), holoCentre = m_offset.ToWorld(m_block); double distSquared = Vector3D.DistanceSquared(playerPos, holoCentre); m_playerCanSee = distSquared <= 1e4d; if (m_playerCanSee && distSquared > 100d) { List <MyLineSegmentOverlapResult <MyEntity> > entitiesInRay = ResourcePool <List <MyLineSegmentOverlapResult <MyEntity> > > .Get(); m_playerCanSee = false; MyEntity[] ignore = new MyEntity[] { (MyEntity)MyAPIGateway.Session.Player.Controller.ControlledEntity }; foreach (Vector3 vector in Static.Directions) { LineD ray = new LineD(playerPos, holoCentre + vector * m_radiusHolo); MyGamePruningStructure.GetTopmostEntitiesOverlappingRay(ref ray, entitiesInRay); if (!RayCast.Obstructed(ray, entitiesInRay.Select(overlap => overlap.Element), ignore)) { m_playerCanSee = true; entitiesInRay.Clear(); break; } entitiesInRay.Clear(); } ResourcePool <List <MyLineSegmentOverlapResult <MyEntity> > > .Return(entitiesInRay); } if (!m_playerCanSee) { return; } RelayStorage storage = m_netClient.GetStorage(); if (storage == null) { ((IMyTerminalBlock)m_block).AppendCustomInfo("No network connection"); return; } m_clearAllAt = DateTime.UtcNow + Static.keepInCache; storage.ForEachLastSeen(CreateHolo); foreach (SeenHolo sh in m_holoEntities.Values) { if (CanDisplay(sh.Seen)) { if (!sh.Holo.Render.Visible) { Log.DebugLog("showing holo: " + sh.Seen.Entity.getBestName()); SetupProjection(sh.Holo); SetVisible(sh.Holo, true); } if (sh.Seen.Entity is MyCubeGrid && sh.ColouredByIntegrity != ((m_options & Option.IntegrityColours) != 0)) { if (sh.ColouredByIntegrity) { RestoreColour(sh); } else { ColourByIntegrity(sh); } } } else if (sh.Holo.Render.Visible) { Log.DebugLog("hiding holo: " + sh.Seen.Entity.getBestName()); SetVisible(sh.Holo, false); } } if (m_holoEntitiesRemove.Count != 0) { foreach (long entityId in m_holoEntitiesRemove) { Log.DebugLog("removing " + entityId + "from m_holoEntities"); SeenHolo sh; if (!m_holoEntities.TryGetValue(entityId, out sh)) { // this may be normal Log.DebugLog("not in m_holoEntities: " + entityId, Logger.severity.WARNING); continue; } OnRemove(sh); m_holoEntities.Remove(entityId); } m_holoEntitiesRemove.Clear(); } }
/// <summary> /// Commits the assembled display list for rendering and initializes a new batch for assembly /// </summary> /// <param name="erase">indicates whether the target buffer should be erased before redering this display list</param> public void CommitDisplayList(bool erase) { WIP.Commit(erase); RenderQueue.Enqueue(WIP); WIP = Pool.Get(); }
private void Display(List <long> entityIds = null) { if (entityIds != null) { UpdateInstructions(); } //Log.DebugLog("Building display list", "Display()", Logger.severity.TRACE); RelayStorage store = m_networkClient.GetStorage(); if (store == null) { //m_textPanel.WritePublicText("No network connection"); m_textSurface.WriteText("No network connection"); return; } m_sortableList = ResourcePool <List <sortableLastSeen> > .Get(); if (entityIds == null) { AllLastSeen(store); } else { SelectLastSeen(store, entityIds); } if (m_sortableList.Count == 0) { //m_textPanel.WritePublicText("No entities detected"); m_textSurface.WriteText("No entities detected"); m_sortableList.Clear(); ResourcePool <List <sortableLastSeen> > .Return(m_sortableList); return; } m_lastDisplay = Globals.ElapsedTime; m_sortableList.Sort(); StringBuilder displayText = new StringBuilder(); displayText.Append(timeString); displayText.Append(DateTime.Now.ToLongTimeString()); displayText.AppendLine(); int count = 0; foreach (sortableLastSeen sortable in m_sortableList) { sortable.TextForPlayer(displayText, count++); if (count >= 20) { break; } } m_sortableList.Clear(); ResourcePool <List <sortableLastSeen> > .Return(m_sortableList); string displayString = displayText.ToString(); //Log.DebugLog("Writing to panel: " + m_textPanel.DisplayNameText + ":\n\t" + displayString, "Display()", Logger.severity.TRACE); //m_textPanel.WritePublicText(displayText.ToString()); m_textPanel.WriteText(displayText.ToString()); }
/// <summary> /// Tests if the ship is obstructed by any voxel. /// </summary> /// <param name="input"><see cref="TestInput"/></param> /// <param name="result"><see cref="VoxelTestResult"/></param> /// <returns>True iff a voxel is obstructing the ship.</returns> public bool RayCastIntersectsVoxel(ref TestInput input, out VoxelTestResult result) { Profiler.StartProfileBlock(); Logger.DebugLog("direction vector is invalid: " + input.Direction, Logger.severity.FATAL, condition: !input.Direction.IsValid() || Math.Abs(1f - input.Direction.LengthSquared()) > 0.01f); Logger.TraceLog(input.ToString()); if (input.Length < 1f) { // need to skip as Proximity doesn't work with short capsules // should be safe, as the ship got here somehow Logger.TraceLog("Input length is small, no voxel test necessary"); result = VoxelTestResult.Default; result.Distance = input.Length; result.Proximity = 1f; return(false); } Vector3D currentPosition = AutopilotGrid.GetCentre(); Vector3 startOffset; Vector3.Multiply(ref input.Direction, StartRayCast, out startOffset); Vector3D startOffsetD = startOffset; Vector3D totalOffset; Vector3D.Add(ref input.Offset, ref startOffsetD, out totalOffset); CapsuleD capsule; Vector3D.Add(ref currentPosition, ref totalOffset, out capsule.P0); Vector3D capsuleDisp; { capsuleDisp.X = input.Direction.X * input.Length; capsuleDisp.Y = input.Direction.Y * input.Length; capsuleDisp.Z = input.Direction.Z * input.Length; } Vector3D.Add(ref capsule.P0, ref capsuleDisp, out capsule.P1); capsule.Radius = AutopilotGrid.PositionComp.LocalVolume.Radius; //Logger.DebugLog("current position: " + currentPosition + ", offset: " + offset + ", line: " + rayDirectionLength + ", start: " + capsule.P0 + ", end: " + capsule.P1); result = VoxelTestResult.Default; Vector3D hitPosition; float proximity = (float)CapsuleDExtensions.ProximityToVoxel(ref capsule, out result.ObstructingVoxel, out hitPosition, true, input.Length); result.Proximity = 10f * proximity; // lie because we have not done a proper test but could have a very nice result if (proximity > 1f) { Logger.TraceLog("Large capsule DOES NOT intersect voxel: " + capsule.String() + ", proximity: " + proximity + "/" + result.Proximity); result.Distance = input.Length; Profiler.EndProfileBlock(); return(false); } Logger.TraceLog("Large capsule DOES intersect voxel: " + capsule.String() + ", proximity: " + proximity + "/" + result.Proximity); IEnumerable <CubeGridCache> myCaches = AttachedGrid.AttachedGrids(AutopilotGrid, AttachedGrid.AttachmentKind.Physics, true).Select(CubeGridCache.GetFor); Vector3 v; input.Direction.CalculatePerpendicularVector(out v); Vector3 w; Vector3.Cross(ref input.Direction, ref v, out w); Matrix to3D = new Matrix(v.X, v.Y, v.Z, 0f, w.X, w.Y, w.Z, 0f, input.Direction.X, input.Direction.Y, input.Direction.Z, 0f, 0f, 0f, 0f, 1f); Matrix to2D; Matrix.Invert(ref to3D, out to2D); Vector2IMatrix <Vector3D> apShipRejections; ResourcePool.Get(out apShipRejections); MatrixD worldMatrix = AutopilotGrid.WorldMatrix; float gridSize = AutopilotGrid.GridSize; foreach (CubeGridCache cache in myCaches) { if (cache == null) { Logger.DebugLog("Missing a cache", Logger.severity.DEBUG); Profiler.EndProfileBlock(); return(false); } foreach (Vector3I cell in cache.OccupiedCells()) { Vector3 local = cell * gridSize; Vector3D world; Vector3D.Transform(ref local, ref worldMatrix, out world); Vector3D offsetWorld; Vector3D.Add(ref world, ref totalOffset, out offsetWorld); Vector3D relative; Vector3D.Subtract(ref offsetWorld, ref currentPosition, out relative); Vector3 relativeF = relative; Vector3 rejection; Vector3.Reject(ref relativeF, ref input.Direction, out rejection); Vector3 planarComponents; Vector3.Transform(ref rejection, ref to2D, out planarComponents); Logger.DebugLog("Math fail: rejection: " + rejection + ", planar components: " + planarComponents + "\nto3D: " + to3D, Logger.severity.FATAL, condition: planarComponents.Z > 0.001f || planarComponents.Z < -0.001f); Vector2 pc2 = new Vector2(planarComponents.X, planarComponents.Y); apShipRejections.Add(ToCell(pc2, gridSize), offsetWorld); } } Vector2IMatrix <bool> testedRejections; ResourcePool.Get(out testedRejections); const int allowedEmpty = 2; foreach (KeyValuePair <Vector2I, Vector3D> cell in apShipRejections.MiddleOut()) { //Logger.DebugLog("Cell was not set: " + cell, Logger.severity.FATAL, condition: cell.Value == Vector3D.Zero); if (!testedRejections.Add(cell.Key, true)) { continue; } int ringIndex = 0; m_insideRing.Clear(); int biggestRingSq = 0; while (true) { int consecutiveEmpty = 0; ExpandingRings.Ring ring = ExpandingRings.GetRing(ringIndex++); foreach (Vector2I ringOffset in ring.Squares) { if (apShipRejections.Contains(ringOffset + cell.Key)) { consecutiveEmpty = 0; } else { consecutiveEmpty++; if (consecutiveEmpty > allowedEmpty) { goto GotRing; } } } m_insideRing.AddArray(ring.Squares); biggestRingSq = ring.DistanceSquared; } GotRing: foreach (Vector2I ringOffset in m_insideRing) { testedRejections.Add(ringOffset + cell.Key, true); } capsule.P0 = cell.Value; Vector3D.Add(ref capsule.P0, ref capsuleDisp, out capsule.P1); capsule.Radius = (1f + (float)Math.Sqrt(biggestRingSq)) * gridSize; result.Proximity = (float)CapsuleDExtensions.ProximityToVoxel(ref capsule, out result.ObstructingVoxel, out hitPosition, true, input.Length); if (result.Proximity <= 1f) { Logger.TraceLog("Block capsule does hit voxel: " + capsule.String() + ", proxmity: " + result.Proximity); double distance; Vector3D.Distance(ref capsule.P0, ref hitPosition, out distance); result.Distance = (float)distance; apShipRejections.Clear(); testedRejections.Clear(); ResourcePool.Return(apShipRejections); ResourcePool.Return(testedRejections); Profiler.EndProfileBlock(); return(true); } } Logger.TraceLog("Ship's path is clear from voxels, proximity: " + result.Proximity); apShipRejections.Clear(); testedRejections.Clear(); ResourcePool.Return(apShipRejections); ResourcePool.Return(testedRejections); Profiler.EndProfileBlock(); return(false); }
/// <summary> /// Tests a grid for obstructing the ship via vector rejection. /// </summary> /// <param name="oGrid">The grid that may obstruct this one.</param> /// <param name="ignoreBlock">Block to ignore, or null</param> /// <param name="input"><see cref="TestInput"/></param> /// <param name="result"><see cref="GridTestResult"/></param> /// <returns>True if oGrid is blocking the ship.</returns> private bool RejectionIntersects(MyCubeGrid oGrid, MyCubeBlock ignoreBlock, ref TestInput input, ref GridTestResult result) { //Logger.DebugLog("Rejection vector is not normalized, length squared: " + rejectionVector.LengthSquared(), Logger.severity.FATAL, condition: Math.Abs(rejectionVector.LengthSquared() - 1f) > 0.001f); //Logger.DebugLog("Testing for rejection intersection: " + oGrid.nameWithId() + ", starting from: " + (AutopilotGrid.GetCentre() + offset) + ", rejection vector: " + rejectionVector + ", distance: " + rejectionDistance + // ", final: " + (AutopilotGrid.GetCentre() + offset + rejectionVector * rejectionDistance)); //Logger.DebugLog("rejction distance < 0: " + rejectionDistance, Logger.severity.ERROR, condition: rejectionDistance < 0f); IEnumerable <CubeGridCache> myCaches = AttachedGrid.AttachedGrids(AutopilotGrid, AttachedGrid.AttachmentKind.Physics, true).Select(CubeGridCache.GetFor); Vector3D currentPosition = AutopilotGrid.GetCentre(); CubeGridCache oCache = CubeGridCache.GetFor(oGrid); if (oCache == null) { Logger.DebugLog("Failed to get cache for other grid", Logger.severity.DEBUG); return(false); } bool checkBlock = ignoreBlock != null && oGrid == ignoreBlock.CubeGrid; Vector3 v; input.Direction.CalculatePerpendicularVector(out v); Vector3 w; Vector3.Cross(ref input.Direction, ref v, out w); Matrix to3D = new Matrix(v.X, v.Y, v.Z, 0f, w.X, w.Y, w.Z, 0f, input.Direction.X, input.Direction.Y, input.Direction.Z, 0f, 0f, 0f, 0f, 1f); Matrix to2D; Matrix.Invert(ref to3D, out to2D); float roundTo; int minDistanceSquared; if (AutopilotGrid.GridSizeEnum == oGrid.GridSizeEnum) { roundTo = AutopilotGrid.GridSize; minDistanceSquared = 1; } else { roundTo = Math.Min(AutopilotGrid.GridSize, oGrid.GridSize); minDistanceSquared = (int)Math.Ceiling(Math.Max(AutopilotGrid.GridSize, oGrid.GridSize) / roundTo); minDistanceSquared *= minDistanceSquared; } int maxDistanceSquared = minDistanceSquared * 100; Profiler.StartProfileBlock("RejectionIntersects:Build ship"); Vector2IMatrix <bool> apShipRejections; ResourcePool.Get(out apShipRejections); MatrixD worldMatrix = AutopilotGrid.WorldMatrix; float gridSize = AutopilotGrid.GridSize; float minProjection = float.MaxValue, maxProjection = float.MinValue; // the permitted range when rejecting the other grids cells foreach (CubeGridCache cache in myCaches) { if (cache == null) { Logger.DebugLog("Missing a cache", Logger.severity.DEBUG); Profiler.EndProfileBlock(); return(false); } foreach (Vector3I cell in cache.OccupiedCells()) { Vector3 local = cell * gridSize; MyCubeBlock block = (MyCubeBlock)cache.CubeGrid.GetCubeBlock(cell)?.FatBlock; if (block != null && block.Subparts != null && block.Subparts.Count != 0 && !CellOccupiedByBlock(cell, block)) { continue; } Vector3D world; Vector3D.Transform(ref local, ref worldMatrix, out world); Vector3D relative; Vector3D.Subtract(ref world, ref currentPosition, out relative); Vector3 relativeF = relative; float projectionDistance; Vector3 rejection; VectorExtensions.RejectNormalized(ref relativeF, ref input.Direction, out projectionDistance, out rejection); if (projectionDistance < minProjection) { minProjection = projectionDistance; } else if (projectionDistance > maxProjection) { maxProjection = projectionDistance; } Vector3 planarComponents; Vector3.Transform(ref rejection, ref to2D, out planarComponents); //Logger.DebugLog("Math fail: rejection: " + rejection + ", planar components: " + planarComponents + "\nto3D: " + to3D, Logger.severity.WARNING, condition: planarComponents.Z > 0.001f || planarComponents.Z < -0.001f); Vector2 pc2 = new Vector2(planarComponents.X, planarComponents.Y); apShipRejections[ToCell(pc2, roundTo)] = true; //Logger.DebugLog("My rejection: " + rejection + ", planar: " + ToCell(pc2, roundTo)); } } Profiler.EndProfileBlock(); minProjection += StartRayCast; // allow autopilot to move away from a touching object //Logger.DebugLog("projection min: " + minProjection + ", max: " + maxProjection + ", max for other: " + (maxProjection + rejectionDistance)); maxProjection += input.Length; //Logger.DebugLog("checking other grid cells"); Profiler.StartProfileBlock("RejectionIntersects:other grid"); Vector2IMatrix <bool> otherGridRejections; ResourcePool.Get(out otherGridRejections); worldMatrix = oGrid.WorldMatrix; gridSize = oGrid.GridSize; foreach (Vector3I cell in oCache.OccupiedCells()) { //Logger.DebugLog("cell: " + cell); Vector3 local = cell * gridSize; Vector3D world; Vector3D.Transform(ref local, ref worldMatrix, out world); Vector3D offsetWorld; Vector3D.Subtract(ref world, ref input.Offset, out offsetWorld); Vector3D relative; Vector3D.Subtract(ref offsetWorld, ref currentPosition, out relative); Vector3 relativeF = relative; Vector3 rejection; VectorExtensions.RejectNormalized(ref relativeF, ref input.Direction, out result.Distance, out rejection); if (result.Distance < minProjection || result.Distance > maxProjection) { continue; } Vector3 planarComponents; Vector3.Transform(ref rejection, ref to2D, out planarComponents); //Logger.DebugLog("Math fail: rejection: " + rejection + ", planar components: " + planarComponents + "\nto3D: " + to3D, Logger.severity.WARNING, condition: planarComponents.Z > 0.001f || planarComponents.Z < -0.001f); Vector2 pc2 = new Vector2(planarComponents.X, planarComponents.Y); Vector2I cell2D = ToCell(pc2, roundTo); if (!otherGridRejections.Add(cell2D, true)) { //Logger.DebugLog("Already tested: " + cell2D); continue; } //Logger.DebugLog("Rejection: " + rejection + ", planar: " + cell2D); //Logger.DebugLog("testing range. x: " + (cell2D.X - steps) + " - " + (cell2D.X + steps)); ExpandingRings.Ring ring = default(ExpandingRings.Ring); for (int ringIndex = 0; ring.DistanceSquared <= maxDistanceSquared; ringIndex++) { ring = ExpandingRings.GetRing(ringIndex); for (int squareIndex = 0; squareIndex < ring.Squares.Length; squareIndex++) { if (apShipRejections.Contains(cell2D + ring.Squares[squareIndex])) { if (ring.DistanceSquared <= minDistanceSquared) { IMySlimBlock slim = oGrid.GetCubeBlock(cell); if (slim != null) { if (checkBlock && slim.FatBlock == ignoreBlock) { continue; } MyCubeBlock fat = (MyCubeBlock)slim.FatBlock; if (fat != null && fat.Subparts != null && fat.Subparts.Count != 0 && !CellOccupiedByBlock(cell, fat)) { continue; } result.ObstructingBlock = fat; } else { result.ObstructingBlock = null; } result.Proximity = 0f; Logger.DebugLog("Hit, projectionDistance: " + result.Distance + ", min: " + minProjection + ", max: " + maxProjection + ", ring: " + ringIndex + ", ring dist sq: " + ring.DistanceSquared + ", min dist sq: " + minDistanceSquared + ", max dist sq: " + maxDistanceSquared); Profiler.EndProfileBlock(); apShipRejections.Clear(); otherGridRejections.Clear(); ResourcePool.Return(apShipRejections); ResourcePool.Return(otherGridRejections); return(true); } else { maxDistanceSquared = ring.DistanceSquared; goto NextCell; } } } } NextCell :; } Profiler.EndProfileBlock(); apShipRejections.Clear(); otherGridRejections.Clear(); ResourcePool.Return(apShipRejections); ResourcePool.Return(otherGridRejections); result.Proximity = (float)Math.Sqrt(maxDistanceSquared); return(false); }
protected UIElement GetResourceFromPool() { return(pool.Get()); }