bool IsBlockPlaceable(IMySlimBlock Block)
        {
            MyCubeGrid Grid = Block.CubeGrid as MyCubeGrid;

            if (Grid.Projector == null)
            {
                return(false);
            }

            BuildCheckResult CheckResult = (Grid.Projector as IMyProjector).CanBuild(Block, true);

            return(CheckResult == BuildCheckResult.OK);
        }
Пример #2
0
        private void UpdateBuildCheckResult(BuildCheckResult result)
        {
            m_result = result;

            switch (result)
            {
            case BuildCheckResult.OK:
                m_preview.GetComponent <Renderer>().material = PreviewMaterials[0].Material;
                break;

            case BuildCheckResult.FAIL:
                m_preview.GetComponent <Renderer>().material = PreviewMaterials[1].Material;
                break;
            }
        }
Пример #3
0
 public ProjectionRaycastData(BuildCheckResult result, MySlimBlock cubeBlock, MyProjectorBase projector)
 {
     raycastResult = result;
     hitCube = cubeBlock;
     cubeProjector = projector;
 }
Пример #4
0
 public ProjectionRaycastData(BuildCheckResult result, MySlimBlock cubeBlock, MyProjectorBase projector)
 {
     raycastResult = result;
     hitCube       = cubeBlock;
     cubeProjector = projector;
 }
