Ejemplo n.º 1
0
        /*
         * static public Boolean CheckCoolDown(String name, out int timeLeft)
         * {
         *      timeLeft = 0;
         *      DockingCooldownItem item = null;
         *      var list = PluginDocking.CooldownList.FindAll(n => n.name.ToLower() == name.ToLower()); // Change to FirstOrDefault
         *      foreach (DockingCooldownItem i in list)
         *      {
         *              item = i;
         *              break;
         *      }
         *
         *      if (item != null)
         *      {
         *              timeLeft = (int)(20.0 - (DateTime.Now - item.startTime).TotalSeconds);
         *              if (timeLeft <= 0)
         *              {
         *                      PluginDocking.CooldownList.Remove(item);
         *                      item = null;
         *              }
         *      }
         *
         *      return item != null;
         * }
         */

        static public bool CheckForIntersection(Dictionary <String, List <IMyCubeBlock> > testList, List <IMyCubeBlock> beaconList, out int intersectElement)
        {
            Boolean intersects = false;

            intersectElement = 0;
            OrientedBoundingBoxD targetTestBounding = GetBoundingBox(beaconList);

            if (testList.Count > 0)
            {
                for (int r = 0; r < testList.Count; r++)
                {
                    List <IMyCubeBlock> beaconTestList = (List <IMyCubeBlock>)testList.ElementAt(r).Value;
                    if (beaconTestList.Count != 4)
                    {
                        continue;
                    }

                    OrientedBoundingBoxD testBounding = GetBoundingBox(beaconTestList);
                    if (testBounding.Contains(ref targetTestBounding) != ContainmentType.Disjoint)
                    {
                        intersectElement = r;
                        intersects       = true;
                        break;
                    }
                }
            }

            return(intersects);
        }
Ejemplo n.º 2
0
        private static bool IntersectsVoxelSurface(OrientedBoundingBoxD box)
        {
            var data = VoxelData;

            using (PoolManager.Get(out List <MyEntity> entities))
            {
                MyGamePruningStructure.GetTopmostEntitiesInBox(box.GetAABB(), entities, MyEntityQueryType.Static);
                foreach (var ent in entities)
                {
                    if (ent is MyVoxelBase voxel && !(ent is MyVoxelPhysics))
                    {
                        var invWorld      = voxel.PositionComp.WorldMatrixInvScaled;
                        var storageBounds = BoundingBoxD.CreateInvalid();
                        var voxelOffset   = (voxel.Size >> 1) + voxel.StorageMin;
                        var storageObb    = box;
                        storageObb.Transform(invWorld);
                        storageObb.HalfExtent /= voxel.VoxelSize;
                        storageObb.Center      = storageObb.Center / voxel.VoxelSize + voxelOffset;
                        storageBounds.Include(storageObb.GetAABB());

                        var storageMin = Vector3I.Max(Vector3I.Floor(storageBounds.Min), voxel.StorageMin);
                        var storageMax = Vector3I.Min(Vector3I.Ceiling(storageBounds.Max), voxel.StorageMax);
                        var localBox   = new BoundingBoxI(storageMin, storageMax);
                        localBox.Inflate(1);
                        var floatBox = new BoundingBox(localBox);
                        if (voxel.IntersectStorage(ref floatBox) == ContainmentType.Disjoint)
                        {
                            continue;
                        }
                        data.Resize(storageMin, storageMax);
                        voxel.Storage.ReadRange(data, MyStorageDataTypeFlags.Content, 0, storageMin, storageMax);
                        foreach (var pt in new BoundingBoxI(Vector3I.Zero, storageMax - storageMin).EnumeratePoints())
                        {
                            var voxelBox    = new BoundingBoxD(storageMin + pt, storageMin + pt + 1);
                            var containment = storageObb.Contains(ref voxelBox);
                            if (containment == ContainmentType.Disjoint)
                            {
                                continue;
                            }
                            var tmpPt   = pt;
                            var index   = data.ComputeLinear(ref tmpPt);
                            var content = data.Content(index);
                            if (containment == ContainmentType.Intersects && content >= 127)
                            {
                                return(true);
                            }
                            if (containment == ContainmentType.Contains && content > 0)
                            {
                                return(true);
                            }
                        }
                    }
                }
            }

            return(false);
        }
