public WeldBlock(Mover mover, AllNavigationSettings navSet, PseudoBlock welder, IMySlimBlock block) : base(mover, navSet) { this.m_logger = new Logger(GetType().Name, () => mover.Block.CubeGrid.DisplayName, () => block.getBestName(), () => m_stage.ToString()); this.m_offset = welder.Block.LocalAABB.GetLongestDim() * 0.5f; // this works for default welders, may not work if mod has an exotic design this.m_welder = welder; this.m_targetSlim = block; this.m_timeout_start = Globals.UpdateCount + TimeoutStart; IMyCubeBlock Projector = ((MyCubeGrid)block.CubeGrid).Projector; if (Projector != null) { this.m_weldProjection = true; this.m_otherGrid = Projector.CubeGrid; this.m_slimTarget_initDmg = 1f; this.m_targetCell = Projector.CubeGrid.WorldToGridInteger(block.CubeGrid.GridIntegerToWorld(block.Position)); } else { this.m_weldProjection = false; this.m_slimTarget_initDmg = block.Damage(); this.m_targetCell = block.Position; } m_navSet.Settings_Task_NavEngage.NavigatorMover = this; m_navSet.Settings_Task_NavEngage.NavigatorRotator = this; m_navSet.Settings_Task_NavEngage.DestinationEntity = m_realGrid; IEnumerator<Vector3I> neighbours = this.m_targetSlim.ForEachNeighbourCell(); while (neighbours.MoveNext()) { Vector3I cell = m_weldProjection ? Projector.CubeGrid.WorldToGridInteger(block.CubeGrid.GridIntegerToWorld(neighbours.Current)) : neighbours.Current; m_neighbours.Add(cell); if (this.m_realGrid.GetCubeBlock(cell) == null) m_emptyNeighbours.Add(cell); } m_targetSlim.ComputeWorldCenter(out m_targetWorld); m_lineUp.To = m_targetWorld; }
private void CubeGrid_OnBlockRemoved(IMySlimBlock obj) { IMyCubeBlock fatblock = obj.FatBlock; if (fatblock == null) return; myLogger.debugLog("block removed: " + obj.getBestName()); myLogger.debugLog("block removed: " + obj.FatBlock.DefinitionDisplayNameText + "/" + obj.getBestName()); lock_CubeBlocks.AcquireExclusive(); try { // by type MyObjectBuilderType myOBtype = fatblock.BlockDefinition.TypeId; ListSnapshots<IMyCubeBlock> setBlocks_Type; if (!CubeBlocks_Type.TryGetValue(myOBtype, out setBlocks_Type)) { myLogger.debugLog("failed to get list of type: " + myOBtype); return; } if (setBlocks_Type.Count == 1) CubeBlocks_Type.Remove(myOBtype); else setBlocks_Type.mutable().Remove(fatblock); // by definition IMyTerminalBlock asTerm = obj.FatBlock as IMyTerminalBlock; if (asTerm != null) TerminalBlocks--; } catch (Exception e) { myLogger.alwaysLog("Exception: " + e, Logger.severity.ERROR); } finally { lock_CubeBlocks.ReleaseExclusive(); } myLogger.debugLog("leaving CubeGrid_OnBlockRemoved(): " + obj.getBestName()); }
/// <summary> /// Find the closest damaged block that can be repaired; either the missing components are available or there are no missing components. /// </summary> /// <returns>The closest repairable block to the welders.</returns> private IMySlimBlock FindClosestRepairable() { Log.DebugLog("searching for closest repairable block"); if (m_damagedBlocks.Count == 0) { if (m_projectedBlocks.Count != 0) { ProjectedToDamaged(); } if (m_damagedBlocks.Count == 0) { GetDamagedBlocks(); if (m_damagedBlocks.Count == 0) { return(null); } } } GetInventoryItems(); IMySlimBlock repairable = null; double closest = float.MaxValue; List <IMySlimBlock> removeList = null; foreach (IMySlimBlock slim in m_damagedBlocks) { if (slim.Closed()) { Log.DebugLog("slim closed: " + slim.getBestName()); continue; } if (slim.Damage() == 0f && ((MyCubeGrid)slim.CubeGrid).Projector == null) { Log.DebugLog("already repaired: " + slim.getBestName(), Logger.severity.DEBUG); if (removeList == null) { removeList = new List <IMySlimBlock>(); } removeList.Add(slim); continue; } Vector3D position; slim.ComputeWorldCenter(out position); double dist = Vector3D.DistanceSquared(m_controlBlock.CubeBlock.GetPosition(), position); if (dist < closest) { m_components_missing.Clear(); if (slim.Damage() != 0f) { GetMissingComponents(slim); } else { // slim is projection GetAllComponents(slim); } bool haveItem = false; foreach (string component in m_components_missing.Keys) { if (m_components_inventory.ContainsKey(component)) { haveItem = true; break; } } if (haveItem || m_components_missing.Count == 0) { repairable = slim; closest = dist; } } } if (removeList != null) { foreach (IMySlimBlock remove in removeList) { m_damagedBlocks.Remove(remove); } } Log.DebugLog(() => "closest repairable block: " + repairable.getBestName(), Logger.severity.DEBUG, condition: repairable != null); return(repairable); }
/// <summary> /// <para>Test line segment between startPosition and targetPosition for obstructing entities.</para> /// <para>Tests for obstructing voxel map, character, or grid.</para> ///// <param name="shortTest">When checking voxels, shortens the line by 1 m, needed to interact with an entity that may be on the surface of the voxel.</param> /// </summary> public static bool Obstructed <Tobstruct, Tignore>(LineD line, IEnumerable <Tobstruct> potentialObstructions, IEnumerable <Tignore> ignoreList, bool checkVoxel = true, bool checkPlanet = DefaultCheckPlanet) //, bool shortTest = true) where Tobstruct : IMyEntity where Tignore : IMyEntity { Profiler.StartProfileBlock(); // Test each entity foreach (IMyEntity entity in potentialObstructions) { if (entity.Closed) { continue; } if (ignoreList != null && ignoreList.Contains((Tignore)entity)) { continue; } IMyCharacter asChar = entity as IMyCharacter; if (asChar != null) { double distance; if (entity.WorldAABB.Intersects(ref line, out distance)) { Logger.DebugLog("obstructed by character: " + entity.getBestName()); Profiler.EndProfileBlock(); return(true); } continue; } IMyCubeGrid asGrid = entity as IMyCubeGrid; if (asGrid != null) { if (!asGrid.Save) { continue; } ICollection <Vector3I> allHitCells; List <Vector3I> hitCells = new List <Vector3I>(); asGrid.RayCastCells(line.From, line.To, hitCells); allHitCells = hitCells; foreach (Vector3I pos in allHitCells) { IMySlimBlock slim = asGrid.GetCubeBlock(pos); if (slim == null) { continue; } MyCubeBlock fatblock = (MyCubeBlock)slim.FatBlock; if (fatblock != null) { if (ignoreList != null && ignoreList.Contains((Tignore)slim.FatBlock)) { continue; } Dictionary <string, MyEntitySubpart> subparts = fatblock.Subparts; if (subparts != null && subparts.Count != 0) { Vector3 gsPosition = pos * asGrid.GridSize; BoundingBox gsAABB; fatblock.CombinedAABB(out gsAABB); if (gsAABB.Contains(gsPosition) == ContainmentType.Disjoint) { continue; } } } Logger.DebugLog("obstructed by block: " + slim.getBestName() + " on " + slim.CubeGrid.DisplayName + ", id: " + slim.CubeGrid.EntityId); Profiler.EndProfileBlock(); return(true); } } } if (checkVoxel) { // Voxel Test MyVoxelBase hitVoxel; Vector3D hitPosition; if (RayCastVoxels(line, out hitVoxel, out hitPosition, checkPlanet)) { Logger.DebugLog("obstructed by voxel: " + hitVoxel + " at " + hitPosition); Profiler.EndProfileBlock(); return(true); } } // no obstruction found Profiler.EndProfileBlock(); return(false); }
public override void Move() { if (m_targetSlim.Closed()) { Log.DebugLog("target block closed: " + m_targetSlim.getBestName(), Logger.severity.INFO); m_navSet.OnTaskComplete_NavEngage(); EnableWelders(false); return; } m_targetSlim.ComputeWorldCenter(out m_targetWorld); if (m_stage == Stage.Retreat) { Retreat(); return; } float offsetSquared = m_offset + OffsetAdd + OffsetAdd; offsetSquared *= offsetSquared; if (Vector3.DistanceSquared(m_welder.WorldPosition, m_targetWorld) > offsetSquared) { EnableWelders(false); if (m_closestEmptyNeighbour.HasValue && Globals.UpdateCount > m_timeout_start) { Log.DebugLog("failed to start, dropping neighbour: " + m_closestEmptyNeighbour, Logger.severity.DEBUG); if (m_emptyNeighbours.Count > 1) { m_emptyNeighbours.Remove(m_closestEmptyNeighbour.Value); m_closestEmptyNeighbour = null; } else { Log.DebugLog("tried every empty neighbour, giving up", Logger.severity.INFO); EnableWelders(false); m_stage = Stage.Retreat; return; } } if (!m_closestEmptyNeighbour.HasValue) { GetClosestEmptyNeighbour(); if (!m_closestEmptyNeighbour.HasValue) { Log.DebugLog("tried every empty neighbour, giving up", Logger.severity.INFO); EnableWelders(false); m_stage = Stage.Retreat; return; } m_timeout_start = Globals.UpdateCount + TimeoutStart; Vector3D from = m_realGrid.GridIntegerToWorld(m_closestEmptyNeighbour.Value); m_lineUp.From = m_lineUp.To + (from - m_lineUp.To) * 100d; } Vector3 closestPoint = m_lineUp.ClosestPoint(m_welder.WorldPosition); if (Vector3.DistanceSquared(m_welder.WorldPosition, closestPoint) > 1f || m_navSet.Settings_Current.DistanceAngle > 0.1f) { m_stage = Stage.Lineup; Destination dest = Destination.FromWorld(m_realGrid, m_lineUp.ClosestPoint(m_welder.WorldPosition)); m_pathfinder.MoveTo(destinations: dest); return; } else // linedup up { m_stage = Stage.Approach; } } else // near target { m_stage = Stage.Weld; EnableWelders(true); } MoveToTarget(); }