Пример #5
0
 public BuildRequest(MyEntityDefinitionId?definition, SolarSystem ss, Vector3D position, Quaternion orientation, BuildCheckResult result)
 {
     Definition = definition; SolarSystem = ss; Position = position; Orientation = orientation; BuildCheckResult = result;
 }
        private bool StepWeld(ShipyardItem shipyardItem)
        {
            var targetsToRemove = new HashSet <BlockTarget>();
            var targetsToRedraw = new HashSet <BlockTarget>();

            //we need to multiply this by MyShipWelder.WELDER_AMOUNT_PER_SECOND / 2, which also evaluates to 1
            float weldAmount = MyAPIGateway.Session.WelderSpeedMultiplier * shipyardItem.Settings.WeldMultiplier;
            float boneAmount = weldAmount * .1f;

            if (shipyardItem.TargetBlocks.Count == 0)
            {
                var sortBlock = Profiler.Start(FullName, nameof(StepWeld), "Sort Targets");
                shipyardItem.TargetBlocks.Clear();
                shipyardItem.ProxDict.Clear();
                //precalculate all the BlockTarget for our target grids to speed things up
                var gridTargets = new Dictionary <long, List <BlockTarget> >();
                foreach (IMyCubeGrid targetGrid in shipyardItem.YardGrids)
                {
                    if (targetGrid.Closed || targetGrid.MarkedForClose)
                    {
                        continue;
                    }

                    var tmpBlocks = new List <IMySlimBlock>();
                    targetGrid.GetBlocks(tmpBlocks);

                    gridTargets.Add(targetGrid.EntityId, new List <BlockTarget>(tmpBlocks.Count));
                    foreach (IMySlimBlock block in tmpBlocks.ToArray())
                    {
                        if (block == null || (block.CubeGrid.Physics != null && block.IsFullIntegrity && !block.HasDeformation))
                        {
                            continue;
                        }

                        var target = new BlockTarget(block, shipyardItem);

                        shipyardItem.TargetBlocks.Add(target);

                        gridTargets[targetGrid.EntityId].Add(target);
                    }

                    //Shouldn't be needed as this is handled by the projector logic in BlockTarget

                    //var proj = targetGrid.Projector();
                    //if (proj != null && !shipyardItem.YardGrids.Contains(proj.CubeGrid))
                    //{
                    //    proj.CubeGrid.GetBlocks(tmpBlocks);
                    //    gridTargets.Add(proj.CubeGrid.EntityId, new List<BlockTarget>());
                    //    foreach (var block in tmpBlocks.ToArray())
                    //    {
                    //        if (block == null || (targetGrid.Physics != null && block.IsFullIntegrity && !block.HasDeformation))
                    //            continue;

                    //        var pos = block.GetPosition();
                    //        if (!shipyardItem.ShipyardBox.Contains(ref pos))
                    //            continue;

                    //        var target = new BlockTarget(block, shipyardItem);

                    //        shipyardItem.TargetBlocks.Add(target);
                    //        gridTargets[block.CubeGrid.EntityId].Add(target);
                    //    }
                    //}
                }
                int count = 0;
                foreach (KeyValuePair <long, List <BlockTarget> > entry in gridTargets)
                {
                    count += entry.Value.Count;
                }

                foreach (IMyCubeBlock tool in shipyardItem.Tools)
                {
                    shipyardItem.ProxDict.Add(tool.EntityId, new List <BlockTarget>());
                    //first sort grids by distance to tool
                    shipyardItem.YardGrids.Sort((a, b) =>
                                                Vector3D.DistanceSquared(a.Center(), tool.GetPosition()).CompareTo(
                                                    Vector3D.DistanceSquared(b.Center(), tool.GetPosition())));

                    foreach (IMyCubeGrid grid in shipyardItem.YardGrids)
                    {
                        //then sort blocks by distance to grid center
                        List <BlockTarget> list = gridTargets[grid.EntityId];
                        switch (shipyardItem.Settings.BuildPattern)
                        {
                        case BuildPatternEnum.FromProjector:
                            list.Sort((a, b) => a.ProjectorDist.CompareTo(b.ProjectorDist));
                            break;

                        case BuildPatternEnum.FromCenter:
                            list.Sort((a, b) => a.CenterDist.CompareTo(b.CenterDist));
                            break;

                        case BuildPatternEnum.FromCorners:
                            list.Sort((a, b) => a.ToolDist[tool.EntityId].CompareTo(b.ToolDist[tool.EntityId]));
                            break;

                        default:
                            throw new Exception("Invalid BuildPatternEnum");
                        }
                        shipyardItem.ProxDict[tool.EntityId].AddRange(list);
                    }
                }
                sortBlock.End();
            }

            //nothing to do
            if (shipyardItem.TargetBlocks.Count == 0)
            {
                Logging.Instance.WriteDebug("TargetBlocks 0");
                return(false);
            }

            //assign blocks to our welders
            foreach (IMyCubeBlock welder in shipyardItem.Tools)
            {
                for (int i = 0; i < shipyardItem.Settings.BeamCount; i++)
                {
                    if (shipyardItem.BlocksToProcess[welder.EntityId][i] != null)
                    {
                        continue;
                    }

                    var         toRemove   = new List <BlockTarget>();
                    BlockTarget nextTarget = null;

                    foreach (BlockTarget target in shipyardItem.ProxDict[welder.EntityId])
                    {
                        bool found = false;
                        //each block can only have one laser assigned
                        foreach (KeyValuePair <long, BlockTarget[]> entry in shipyardItem.BlocksToProcess)
                        {
                            if (entry.Value.Contains(target))
                            {
                                found = true;
                                break;
                            }
                        }
                        if (found)
                        {
                            toRemove.Add(target);
                            continue;
                        }

                        if (target.Projector != null)
                        {
                            BuildCheckResult res = target.Projector.CanBuild(target.Block, false);
                            if (res == BuildCheckResult.AlreadyBuilt)
                            {
                                target.UpdateAfterBuild();
                            }
                            else if (res != BuildCheckResult.OK)
                            {
                                continue;
                            }
                            else
                            {
                                bool success = false;
                                Utilities.InvokeBlocking(() => success = BuildTarget(target, shipyardItem, welder));
                                Logging.Instance.WriteDebug(success.ToString());
                                if (!success)
                                {
                                    //toRemove.Add(target);
                                    continue;
                                }
                                target.UpdateAfterBuild();
                            }
                        }
                        if (target.CubeGrid.Physics != null && target.Block.IsFullIntegrity && !target.Block.HasDeformation)
                        {
                            toRemove.Add(target);
                            continue;
                        }
                        nextTarget = target;
                        break;
                    }

                    if (nextTarget != null)
                    {
                        targetsToRedraw.Add(nextTarget);
                        shipyardItem.BlocksToProcess[welder.EntityId][i] = nextTarget;
                    }

                    foreach (BlockTarget removeTarget in toRemove)
                    {
                        shipyardItem.ProxDict[welder.EntityId].Remove(removeTarget);
                        shipyardItem.TargetBlocks.Remove(removeTarget);
                    }
                }
            }

            //update lasers
            foreach (KeyValuePair <long, BlockTarget[]> entry in shipyardItem.BlocksToProcess)
            {
                for (int i = 0; i < entry.Value.Length; i++)
                {
                    BlockTarget targetBlock = entry.Value[i];

                    if (targetBlock == null || _stalledTargets.Contains(targetBlock))
                    {
                        continue;
                    }

                    if (targetsToRedraw.Contains(targetBlock))
                    {
                        var toolLine = new Communication.ToolLineStruct
                        {
                            ToolId       = entry.Key,
                            GridId       = targetBlock.CubeGrid.EntityId,
                            BlockPos     = targetBlock.GridPosition,
                            PackedColor  = Color.DarkCyan.PackedValue,
                            Pulse        = false,
                            EmitterIndex = (byte)i
                        };

                        Communication.SendLine(toolLine, shipyardItem.ShipyardBox.Center);
                    }
                }
            }

            if (shipyardItem.BlocksToProcess.All(e => e.Value.All(t => t == null)))
            {
                Logging.Instance.WriteDebug("Null thing?");
                return(false);
            }

            shipyardItem.UpdatePowerUse();
            targetsToRedraw.Clear();

            Utilities.InvokeBlocking(() =>
            {
                foreach (IMyCubeBlock welder in shipyardItem.Tools)
                {
                    var tool = (IMyCollector)welder;
                    MyInventory welderInventory = ((MyEntity)tool).GetInventory();
                    int i = 0;
                    foreach (BlockTarget target in shipyardItem.BlocksToProcess[tool.EntityId])
                    {
                        if (target == null)
                        {
                            continue;
                        }

                        if (target.CubeGrid.Physics == null || target.CubeGrid.Closed || target.CubeGrid.MarkedForClose)
                        {
                            targetsToRemove.Add(target);
                            continue;
                        }

                        if (!MyAPIGateway.Session.CreativeMode)
                        {
                            /*
                             * Welding laser "efficiency" is a float between 0-1 where:
                             *   0.0 =>   0% of component stock used for construction (100% loss)
                             *   1.0 => 100% of component stock used for construction (0% loss)
                             *
                             * Efficiency decay/distance formula is the same as above for grinder
                             */
                            double efficiency = 1 - (target.ToolDist[tool.EntityId] / 200000);
                            if (!shipyardItem.StaticYard)
                            {
                                efficiency /= 2;
                            }
                            if (efficiency < 0.1)
                            {
                                efficiency = 0.1;
                            }
                            //Logging.Instance.WriteDebug(String.Format("Welder[{0}]block[{1}] distance=[{2:F2}m] efficiency=[{3:F5}]", tool.DisplayNameText, i, Math.Sqrt(target.ToolDist[tool.EntityId]), efficiency));

                            /*
                             * We have to factor in our efficiency ratio before transferring to the block "construction stockpile",
                             * but that math isn't nearly as easy as it was with the grinder.
                             *
                             * For each missing component type, we know how many items are "missing" from the construction model, M
                             *
                             * The simplest approach would be to pull M items from the conveyor system (if enabled), then move
                             * (M*efficiency) items to the "construction stockpile" and vaporize the other (M*(1-efficiency)) items.
                             * However, this approach would leave the construction stockpile incomplete and require several iterations
                             * before M items have actually been copied.
                             *
                             * A better solution is to pull enough "extra" items from the conveyors that the welder has enough to
                             * move M items to the construction stockpile even after losses due to distance inefficiency
                             *
                             * For example, if the target block is missing M=9 items and we are running at 0.9 (90%) efficiency,
                             * ideally that means we should pull 10 units, vaporize 1, and still have 9 for construction. However,
                             * if the conveyor system was only able to supply us with 2 components, we should not continue to blindly
                             * vaporize 1 unit.
                             *
                             * Instead, we have to consult the post-conveyor-pull welder inventory to determine if it has at least
                             * the required number of components.  If it does, we vaporize M*(1-efficiency).  Otherwise we only
                             * vaporize current_count*(1-efficiency) and transfer the rest to the construction stockpile
                             */
                            var missingComponents = new Dictionary <string, int>();
                            target.Block.GetMissingComponents(missingComponents);

                            var wasteComponents = new Dictionary <string, int>();
                            foreach (KeyValuePair <string, int> entry in missingComponents)
                            {
                                var componentId            = new MyDefinitionId(typeof(MyObjectBuilder_Component), entry.Key);
                                int missing                = entry.Value;
                                MyFixedPoint totalRequired = (MyFixedPoint)(missing / efficiency);

                                MyFixedPoint currentStock = welderInventory.GetItemAmount(componentId);

                                //Logging.Instance.WriteDebug(String.Format("Welder[{0}]block[{1}] Component[{2}] missing[{3:F3}] inefficiency requires[{4:F3}] in_stock[{5:F3}]", tool.DisplayNameText, i, entry.Key, missing, totalRequired, currentStock));
                                if (currentStock < totalRequired && tool.UseConveyorSystem)
                                {
                                    // Welder doesn't have totalRequired, so try to pull the difference from conveyors
                                    welderInventory.PullAny(shipyardItem.ConnectedCargo, entry.Key, (int)Math.Ceiling((double)(totalRequired - currentStock)));
                                    currentStock = welderInventory.GetItemAmount(componentId);
                                    //Logging.Instance.WriteDebug(String.Format("Welder[{0}]block[{1}] Component[{2}] - after conveyor pull - in_stock[{3:F3}]", tool.DisplayNameText, i, entry.Key, currentStock));
                                }

                                // Now compute the number of components to delete
                                // MoveItemsToConstructionPile() below won't move anything if we have less than 1 unit,
                                // so don't bother "losing" anything due to ineffeciency
                                if (currentStock >= 1)
                                {
                                    // The lesser of (missing, currentStock), times (1 minus) our efficiency fraction
                                    MyFixedPoint toDelete = MyFixedPoint.Min(MyFixedPoint.Floor(currentStock), missing) * (MyFixedPoint)(1 - efficiency);
                                    //Logging.Instance.WriteDebug(String.Format("Welder[{0}]block[{1}] Component[{2}] amount lost due to distance [{3:F3}]", tool.DisplayNameText, i, entry.Key, toDelete));
                                    welderInventory.RemoveItemsOfType((int)toDelete, componentId);
                                }
                            }

                            target.Block.MoveItemsToConstructionStockpile(welderInventory);

                            missingComponents.Clear();
                            target.Block.GetMissingComponents(missingComponents);

                            if (missingComponents.Any() && !target.Block.HasDeformation)
                            {
                                if (_stalledTargets.Add(target))
                                {
                                    targetsToRedraw.Add(target);
                                }
                            }
                            else
                            {
                                if (_stalledTargets.Remove(target))
                                {
                                    targetsToRedraw.Add(target);
                                }
                            }

                            target.Block.IncreaseMountLevel(weldAmount, 0, welderInventory, boneAmount, true);
                            if (target.Block.IsFullIntegrity && !target.Block.HasDeformation)
                            {
                                targetsToRemove.Add(target);
                            }
                        }
                        i++;
                    }
                }
            });

            shipyardItem.MissingComponentsDict.Clear();

            foreach (KeyValuePair <long, BlockTarget[]> entry in shipyardItem.BlocksToProcess)
            {
                for (int i = 0; i < entry.Value.Length; i++)
                {
                    BlockTarget target = entry.Value[i];

                    if (target == null)
                    {
                        continue;
                    }

                    if (targetsToRemove.Contains(target))
                    {
                        Communication.ClearLine(entry.Key, i);
                        _stalledTargets.Remove(target);
                        shipyardItem.TargetBlocks.Remove(target);
                        entry.Value[i] = null;
                        continue;
                    }

                    if (_stalledTargets.Contains(target))
                    {
                        var blockComponents = new Dictionary <string, int>();
                        target.Block.GetMissingComponents(blockComponents);

                        foreach (KeyValuePair <string, int> component in blockComponents)
                        {
                            if (shipyardItem.MissingComponentsDict.ContainsKey(component.Key))
                            {
                                shipyardItem.MissingComponentsDict[component.Key] += component.Value;
                            }
                            else
                            {
                                shipyardItem.MissingComponentsDict.Add(component.Key, component.Value);
                            }
                        }

                        var toolLine = new Communication.ToolLineStruct
                        {
                            ToolId       = entry.Key,
                            GridId       = target.CubeGrid.EntityId,
                            BlockPos     = target.GridPosition,
                            PackedColor  = Color.Purple.PackedValue,
                            Pulse        = true,
                            EmitterIndex = (byte)i
                        };

                        if (targetsToRedraw.Contains(target))
                        {
                            Communication.ClearLine(entry.Key, i);
                            Communication.SendLine(toolLine, shipyardItem.ShipyardBox.Center);
                        }
                        continue;
                    }
                }
            }

            return(true);
        }
Пример #7
0
 public void OnTriggerExit(Collider other)
 {
     Result = BuildCheckResult.OK;
 }
Пример #8
0
 public void OnTriggerStay(Collider other)
 {
     Result = BuildCheckResult.FAIL;
 }