Ejemplo n.º 3
0
        public static void DisableItemsIn(OrientedBoundingBoxD box)
        {
            var worldBox = box.GetAABB();

            using (PoolManager.Get(out List <MyEntity> entities))
            {
                MyEntities.GetTopMostEntitiesInBox(ref worldBox, entities);
                foreach (var entity in entities)
                {
                    (entity as MyVoxelBase)?.DisableFarmingItemsIn(box);
                }
            }
        }
        public static bool AnyBlocksInAABB(this MyGridDataComponent g, BoundingBoxD box)
        {
            var e = g.Entity;

            if (e.PositionComp == null)
            {
                return(false);
            }
            if (box.Contains(e.PositionComp.WorldAABB) == ContainmentType.Contains)
            {
                return(g.BlockCount > 0);
            }

            var orientedBoundingBoxD = OrientedBoundingBoxD.Create(box, e.PositionComp.WorldMatrixNormalizedInv);
            var sizeR = 1f / g.Size;

            orientedBoundingBoxD.Center     *= sizeR;
            orientedBoundingBoxD.HalfExtent *= sizeR;
            box = box.TransformFast(e.PositionComp.WorldMatrixNormalizedInv);
            var min    = box.Min;
            var max    = box.Max;
            var obbPt1 = new Vector3I((int)Math.Round(min.X * sizeR), (int)Math.Round(min.Y * sizeR), (int)Math.Round(min.Z * sizeR));
            var obbPt2 = new Vector3I((int)Math.Round(max.X * sizeR), (int)Math.Round(max.Y * sizeR), (int)Math.Round(max.Z * sizeR));
            var obbMin = Vector3I.Min(obbPt1, obbPt2);
            var obbMax = Vector3I.Max(obbPt1, obbPt2);
            var start  = Vector3I.Max(obbMin, g.Min);
            var end    = Vector3I.Min(obbMax, g.Max);

            if (start.X > end.X || start.Y > end.Y || start.Z > end.Z)
            {
                return(false);
            }
            var vector3IRangeIterator = new Vector3I_RangeIterator(ref start, ref end);
            var next = vector3IRangeIterator.Current;

            while (vector3IRangeIterator.IsValid())
            {
                if (g.GetAnyBlock(next) != null)
                {
                    return(true);
                }
                vector3IRangeIterator.GetNext(out next);
            }

            return(false);
        }
Ejemplo n.º 5
0
        public static bool IsGridInside(IMyCubeGrid dockingEntity, List <IMyCubeBlock> beaconList)
        {
            // Get bounding box of both the docking zone and docking ship
            OrientedBoundingBoxD targetBounding  = Entity.GetBoundingBox(beaconList);
            OrientedBoundingBoxD dockingBounding = Entity.GetBoundingBox(dockingEntity);

            // If the docking entity is bigger in some way than the zone, this will fail (docking ship larger than dock) ???
            if (!Entity.GreaterThan(dockingBounding.HalfExtent * 2, targetBounding.HalfExtent * 2))
            {
                return(false);
            }

            // Make sure the docking zone contains the docking ship.  If they intersect or are disjointed, then fail
            if (targetBounding.Contains(ref dockingBounding) != ContainmentType.Contains)
            {
                return(false);
            }

            return(true);
        }
Ejemplo n.º 6
0
        public static void DisableFarmingItemsIn(this MyVoxelBase voxel, OrientedBoundingBoxD box)
        {
            if (voxel.Hierarchy == null)
            {
                return;
            }
            var worldBox = box.GetAABB();

            _working.Clear();
            voxel.Hierarchy.QueryBounds(in worldBox, _working);
            foreach (var entity in _working)
            {
                var sector = entity as MyEnvironmentSector;
                if (sector == null)
                {
                    continue;
                }
                var tmp = box;
                sector.DisableItemsInObb(ref tmp);
            }

            _working.Clear();
        }
Ejemplo n.º 7
0
        public static void DisableFarmingItemsIn(this MyVoxelBase voxel, OrientedBoundingBoxD worldObb)
        {
            if (voxel.Hierarchy == null)
            {
                return;
            }
            var worldAabb = worldObb.GetAABB();

            using (PoolManager.Get(out List <MyEntity> working))
            {
                voxel.Hierarchy.QueryBounds(in worldAabb, working);
                foreach (var entity in working)
                {
                    var sector = entity as MyEnvironmentSector;
                    if (sector == null)
                    {
                        continue;
                    }
                    var tmp = worldObb;
                    sector.DisableItemsInObb(ref tmp);
                }
            }
        }
Ejemplo n.º 8
0
        public override bool HandleCommand(ulong userId, string[] words)
        {
            if (!PluginSettings.Instance.DockingEnabled)
            {
                return(false);
            }

            if (words.Length < 1)
            {
                Communication.SendPrivateInformation(userId, GetHelp());
                return(true);
            }

            if (m_docking)
            {
                Communication.SendPrivateInformation(userId, "Server is busy");
                return(true);
            }

            m_docking = true;
            try
            {
                string pylonName = string.Join(" ", words);

                /*
                 * int timeLeft;
                 * if (Entity.CheckCoolDown(pylonName, out timeLeft))
                 * {
                 *      Communication.Message(String.Format("The docking zone '{0}' is on cooldown.  Please wait a {1} seconds before trying to dock/undock again.", pylonName, Math.Max(0, timeLeft)));
                 *      return;
                 * }
                 */

                if (PlayerMap.Instance.GetPlayerIdsFromSteamId(userId).Count < 1)
                {
                    Communication.SendPrivateInformation(userId, $"Unable to find player Id: {userId}");
                    return(true);
                }

                long playerId = PlayerMap.Instance.GetPlayerIdsFromSteamId(userId).First();

                Dictionary <string, List <IMyCubeBlock> > testList;
                List <IMyCubeBlock> beaconList;
                DockingZone.FindByName(pylonName, out testList, out beaconList, playerId);
                if (beaconList.Count == 4)
                {
                    // Check ownership
                    foreach (IMyCubeBlock entityBlock in beaconList)
                    {
                        IMyTerminalBlock terminal = (IMyTerminalBlock)entityBlock;
                        if (!terminal.HasPlayerAccess(playerId))
                        {
                            Communication.SendPrivateInformation(userId, $"You do not have permission to use '{pylonName}'.  You must either own all the beacons or they must be shared with faction.");
                            return(true);
                        }
                    }

                    // Check for bounding box intsection of other docking zones
                    int intersectElement = 0;
                    if (Entity.CheckForIntersection(testList, beaconList, out intersectElement))
                    {
                        Communication.SendPrivateInformation(userId, $"The docking zone '{pylonName}' intersects with docking zone '{testList.ElementAt( intersectElement ).Key}'.  Make sure you place your docking zones so they don't overlap.");
                        return(true);
                    }

                    // Check if ship already docked in this zone
                    IMyCubeBlock       e             = beaconList[0];
                    IMyCubeGrid        parent        = (IMyCubeGrid)e.Parent;
                    long[]             beaconListIds = beaconList.Select(b => b.EntityId).ToArray();
                    long               ownerId       = beaconList.First().OwnerId;
                    List <DockingItem> checkItems    = Docking.Instance.Find(d => d.PlayerId == ownerId && d.TargetEntityId == parent.EntityId && d.DockingBeaconIds.Intersect(beaconListIds).Count() == 4);
                    if (checkItems.Count >= PluginSettings.Instance.DockingShipsPerZone)
                    {
                        Communication.SendPrivateInformation(userId, $"Docking zone '{pylonName}' already contains the maximum capacity of ships.");
                        return(true);
                    }

                    // Figure out center of docking area, and other distance information
                    double   maxDistance = 99;
                    Vector3D vPos        = new Vector3D(0, 0, 0);

                    foreach (IMyCubeBlock b in beaconList)
                    {
                        Vector3D beaconPos = Entity.GetBlockEntityPosition(b);
                        vPos += beaconPos;
                    }

                    vPos = vPos / 4;
                    foreach (IMyCubeBlock b in beaconList)
                    {
                        Vector3D beaconPos = Entity.GetBlockEntityPosition(b);
                        maxDistance = Math.Min(maxDistance, Vector3D.Distance(vPos, beaconPos));
                    }

                    // Find ship in docking area
                    IMyCubeGrid         dockingEntity = null;
                    HashSet <IMyEntity> cubeGrids     = new HashSet <IMyEntity>();
                    Wrapper.GameAction(() =>
                    {
                        MyAPIGateway.Entities.GetEntities(cubeGrids, f => f is IMyCubeGrid);
                    });
                    foreach (IMyCubeGrid gridCheck in cubeGrids)
                    {
                        if (gridCheck.IsStatic || gridCheck == parent)
                        {
                            continue;
                        }

                        double distance = Vector3D.Distance(gridCheck.GetPosition(), vPos);
                        if (distance < maxDistance)
                        {
                            dockingEntity = gridCheck;
                            break;
                        }
                    }

                    // Figure out if the ship fits in docking area, and then save ship
                    if (dockingEntity != null)
                    {
                        // Get bounding box of both the docking zone and docking ship
                        OrientedBoundingBoxD targetBounding  = Entity.GetBoundingBox(beaconList);
                        OrientedBoundingBoxD dockingBounding = Entity.GetBoundingBox(dockingEntity);

                        // Make sure the docking zone contains the docking ship.  If they intersect or are disjointed, then fail
                        if (!Entity.GreaterThan(dockingBounding.HalfExtent * 2, targetBounding.HalfExtent * 2))
                        {
                            Communication.SendPrivateInformation(userId, $"The ship '{dockingEntity.DisplayName}' is too large for it's carrier.  The ship's bounding box must fit inside the docking zone bounding box!");
                            return(true);
                        }

                        if (targetBounding.Contains(ref dockingBounding) != ContainmentType.Contains)
                        {
                            Communication.SendPrivateInformation(userId, $"The ship '{dockingEntity.DisplayName}' is not fully inside the docking zone '{pylonName}'.  Make sure the ship is fully contained inside the docking zone");
                            return(true);
                        }

                        // Calculate the mass and ensure the docking ship is less than half the mass of the dock
                        float parentMass  = Entity.CalculateMass(parent);
                        float dockingMass = Entity.CalculateMass(dockingEntity);
                        if (dockingMass > parentMass)
                        {
                            Communication.SendPrivateInformation(userId, $"The ship you're trying to dock is too heavy for it's carrier.  The ship mass must be less than half the large ship / stations mass! (DM={dockingMass}kg CM={parentMass}kg)");
                            return(true);
                        }

                        // Check to see if the ship is piloted, if it is, error out.
                        // TODO: Check to see if we can get a real time copy of this entity?
                        List <IMySlimBlock> blocks = new List <IMySlimBlock>();
                        dockingEntity.GetBlocks(blocks, x => x.FatBlock is MyCockpit);
                        foreach (IMySlimBlock slim in blocks)
                        {
                            //MyObjectBuilder_Cockpit c = (MyObjectBuilder_Cockpit)slim.FatBlock.GetObjectBuilderCubeBlock();
                            var c = (MyShipController)slim.FatBlock;
                            if (c.Pilot != null)
                            {
                                Communication.SendPrivateInformation(userId, $"Ship in docking zone '{pylonName}' has a pilot!  Please exit the ship before trying to dock.  (Sometimes this can lag a bit.  Wait 10 seconds and try again)");
                                return(true);
                            }
                        }

                        // Save position and rotation information.  Some fun stuff here.
                        // Get our dock rotation as a quaternion
                        Quaternion saveQuat = Quaternion.CreateFromRotationMatrix(parent.WorldMatrix.GetOrientation());
                        // Transform docked ship's local position by inverse of the the parent (unwinds parent) and save it for when we undock
                        Vector3D savePos = Vector3D.Transform(dockingEntity.GetPosition() - parent.GetPosition(), Quaternion.Inverse(saveQuat));
                        // Get local rotation of dock ship, and save it for when we undock
                        saveQuat = Quaternion.Inverse(saveQuat) * Quaternion.CreateFromRotationMatrix(dockingEntity.WorldMatrix.GetOrientation());

                        // Save ship to file and remove
                        FileInfo info = new FileInfo(Path.Combine(Essentials.PluginPath, "Docking", $"docked_{ownerId}_{parent.EntityId}_{dockingEntity.EntityId}.sbc"));
                        if (!Directory.Exists(info.DirectoryName))
                        {
                            Directory.CreateDirectory(info.DirectoryName);
                        }
                        //CubeGridEntity dockingGrid = new CubeGridEntity((MyObjectBuilder_CubeGrid)dockingEntity.GetObjectBuilder(), dockingEntity);
                        MyObjectBuilder_CubeGrid gridBuilder = CubeGrids.SafeGetObjectBuilder(dockingEntity);
                        if (gridBuilder == null)
                        {
                            Communication.SendPrivateInformation(userId, $"Failed to load entity for export: {dockingEntity.DisplayName}");
                            return(true);
                        }

                        // Save item
                        DockingItem dockItem = new DockingItem
                        {
                            DockedEntityId   = dockingEntity.EntityId,
                            TargetEntityId   = parent.EntityId,
                            PlayerId         = ownerId,
                            DockingBeaconIds = beaconList.Select(s => s.EntityId).ToArray( ),
                            DockedName       = dockingEntity.DisplayName,
                            SavePos          = savePos,
                            SaveQuat         = saveQuat
                        };
                        Docking.Instance.Add(dockItem);

                        // Serialize and save ship to file
                        MyObjectBuilderSerializer.SerializeXML(info.FullName, false, gridBuilder);
                        Wrapper.BeginGameAction(() => dockingEntity.Close( ));

                        Communication.SendPrivateInformation(userId, $"Docked ship '{dockItem.DockedName}' in docking zone '{pylonName}'.");
                        Log.Info("Docked ship \"{0}\" in docking zone \"{1}\". Saved to {2}", dockItem.DockedName, pylonName, info.FullName);

                        /*
                         * // Add a cool down
                         * DockingCooldownItem cItem = new DockingCooldownItem();
                         * cItem.name = pylonName;
                         * cItem.startTime = DateTime.Now;
                         * PluginDocking.CooldownList.Add(cItem);
                         */
                    }
                    else
                    {
                        Communication.SendPrivateInformation(userId, $"No ships in docking zone '{pylonName}'.");
                    }
                }
                else if (beaconList.Count > 4)
                {
                    Communication.SendPrivateInformation(userId, $"Too many beacons with the name or another zone with the name '{pylonName}'.  Place only 4 beacons to create a zone or try a different zone name.");
                }
                else
                {
                    Communication.SendPrivateInformation(userId, string.Format("Can not locate docking zone '{0}'.  There must be 4 beacons with the name '{0}' to create a docking zone.  Beacons must be fully built!", pylonName));
                }

                return(true);
            }
            catch (SecurityException ex)
            {
                Log.Error("Can't access docked ship file.", ex);
                return(false);
            }
            catch (UnauthorizedAccessException ex)
            {
                Log.Error("Can't access docked ship file.", ex);
                return(false);
            }
            catch (DirectoryNotFoundException ex)
            {
                Log.Error("Directory does not exist", ex);
                return(false);
            }
            catch (IOException ex)
            {
                Log.Error(ex);
                return(false);
            }
            finally
            {
                m_docking = false;
            }
        }
Ejemplo n.º 9
0
        public static bool DoGrading(
            IReadOnlyList <IRailGradeComponent> components, Vector3D target, float radius, uint availableForDeposit,
            uint availableForExcavate,
            uint[] excavatedByMaterial, byte materialToDeposit, out uint totalDeposited, out uint totalExcavated,
            bool testDynamic, out bool triedToChange, out bool intersectedDynamic)
        {
            try
            {
                var voxelRadius = (int)Math.Ceiling(radius);
                {
                    _dynamicEntities.Clear();
                    _workingVoxels.Clear();
                    var sphere = new BoundingSphereD(target, voxelRadius + 2);
                    var tmp    = MyEntities.GetEntitiesInSphere(ref sphere);
                    using (tmp.GetClearToken())
                        foreach (var e in tmp)
                        {
                            if (e is MyVoxelBase vox)
                            {
                                _workingVoxels.Add(vox);
                            }
                            if (e.Physics != null && !e.Physics.IsStatic)
                            {
                                _dynamicEntities.Add(e);
                            }
                        }
                }


                totalDeposited     = 0;
                totalExcavated     = 0;
                triedToChange      = false;
                intersectedDynamic = false;

                var fill     = new IGradeShape[components.Count];
                var excavate = new IGradeShape[components.Count];
                for (var i = 0; i < components.Count; i++)
                {
                    components[i].Unblit(out fill[i], out excavate[i]);
                }

                var voxel = MyGamePruningStructureSandbox.GetClosestPlanet(target)?.RootVoxel;
                if (voxel == null)
                {
                    return(false);
                }
                Vector3I center;
                MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref target, out center);
                var voxMin = center - voxelRadius - 1;
                var voxMax = center + voxelRadius + 1;
                _storage.Resize(voxMin, voxMax);
                voxel.Storage.ReadRange(_storage, MyStorageDataTypeFlags.ContentAndMaterial, 0, voxMin, voxMax);

                var changed = false;

                #region Mutate

                for (var i = 0;
                     i <= voxelRadius && (!triedToChange || availableForExcavate > 0 || availableForDeposit > 0);
                     i++)
                {
                    for (var e = new ShellEnumerator(center - i, center + i);
                         e.MoveNext() && (!triedToChange || availableForExcavate > 0 || availableForDeposit > 0);)
                    {
                        var      vCoord    = e.Current;
                        var      dataCoord = e.Current - voxMin;
                        Vector3D worldCoord;
                        MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxel.PositionLeftBottomCorner, ref vCoord,
                                                                      out worldCoord);
                        var cval = _storage.Get(MyStorageDataTypeEnum.Content, ref dataCoord);

                        byte?excavationDensity = null;
                        if (cval > 0 && (!triedToChange || availableForExcavate > 0))
                        {
                            float density = 0;
                            foreach (var c in excavate.Where(x => x != null))
                            {
                                density = Math.Max(density, c.GetDensity(ref worldCoord));
                            }
                            if (density > 0)
                            {
                                excavationDensity = (byte)((1 - density) * byte.MaxValue);
                            }
                        }

                        byte?fillDensity = null;
                        if (cval < byte.MaxValue && (!triedToChange || availableForDeposit > 0))
                        {
                            float density = 0;
                            foreach (var c in fill.Where(x => x != null))
                            {
                                density = Math.Max(density, c.GetDensity(ref worldCoord));
                            }
                            if (density > 0)
                            {
                                fillDensity = (byte)(density * byte.MaxValue);
                            }
                        }

                        if ((!fillDensity.HasValue || cval >= fillDensity.Value) &&
                            (!excavationDensity.HasValue || cval <= excavationDensity.Value))
                        {
                            continue;
                        }

                        if (excavationDensity.HasValue && excavationDensity.Value < cval)
                        {
                            triedToChange = true;
                            var toExtract = (uint)Math.Min(availableForExcavate, cval - excavationDensity.Value);
                            if (toExtract > 0)
                            {
                                var mid = _storage.Get(MyStorageDataTypeEnum.Material, ref dataCoord);
                                if (excavatedByMaterial != null && mid < excavatedByMaterial.Length)
                                {
                                    excavatedByMaterial[mid] += toExtract;
                                }
                                DisableFarming(worldCoord);
                                _storage.Set(MyStorageDataTypeEnum.Content, ref dataCoord, (byte)(cval - toExtract));
                                totalExcavated       += toExtract;
                                availableForExcavate -= toExtract;
                                changed = true;
                            }

                            continue;
                        }

                        if (!fillDensity.HasValue || fillDensity.Value <= cval)
                        {
                            continue;
                        }
                        triedToChange = true;
                        var toFill = Math.Min(availableForDeposit, fillDensity.Value - cval);
                        if (toFill <= 0)
                        {
                            continue;
                        }

                        // would this deposit in midair?
                        {
                            var test = worldCoord;
                            test += 2 * Vector3D.Normalize(
                                MyGravityProviderSystem.CalculateNaturalGravityInPoint(worldCoord));
                            Vector3I vtest;
                            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref test,
                                                                          out vtest);
                            vtest = Vector3I.Clamp(vtest, voxMin, voxMax) - voxMin;
                            if (vtest != vCoord && _storage.Get(MyStorageDataTypeEnum.Content, ref vtest) == 0)
                            {
                                continue;
                            }
                        }

                        // would it touch something dynamic?
                        if (testDynamic)
                        {
                            var box = new BoundingBoxD(worldCoord - 0.25, worldCoord + 0.25);
                            var bad = false;
                            foreach (var k in _dynamicEntities)
                            {
                                if (k.PositionComp.WorldAABB.Contains(box) == ContainmentType.Disjoint)
                                {
                                    continue;
                                }
                                var obb = new OrientedBoundingBoxD(k.PositionComp.LocalAABB, k.WorldMatrix);
                                if (!obb.Intersects(ref box))
                                {
                                    continue;
                                }
                                bad = true;
                                break;
                            }

                            if (bad)
                            {
                                intersectedDynamic = true;
                                continue;
                            }
                        }

                        changed = true;
                        DisableFarming(worldCoord);
                        availableForDeposit = (uint)(availableForDeposit - toFill);
                        totalDeposited     += (uint)toFill;
                        _storage.Set(MyStorageDataTypeEnum.Content, ref dataCoord, (byte)(cval + toFill));
                        if (fillDensity.Value <= cval * 1.25f)
                        {
                            continue;
                        }
                        var t = -Vector3I.One;
                        for (var itrContent = new Vector3I_RangeIterator(ref t, ref Vector3I.One);
                             itrContent.IsValid();
                             itrContent.MoveNext())
                        {
                            var tpos = dataCoord + itrContent.Current;
//                    var state = _storage.Get(MyStorageDataTypeEnum.Content, ref tpos);
//                    if (itrContent.Current == Vector3I.Zero || state == 0)
                            _storage.Set(MyStorageDataTypeEnum.Material, ref tpos, materialToDeposit);
                        }
                    }
                }

                #endregion Mutate

                if (changed)
                {
                    voxel.Storage.WriteRange(_storage, MyStorageDataTypeFlags.ContentAndMaterial, voxMin, voxMax);
                }

                return(changed);
            }
            finally
            {
                _dynamicEntities.Clear();
                _workingVoxels.Clear();
            }
        }
Ejemplo n.º 10
0
        private static int PerformVoxelOpInternal(
            List <MyVoxelBase> voxels,
            List <OrientedBoundingBoxD> boxes,
            byte replacementMaterial,
            int materialLimit,
            VoxelMiningBuffer miningBuffer,
            bool disableFarmingItems)
        {
            var data         = VoxelData;
            var usedMaterial = 0;

            using (PoolManager.Get(out List <OrientedBoundingBoxD> storageBoxes))
                foreach (var voxel in voxels)
                {
                    if (materialLimit < usedMaterial)
                    {
                        break;
                    }
                    var invWorld      = voxel.PositionComp.WorldMatrixInvScaled;
                    var storageBounds = BoundingBoxD.CreateInvalid();
                    storageBoxes.Clear();
                    var voxelOffset = (voxel.Size >> 1) + voxel.StorageMin;
                    foreach (var obb in boxes)
                    {
                        var storageObb = obb;
                        storageObb.Transform(invWorld);
                        storageObb.HalfExtent /= voxel.VoxelSize;
                        storageObb.Center      = storageObb.Center / voxel.VoxelSize + voxelOffset;
                        storageBoxes.Add(storageObb);
                        storageBounds.Include(storageObb.GetAABB());
                    }

                    var storageMin = Vector3I.Max(Vector3I.Floor(storageBounds.Min), voxel.StorageMin);
                    var storageMax = Vector3I.Min(Vector3I.Ceiling(storageBounds.Max), voxel.StorageMax);
                    var localBox   = new BoundingBox(storageMin, storageMax);
                    localBox.Translate(-voxel.SizeInMetresHalf - voxel.StorageMin);
                    if (voxel.IntersectStorage(ref localBox, false) == ContainmentType.Disjoint)
                    {
                        continue;
                    }
                    data.Resize(storageMin, storageMax);
                    voxel.Storage.ReadRange(data, MyStorageDataTypeFlags.ContentAndMaterial, 0, storageMin, storageMax);
                    var modified       = false;
                    var modifiedVoxels = BoundingBoxD.CreateInvalid();
                    foreach (var pt in new BoundingBoxI(Vector3I.Zero, storageMax - storageMin).EnumeratePoints())
                    {
                        if (materialLimit < usedMaterial)
                        {
                            break;
                        }
                        var contained = false;
                        var voxelBox  = new BoundingBoxD(storageMin + pt, storageMin + pt + 1);
                        foreach (var storageBox in storageBoxes)
                        {
                            if (storageBox.Intersects(ref voxelBox))
                            {
                                contained = true;
                                break;
                            }
                        }

                        if (!contained)
                        {
                            continue;
                        }
                        var tmpPt   = pt;
                        var index   = data.ComputeLinear(ref tmpPt);
                        var content = data.Content(index);
                        if (content <= 0)
                        {
                            continue;
                        }
                        var material = data.Material(index);
                        if (material == replacementMaterial)
                        {
                            continue;
                        }

                        usedMaterial += content;
                        miningBuffer?.Add(material, content);
                        data.Material(index, replacementMaterial);
                        modified = true;
                        modifiedVoxels.Include(voxelBox);
                    }

                    if (!modified)
                    {
                        continue;
                    }
                    voxel.Storage.WriteRange(data, MyStorageDataTypeFlags.Material, storageMin, storageMax);
                    if (!disableFarmingItems)
                    {
                        continue;
                    }
                    modifiedVoxels.Min = (modifiedVoxels.Min - voxelOffset) * voxel.VoxelSize;
                    modifiedVoxels.Max = (modifiedVoxels.Max - voxelOffset) * voxel.VoxelSize;
                    voxel.DisableFarmingItemsIn(OrientedBoundingBoxD.Create(modifiedVoxels, voxel.WorldMatrix));
                }

            return(usedMaterial);
        }