Пример #1
0
        public void ReadRange(MyStorageData target, MyStorageDataTypeFlags dataToRead, int lodIndex, ref Vector3I lodVoxelRangeMin, ref Vector3I lodVoxelRangeMax, ref MyVoxelRequestFlags requestFlags)
        {
            ProfilerShort.Begin(GetType().Name + ".ReadRange");
            try
            {
                const int SUBRANGE_SIZE_SHIFT = 3;
                const int SUBRANGE_SIZE       = 1 << SUBRANGE_SIZE_SHIFT;
                var       threshold           = new Vector3I(SUBRANGE_SIZE);
                var       rangeSize           = lodVoxelRangeMax - lodVoxelRangeMin + 1;
                if ((dataToRead & MyStorageDataTypeFlags.Content) != 0)
                {
                    target.ClearContent(0);
                }

                if ((rangeSize.X <= threshold.X &&
                     rangeSize.Y <= threshold.Y &&
                     rangeSize.Z <= threshold.Z) || !MyFakes.ENABLE_SPLIT_VOXEL_READ_QUERIES)
                {
                    using (m_lock.AcquireSharedUsing())
                    {
                        ReadRangeInternal(target, ref Vector3I.Zero, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags);
                    }
                }
                else
                {
                    // These optimizations don't work when splitting the range.
                    requestFlags &= ~(MyVoxelRequestFlags.OneMaterial | MyVoxelRequestFlags.ContentChecked);
                    MyVoxelRequestFlags flags = requestFlags;

                    // splitting to smaller ranges to make sure the lock is not held for too long, preventing write on update thread
                    // subranges could be aligned to multiple of their size for possibly better performance
                    var steps = (rangeSize - 1) >> SUBRANGE_SIZE_SHIFT;
                    for (var it = new Vector3I.RangeIterator(ref Vector3I.Zero, ref steps); it.IsValid(); it.MoveNext())
                    {
                        flags = requestFlags;
                        var offset = it.Current << SUBRANGE_SIZE_SHIFT;
                        var min    = lodVoxelRangeMin + offset;
                        var max    = min + SUBRANGE_SIZE - 1;
                        Vector3I.Min(ref max, ref lodVoxelRangeMax, out max);
                        Debug.Assert(min.IsInsideInclusive(ref lodVoxelRangeMin, ref lodVoxelRangeMax));
                        Debug.Assert(max.IsInsideInclusive(ref lodVoxelRangeMin, ref lodVoxelRangeMax));
                        using (m_lock.AcquireSharedUsing())
                        {
                            ReadRangeInternal(target, ref offset, dataToRead, lodIndex, ref min, ref max, ref flags);
                        }
                    }

                    // If the storage is consistent this should be fine.
                    requestFlags = flags;
                }
            }
            finally
            {
                ProfilerShort.End();
            }
        }
        private static MyStorageBase Compatibility_LoadCellStorage(int fileVersion, Stream stream)
        {
            //  Size of this voxel map (in voxels)
            Vector3I tmpSize;
            tmpSize.X = stream.ReadInt32();
            tmpSize.Y = stream.ReadInt32();
            tmpSize.Z = stream.ReadInt32();
            var storage = new MyOctreeStorage(null, tmpSize);

            //  Size of data cell in voxels. Has to be the same as current size specified by our constants.
            Vector3I cellSize;
            cellSize.X = stream.ReadInt32();
            cellSize.Y = stream.ReadInt32();
            cellSize.Z = stream.ReadInt32();
            Trace.Assert(cellSize.X == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS &&
                         cellSize.Y == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS &&
                         cellSize.Z == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS);

            Vector3I cellsCount = tmpSize / cellSize;

            Dictionary<byte, MyVoxelMaterialDefinition> mappingTable = null;
            if (fileVersion == STORAGE_TYPE_VERSION_CELL)
            {
                // loading material names->index mappings
                mappingTable = Compatibility_LoadMaterialIndexMapping(stream);
            }
            else if (fileVersion == 1)
            {
                // material name->index mappings were not saved in this version
            }

            var startCoord = Vector3I.Zero;
            var endCoord = new Vector3I(MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS - 1);

            var cache = new MyStorageData();
            cache.Resize(Vector3I.Zero, endCoord);
            Vector3I cellCoord;
            for (cellCoord.X = 0; cellCoord.X < cellsCount.X; cellCoord.X++)
            {
                for (cellCoord.Y = 0; cellCoord.Y < cellsCount.Y; cellCoord.Y++)
                {
                    for (cellCoord.Z = 0; cellCoord.Z < cellsCount.Z; cellCoord.Z++)
                    {
                        MyVoxelRangeType cellType = (MyVoxelRangeType)stream.ReadByteNoAlloc();

                        //  Cell's are FULL by default, therefore we don't need to change them
                        switch (cellType)
                        {
                            case MyVoxelRangeType.EMPTY: cache.ClearContent(MyVoxelConstants.VOXEL_CONTENT_EMPTY); break;
                            case MyVoxelRangeType.FULL: cache.ClearContent(MyVoxelConstants.VOXEL_CONTENT_FULL); break;
                            case MyVoxelRangeType.MIXED:
                                Vector3I v;
                                for (v.X = 0; v.X < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; v.X++)
                                {
                                    for (v.Y = 0; v.Y < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; v.Y++)
                                    {
                                        for (v.Z = 0; v.Z < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; v.Z++)
                                        {
                                            cache.Content(ref v, stream.ReadByteNoAlloc());
                                        }
                                    }
                                }
                                break;
                        }
                        startCoord = cellCoord * MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS;
                        endCoord = startCoord + (MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS - 1);
                        storage.WriteRange(cache, MyStorageDataTypeFlags.Content, ref startCoord, ref endCoord);
                    }
                }
            }

            try
            { // In case materials are not saved, catch any exceptions caused by this.
                // Read materials and indestructible
                for (cellCoord.X = 0; cellCoord.X < cellsCount.X; cellCoord.X++)
                {
                    for (cellCoord.Y = 0; cellCoord.Y < cellsCount.Y; cellCoord.Y++)
                    {
                        for (cellCoord.Z = 0; cellCoord.Z < cellsCount.Z; cellCoord.Z++)
                        {
                            bool isSingleMaterial = stream.ReadByteNoAlloc() == 1;
                            MyVoxelMaterialDefinition material = null;

                            if (isSingleMaterial)
                            {
                                material = Compatibility_LoadCellVoxelMaterial(stream, mappingTable);
                                cache.ClearMaterials(material.Index);
                            }
                            else
                            {
                                byte indestructibleContent;
                                Vector3I voxelCoordInCell;
                                for (voxelCoordInCell.X = 0; voxelCoordInCell.X < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; voxelCoordInCell.X++)
                                {
                                    for (voxelCoordInCell.Y = 0; voxelCoordInCell.Y < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; voxelCoordInCell.Y++)
                                    {
                                        for (voxelCoordInCell.Z = 0; voxelCoordInCell.Z < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; voxelCoordInCell.Z++)
                                        {
                                            material = Compatibility_LoadCellVoxelMaterial(stream, mappingTable);
                                            indestructibleContent = stream.ReadByteNoAlloc();
                                            cache.Material(ref voxelCoordInCell, material.Index);
                                        }
                                    }
                                }
                            }
                            startCoord = cellCoord * MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS;
                            endCoord = startCoord + (MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS - 1);
                            storage.WriteRange(cache, MyStorageDataTypeFlags.Material, ref startCoord, ref endCoord);
                        }
                    }
                }
            }
            catch (EndOfStreamException ex)
            {
                MySandboxGame.Log.WriteLine(ex);
            }

            return storage;
        }
Пример #3
0
        private static MyStorageBase Compatibility_LoadCellStorage(int fileVersion, Stream stream)
        {
            //  Size of this voxel map (in voxels)
            Vector3I tmpSize;

            tmpSize.X = stream.ReadInt32();
            tmpSize.Y = stream.ReadInt32();
            tmpSize.Z = stream.ReadInt32();
            var storage = new MyOctreeStorage(null, tmpSize);

            //  Size of data cell in voxels. Has to be the same as current size specified by our constants.
            Vector3I cellSize;

            cellSize.X = stream.ReadInt32();
            cellSize.Y = stream.ReadInt32();
            cellSize.Z = stream.ReadInt32();
#if !XB1
            Trace.Assert(cellSize.X == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS &&
                         cellSize.Y == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS &&
                         cellSize.Z == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS);
#else // XB1
            System.Diagnostics.Debug.Assert(cellSize.X == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS &&
                                            cellSize.Y == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS &&
                                            cellSize.Z == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS);
#endif // XB1

            Vector3I cellsCount = tmpSize / cellSize;

            Dictionary <byte, MyVoxelMaterialDefinition> mappingTable = null;
            if (fileVersion == STORAGE_TYPE_VERSION_CELL)
            {
                // loading material names->index mappings
                mappingTable = Compatibility_LoadMaterialIndexMapping(stream);
            }
            else if (fileVersion == 1)
            {
                // material name->index mappings were not saved in this version
            }

            var startCoord = Vector3I.Zero;
            var endCoord   = new Vector3I(MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS - 1);

            var cache = new MyStorageData();
            cache.Resize(Vector3I.Zero, endCoord);
            Vector3I cellCoord;
            for (cellCoord.X = 0; cellCoord.X < cellsCount.X; cellCoord.X++)
            {
                for (cellCoord.Y = 0; cellCoord.Y < cellsCount.Y; cellCoord.Y++)
                {
                    for (cellCoord.Z = 0; cellCoord.Z < cellsCount.Z; cellCoord.Z++)
                    {
                        MyVoxelRangeType cellType = (MyVoxelRangeType)stream.ReadByteNoAlloc();

                        //  Cell's are FULL by default, therefore we don't need to change them
                        switch (cellType)
                        {
                        case MyVoxelRangeType.EMPTY: cache.ClearContent(MyVoxelConstants.VOXEL_CONTENT_EMPTY); break;

                        case MyVoxelRangeType.FULL: cache.ClearContent(MyVoxelConstants.VOXEL_CONTENT_FULL); break;

                        case MyVoxelRangeType.MIXED:
                            Vector3I v;
                            for (v.X = 0; v.X < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; v.X++)
                            {
                                for (v.Y = 0; v.Y < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; v.Y++)
                                {
                                    for (v.Z = 0; v.Z < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; v.Z++)
                                    {
                                        cache.Content(ref v, stream.ReadByteNoAlloc());
                                    }
                                }
                            }
                            break;
                        }
                        startCoord = cellCoord * MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS;
                        endCoord   = startCoord + (MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS - 1);
                        storage.WriteRange(cache, MyStorageDataTypeFlags.Content, ref startCoord, ref endCoord);
                    }
                }
            }

            try
            { // In case materials are not saved, catch any exceptions caused by this.
                // Read materials and indestructible
                for (cellCoord.X = 0; cellCoord.X < cellsCount.X; cellCoord.X++)
                {
                    for (cellCoord.Y = 0; cellCoord.Y < cellsCount.Y; cellCoord.Y++)
                    {
                        for (cellCoord.Z = 0; cellCoord.Z < cellsCount.Z; cellCoord.Z++)
                        {
                            bool isSingleMaterial = stream.ReadByteNoAlloc() == 1;
                            MyVoxelMaterialDefinition material = null;

                            if (isSingleMaterial)
                            {
                                material = Compatibility_LoadCellVoxelMaterial(stream, mappingTable);
                                cache.ClearMaterials(material.Index);
                            }
                            else
                            {
                                byte     indestructibleContent;
                                Vector3I voxelCoordInCell;
                                for (voxelCoordInCell.X = 0; voxelCoordInCell.X < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; voxelCoordInCell.X++)
                                {
                                    for (voxelCoordInCell.Y = 0; voxelCoordInCell.Y < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; voxelCoordInCell.Y++)
                                    {
                                        for (voxelCoordInCell.Z = 0; voxelCoordInCell.Z < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; voxelCoordInCell.Z++)
                                        {
                                            material = Compatibility_LoadCellVoxelMaterial(stream, mappingTable);
                                            indestructibleContent = stream.ReadByteNoAlloc();
                                            cache.Material(ref voxelCoordInCell, material.Index);
                                        }
                                    }
                                }
                            }
                            startCoord = cellCoord * MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS;
                            endCoord   = startCoord + (MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS - 1);
                            storage.WriteRange(cache, MyStorageDataTypeFlags.Material, ref startCoord, ref endCoord);
                        }
                    }
                }
            }
            catch (EndOfStreamException ex)
            {
                MySandboxGame.Log.WriteLine(ex);
            }

            return(storage);
        }
Пример #4
0
        public void ReadRange(MyStorageData target, MyStorageDataTypeFlags dataToRead, int lodIndex, ref Vector3I lodVoxelRangeMin, ref Vector3I lodVoxelRangeMax, ref MyVoxelRequestFlags requestFlags)
        {
            ProfilerShort.Begin(GetType().Name + ".ReadRange");

            if ((dataToRead & MyStorageDataTypeFlags.Content) != 0)
            {
                target.ClearContent(0);
            }

            if (requestFlags.HasFlags(MyVoxelRequestFlags.AdviseCache) && lodIndex == 0 && CachedWrites)
            {
                ReadRangeAdviseCache(target, dataToRead, ref lodVoxelRangeMin, ref lodVoxelRangeMax);
                ProfilerShort.End();
                return;
            }

            if (CachedWrites && lodIndex <= VoxelChunk.SizeBits && m_cachedChunks.Count > 0)
            {
                // read occlusion separate
                if (dataToRead.Requests(MyStorageDataTypeEnum.Occlusion))
                {
                    using (m_storageLock.AcquireSharedUsing())
                        ReadRangeInternal(target, ref Vector3I.Zero, MyStorageDataTypeFlags.Occlusion, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags);

                    dataToRead ^= MyStorageDataTypeFlags.Occlusion;
                }

                if (m_tmpChunks == null) m_tmpChunks = new List<VoxelChunk>();

                var lodDiff = VoxelChunk.SizeBits - lodIndex;

                // We fetch which chunks overlap our current range from the chunk tree, then we read all data from storage and apply those changes
                var querybb = new BoundingBox(lodVoxelRangeMin << lodIndex, lodVoxelRangeMax << lodIndex);

                using (m_cacheLock.AcquireSharedUsing())
                    m_cacheMap.OverlapAllBoundingBox(ref querybb, m_tmpChunks, 0, false);

                if (m_tmpChunks.Count > 0)
                {
                    var chunkMin = lodVoxelRangeMin >> lodDiff;
                    var chunkMax = lodVoxelRangeMax >> lodDiff;

                    bool readFromStorage = false;

                    if ((chunkMax - chunkMin + 1).Size > m_tmpChunks.Count)
                    {
                        using (m_storageLock.AcquireSharedUsing())
                            ReadRangeInternal(target, ref Vector3I.Zero, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags);
                        readFromStorage = true;
                    }

                    for (int i = 0; i < m_tmpChunks.Count; ++i)
                    {
                        var chunk = m_tmpChunks[i];
                        var pos = chunk.Coords;

                        var celPos = pos << lodDiff;

                        var lodCkStart = pos << lodDiff;
                        lodCkStart = Vector3I.Max(lodCkStart, lodVoxelRangeMin);

                        var targetOffset = lodCkStart - lodVoxelRangeMin;

                        var lodCkEnd = ((pos + 1) << lodDiff) - 1;
                        lodCkEnd = Vector3I.Min(lodCkEnd, lodVoxelRangeMax);

                        lodCkStart -= celPos;
                        lodCkEnd -= celPos;

                        if ((chunk.Cached & dataToRead) != dataToRead && !readFromStorage)
                        {
                            using (m_storageLock.AcquireSharedUsing())
                                if ((chunk.Cached & dataToRead) != dataToRead)
                                    ReadDatForChunk(chunk, dataToRead);
                        }

                        using (chunk.Lock.AcquireSharedUsing())
                            chunk.ReadLod(target, !readFromStorage ? dataToRead : dataToRead & chunk.Cached, ref targetOffset, lodIndex, ref lodCkStart, ref lodCkEnd);
                    }

                    m_tmpChunks.Clear();
                    ProfilerShort.End();
                    return;
                }
            }

            // all else
            using (m_storageLock.AcquireSharedUsing())
                ReadRangeInternal(target, ref Vector3I.Zero, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags);

            ProfilerShort.End();
        }
        private bool IsValidVoxelTarget(NaniteMiningItem target, IMyEntity entity)
        {
            if (entity == null)
            {
                return(false);
            }

            byte         material2 = 0;
            float        amount = 0;
            IMyVoxelBase voxel = entity as IMyVoxelBase;
            Vector3D     targetMin = target.Position;
            Vector3D     targetMax = target.Position;
            Vector3I     minVoxel, maxVoxel;

            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref targetMin, out minVoxel);
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref targetMax, out maxVoxel);

            MyVoxelBase voxelBase = voxel as MyVoxelBase;

            minVoxel += voxelBase.StorageMin;
            maxVoxel += voxelBase.StorageMin;

            voxel.Storage.ClampVoxel(ref minVoxel);
            voxel.Storage.ClampVoxel(ref maxVoxel);

            MyStorageData cache = new MyStorageData();

            cache.Resize(minVoxel, maxVoxel);
            var flag = MyVoxelRequestFlags.AdviseCache;

            cache.ClearContent(0);
            cache.ClearMaterials(0);

            byte original = 0;

            voxel.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, minVoxel, maxVoxel, ref flag);

            original  = cache.Content(0);
            material2 = cache.Material(0);

            if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY)
            {
                Logging.Instance.WriteLine("[Mining] Content is empty!", 2);
                MyAPIGateway.Utilities.InvokeOnGameThread(() =>
                                                          { AddMinedPosition(target); });
                return(false);
            }

            Logging.Instance.WriteLine($"[Mining] Material: SizeLinear: {cache.SizeLinear}, Size3D: {cache.Size3D}, AboveISO: {cache.ContainsVoxelsAboveIsoLevel()}", 2);
            cache.Content(0, 0);

            var voxelMat = target.Definition;

            target.Amount = CalculateAmount(voxelMat, original * 8f);

            Logging.Instance.WriteLine($"[Mining] Removing: {target.Position} ({material2} {amount})", 2);

            if (material2 == 0)
            {
                Logging.Instance.WriteLine("[Mining] Material is 0", 2);
                MyAPIGateway.Utilities.InvokeOnGameThread(() =>
                                                          { AddMinedPosition(target); });
                return(false);
            }

            if (target.Amount == 0f)
            {
                Logging.Instance.WriteLine("[Mining] Amount is 0", 2);
                MyAPIGateway.Utilities.InvokeOnGameThread(() =>
                                                          { AddMinedPosition(target); });
                return(false);
            }

            return(true);
        }
Пример #6
0
        public void ReadRange(MyStorageData target, MyStorageDataTypeFlags dataToRead, int lodIndex, ref Vector3I lodVoxelRangeMin, ref Vector3I lodVoxelRangeMax, ref MyVoxelRequestFlags requestFlags)
        {
            ProfilerShort.Begin(GetType().Name + ".ReadRange");

            if ((dataToRead & MyStorageDataTypeFlags.Content) != 0)
            {
                target.ClearContent(0);
            }

            if (requestFlags.HasFlags(MyVoxelRequestFlags.AdviseCache) && lodIndex == 0 && CachedWrites)
            {
                ReadRangeAdviseCache(target, dataToRead, ref lodVoxelRangeMin, ref lodVoxelRangeMax);
                ProfilerShort.End();
                return;
            }

            if (CachedWrites && lodIndex <= VoxelChunk.SizeBits && m_cachedChunks.Count > 0)
            {
                // read occlusion separate
                if (dataToRead.Requests(MyStorageDataTypeEnum.Occlusion))
                {
                    using (m_storageLock.AcquireSharedUsing())
                        ReadRangeInternal(target, ref Vector3I.Zero, MyStorageDataTypeFlags.Occlusion, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags);

                    dataToRead ^= MyStorageDataTypeFlags.Occlusion;
                }

                if (m_tmpChunks == null)
                {
                    m_tmpChunks = new List <VoxelChunk>();
                }

                var lodDiff = VoxelChunk.SizeBits - lodIndex;

                // We fetch which chunks overlap our current range from the chunk tree, then we read all data from storage and apply those changes
                var querybb = new BoundingBox(lodVoxelRangeMin << lodIndex, lodVoxelRangeMax << lodIndex);

                using (m_cacheLock.AcquireSharedUsing())
                    m_cacheMap.OverlapAllBoundingBox(ref querybb, m_tmpChunks, 0, false);

                if (m_tmpChunks.Count > 0)
                {
                    var chunkMin = lodVoxelRangeMin >> lodDiff;
                    var chunkMax = lodVoxelRangeMax >> lodDiff;

                    bool readFromStorage = false;

                    if ((chunkMax - chunkMin + 1).Size > m_tmpChunks.Count)
                    {
                        using (m_storageLock.AcquireSharedUsing())
                            ReadRangeInternal(target, ref Vector3I.Zero, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags);
                        readFromStorage = true;
                    }

                    for (int i = 0; i < m_tmpChunks.Count; ++i)
                    {
                        var chunk = m_tmpChunks[i];
                        var pos   = chunk.Coords;

                        var celPos = pos << lodDiff;

                        var lodCkStart = pos << lodDiff;
                        lodCkStart = Vector3I.Max(lodCkStart, lodVoxelRangeMin);

                        var targetOffset = lodCkStart - lodVoxelRangeMin;

                        var lodCkEnd = ((pos + 1) << lodDiff) - 1;
                        lodCkEnd = Vector3I.Min(lodCkEnd, lodVoxelRangeMax);

                        lodCkStart -= celPos;
                        lodCkEnd   -= celPos;

                        if ((chunk.Cached & dataToRead) != dataToRead && !readFromStorage)
                        {
                            using (m_storageLock.AcquireSharedUsing())
                                if ((chunk.Cached & dataToRead) != dataToRead)
                                {
                                    ReadDatForChunk(chunk, dataToRead);
                                }
                        }

                        using (chunk.Lock.AcquireSharedUsing())
                            chunk.ReadLod(target, !readFromStorage ? dataToRead : dataToRead & chunk.Cached, ref targetOffset, lodIndex, ref lodCkStart, ref lodCkEnd);
                    }

                    m_tmpChunks.Clear();
                    ProfilerShort.End();
                    return;
                }
            }

            // all else
            using (m_storageLock.AcquireSharedUsing())
                ReadRangeInternal(target, ref Vector3I.Zero, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags);

            ProfilerShort.End();
        }
Пример #7
0
        public static void RemoveVoxelContent(long voxelId, Vector3D position, out byte materialRemoved, out float amountOfMaterial)
        {
            materialRemoved  = 0;
            amountOfMaterial = 0f;

            IMyEntity entity;

            if (!MyAPIGateway.Entities.TryGetEntityById(voxelId, out entity))
            {
                return;
            }

            var      voxel = entity as IMyVoxelBase;
            var      targetMin = position;
            var      targetMax = position;
            Vector3I minVoxel, maxVoxel;

            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref targetMin, out minVoxel);
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref targetMax, out maxVoxel);

            MyVoxelBase voxelBase = voxel as MyVoxelBase;

            minVoxel += voxelBase.StorageMin;
            maxVoxel += voxelBase.StorageMin + 1;

            voxel.Storage.ClampVoxel(ref minVoxel);
            voxel.Storage.ClampVoxel(ref maxVoxel);

            MyStorageData cache = new MyStorageData();

            cache.Resize(minVoxel, maxVoxel);
            var flag = MyVoxelRequestFlags.AdviseCache;

            cache.ClearContent(0);
            cache.ClearMaterials(0);

            byte original = 0;
            byte material = 0;

            // I don't really think pinning is necessary since I'm in the main thread, but this hasn't been working for awhile, so I'll keep it here.
            voxel.Storage.PinAndExecute(() =>
            {
                voxel.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, minVoxel, maxVoxel, ref flag);

                // Grab content and material
                original = cache.Content(0);
                material = cache.Material(0);

                if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY)
                {
                    //Logging.Instance.WriteLine(string.Format("Content is empty"));
                    return;
                }

                // Remove Content
                Logging.Instance.WriteLine($"Material: SizeLinear: {cache.SizeLinear}, Size3D: {cache.Size3D}, AboveISO: {cache.ContainsVoxelsAboveIsoLevel()}");
                cache.Content(0, 0);
                voxel.Storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, minVoxel, maxVoxel);
            });

            // Calculate Material Mined
            var voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(material);

            materialRemoved  = material;
            amountOfMaterial = CalculateAmount(voxelMat, original * 3.9f);

            // This will sync the clients.  Apparently voxel writes do not sync, lovely.
            if (Sync.IsServer)
            {
                VoxelRemovalData data = new VoxelRemovalData();
                data.VoxelID  = voxelId;
                data.Position = position;
                MyAPIGateway.Multiplayer.SendMessageToOthers(8969, ASCIIEncoding.ASCII.GetBytes(MyAPIGateway.Utilities.SerializeToXML(data)));
            }
        }
Пример #8
0
        private void ReadVoxel(IMyVoxelBase voxel, Vector3D position, Dictionary <Vector3D, NaniteMiningItem> targets, HashSet <string> allowedOreList = null)
        {
            var m_cache = new MyStorageData();
            NaniteShapeSphere shapeSphere = new NaniteShapeSphere();

            shapeSphere.Center = position;
            shapeSphere.Radius = NaniteConstructionManager.Settings.MiningRadius / 2;

            //NaniteShapeCapsule shapeCapsule = new NaniteShapeCapsule();
            //shapeCapsule.A = positionA;
            //shapeCapsule.B = positionB;
            //shapeCapsule.Radius = NaniteConstructionManager.Settings.MiningRadius;

            Vector3I minCorner, maxCorner, numCells;

            GetVoxelShapeDimensions(voxel, shapeSphere, out minCorner, out maxCorner, out numCells);

            var cacheMin = minCorner - 1;
            var cacheMax = maxCorner + 1;

            //bool bRareOnly = true;
            //if (allowedOreList != null && allowedOreList.Contains("Stone"))
            //    bRareOnly = false;

            m_cache.Resize(cacheMin, cacheMax);
            m_cache.ClearContent(0);
            m_cache.ClearMaterials(0);
            var flags = MyVoxelRequestFlags.AdviseCache;

            voxel.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, cacheMin, cacheMax, ref flags);

            //voxel.Storage.PinAndExecute(() =>
            {
                Vector3I pos;
                for (pos.X = minCorner.X; pos.X <= maxCorner.X; ++pos.X)
                {
                    for (pos.Y = minCorner.Y; pos.Y <= maxCorner.Y; ++pos.Y)
                    {
                        for (pos.Z = minCorner.Z; pos.Z <= maxCorner.Z; ++pos.Z)
                        {
                            // get original amount
                            var relPos = pos - cacheMin;
                            var lin    = m_cache.ComputeLinear(ref relPos);

                            //var relPos = pos - cacheMin; // Position of voxel in local space
                            var original = m_cache.Content(lin); // Content at this position

                            if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY)
                            {
                                continue;
                            }

                            var      material = m_cache.Material(lin); // Material at this position
                            Vector3D vpos;
                            MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxel.PositionLeftBottomCorner, ref pos, out vpos);
                            if (targets.ContainsKey(vpos))
                            {
                                continue;
                            }

                            /*
                             * var volume = shapeSphere.GetVolume(ref vpos);
                             * if (volume == 0f) // Shape and voxel do not intersect at this position, so continue
                             *  continue;
                             */

                            // Pull information about voxel required for later processing
                            var voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(material);
                            //if ((bRareOnly && voxelMat.IsRare) || !bRareOnly)
                            //if(voxelMat.IsRare)
                            if (allowedOreList != null)// || (allowedOreList == null && bRareOnly && voxelMat.IsRare))
                            {
                                if (allowedOreList != null && !allowedOreList.Contains(voxelMat.MinedOre))
                                {
                                    continue;
                                }


                                NaniteMiningItem miningItem = new NaniteMiningItem();
                                miningItem.Position      = vpos;
                                miningItem.VoxelMaterial = material;
                                miningItem.VoxelId       = voxel.EntityId;
                                miningItem.Amount        = original; // * 3.9f;
                                miningItem.MiningHammer  = this;
                                targets.Add(vpos, miningItem);
                                //count++;
                            }

                            //m_cache.Content(lin, 0);
                            //m_cache.Material(lin, 0);
                        }
                    }
                }


                //voxel.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, cacheMin, cacheMax);
            };

            /*
             * int count = 0;
             * for (var itCells = new Vector3I_RangeIterator(ref Vector3I.Zero, ref numCells); itCells.IsValid(); itCells.MoveNext())
             * {
             *  Vector3I cellMinCorner, cellMaxCorner;
             *  GetCellCorners(ref minCorner, ref maxCorner, ref itCells, out cellMinCorner, out cellMaxCorner);
             *
             *  var cacheMin = cellMinCorner - 1;
             *  var cacheMax = cellMaxCorner + 1;
             *  voxel.Storage.ClampVoxel(ref cacheMin);
             *  voxel.Storage.ClampVoxel(ref cacheMax);
             *
             *  m_cache.Resize(cacheMin, cacheMax);
             *  voxel.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, cacheMin, cacheMax);
             *
             *  for (var it = new Vector3I_RangeIterator(ref cellMinCorner, ref cellMaxCorner); it.IsValid(); it.MoveNext())
             *  {
             *      var relPos = it.Current - cacheMin; // Position of voxel in local space
             *      var original = m_cache.Content(ref relPos); // Content at this position
             *      var material = m_cache.Material(ref relPos); // Material at this position
             *
             *      if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY)
             *          continue;
             *
             *      Vector3D vpos;
             *      MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxel.PositionLeftBottomCorner, ref it.Current, out vpos);
             *      if (targets.ContainsKey(vpos))
             *          continue;
             *
             *      var volume = shapeSphere.GetVolume(ref vpos);
             *      if (volume == 0f) // Shape and voxel do not intersect at this position, so continue
             *          continue;
             *
             *      // Pull information about voxel required for later processing
             *      var voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref relPos));
             *      //if ((bRareOnly && voxelMat.IsRare) || !bRareOnly)
             *      //if(voxelMat.IsRare)
             *      if (allowedOreList != null)// || (allowedOreList == null && bRareOnly && voxelMat.IsRare))
             *      {
             *          if (allowedOreList != null && !allowedOreList.Contains(voxelMat.MinedOre))
             *              continue;
             *
             *          NaniteMiningItem miningItem = new NaniteMiningItem();
             *          miningItem.Position = vpos;
             *          miningItem.VoxelMaterial = material;
             *          miningItem.VoxelId = voxel.EntityId;
             *          miningItem.Amount = original; // * 3.9f;
             *          miningItem.MiningHammer = this;
             *          targets.Add(vpos, miningItem);
             *          count++;
             *      }
             *  }
             * }
             */

            //Logging.Instance.WriteLine(string.Format("Voxels Read: {0} - {1}", voxel.GetType().Name, count));
        }
Пример #9
0
        public unsafe MyStorageBase Compatibility_LoadCellStorage(int fileVersion, Stream stream)
        {
            Vector3I vectori;
            Vector3I vectori2;
            Vector3I vectori6;

            vectori.X = stream.ReadInt32();
            vectori.Y = stream.ReadInt32();
            vectori.Z = stream.ReadInt32();
            MyOctreeStorage storage = new MyOctreeStorage(null, vectori);

            vectori2.X = stream.ReadInt32();
            vectori2.Y = stream.ReadInt32();
            vectori2.Z = stream.ReadInt32();
            Vector3I vectori3 = (Vector3I)(vectori / vectori2);
            Dictionary <byte, MyVoxelMaterialDefinition> mapping = null;

            if (fileVersion == 2)
            {
                mapping = this.Compatibility_LoadMaterialIndexMapping(stream);
            }
            else
            {
                int num2 = fileVersion;
            }
            Vector3I      zero   = Vector3I.Zero;
            Vector3I      end    = new Vector3I(7);
            MyStorageData source = new MyStorageData(MyStorageDataTypeFlags.All);

            source.Resize(Vector3I.Zero, end);
            vectori6.X = 0;
            while (vectori6.X < vectori3.X)
            {
                vectori6.Y = 0;
                while (true)
                {
                    if (vectori6.Y >= vectori3.Y)
                    {
                        int *numPtr6 = (int *)ref vectori6.X;
                        numPtr6[0]++;
                        break;
                    }
                    vectori6.Z = 0;
                    while (true)
                    {
                        if (vectori6.Z >= vectori3.Z)
                        {
                            int *numPtr5 = (int *)ref vectori6.Y;
                            numPtr5[0]++;
                            break;
                        }
                        MyVoxelContentConstitution constitution = (MyVoxelContentConstitution)stream.ReadByteNoAlloc();
                        switch (constitution)
                        {
                        case MyVoxelContentConstitution.Empty:
                            source.ClearContent(0);
                            break;

                        case MyVoxelContentConstitution.Full:
                            source.ClearContent(0xff);
                            break;

                        case MyVoxelContentConstitution.Mixed:
                            Vector3I vectori7;
                            vectori7.X = 0;
                            while (vectori7.X < 8)
                            {
                                vectori7.Y = 0;
                                while (true)
                                {
                                    if (vectori7.Y >= 8)
                                    {
                                        int *numPtr3 = (int *)ref vectori7.X;
                                        numPtr3[0]++;
                                        break;
                                    }
                                    vectori7.Z = 0;
                                    while (true)
                                    {
                                        if (vectori7.Z >= 8)
                                        {
                                            int *numPtr2 = (int *)ref vectori7.Y;
                                            numPtr2[0]++;
                                            break;
                                        }
                                        source.Content(ref vectori7, stream.ReadByteNoAlloc());
                                        int *numPtr1 = (int *)ref vectori7.Z;
                                        numPtr1[0]++;
                                    }
                                }
                            }
                            break;

                        default:
                            break;
                        }
                        zero = vectori6 * 8;
                        storage.WriteRange(source, MyStorageDataTypeFlags.Content, zero, (Vector3I)(zero + 7), true, false);
                        int *numPtr4 = (int *)ref vectori6.Z;
                        numPtr4[0]++;
                    }
                }
            }
            try
            {
                vectori6.X = 0;
                while (vectori6.X < vectori3.X)
                {
                    vectori6.Y = 0;
                    while (true)
                    {
                        if (vectori6.Y >= vectori3.Y)
                        {
                            int *numPtr12 = (int *)ref vectori6.X;
                            numPtr12[0]++;
                            break;
                        }
                        vectori6.Z = 0;
                        while (true)
                        {
                            if (vectori6.Z >= vectori3.Z)
                            {
                                int *numPtr11 = (int *)ref vectori6.Y;
                                numPtr11[0]++;
                                break;
                            }
                            MyVoxelMaterialDefinition definition = null;
                            if (stream.ReadByteNoAlloc() == 1)
                            {
                                source.ClearMaterials(this.Compatibility_LoadCellVoxelMaterial(stream, mapping).Index);
                            }
                            else
                            {
                                Vector3I vectori8;
                                vectori8.X = 0;
                                while (vectori8.X < 8)
                                {
                                    vectori8.Y = 0;
                                    while (true)
                                    {
                                        if (vectori8.Y >= 8)
                                        {
                                            int *numPtr9 = (int *)ref vectori8.X;
                                            numPtr9[0]++;
                                            break;
                                        }
                                        vectori8.Z = 0;
                                        while (true)
                                        {
                                            if (vectori8.Z >= 8)
                                            {
                                                int *numPtr8 = (int *)ref vectori8.Y;
                                                numPtr8[0]++;
                                                break;
                                            }
                                            definition = this.Compatibility_LoadCellVoxelMaterial(stream, mapping);
                                            stream.ReadByteNoAlloc();
                                            source.Material(ref vectori8, definition.Index);
                                            int *numPtr7 = (int *)ref vectori8.Z;
                                            numPtr7[0]++;
                                        }
                                    }
                                }
                            }
                            zero = vectori6 * 8;
                            storage.WriteRange(source, MyStorageDataTypeFlags.Material, zero, (Vector3I)(zero + 7), true, false);
                            int *numPtr10 = (int *)ref vectori6.Z;
                            numPtr10[0]++;
                        }
                    }
                }
            }
            catch (EndOfStreamException exception)
            {
                MySandboxGame.Log.WriteLine(exception);
            }
            return(storage);
        }
Пример #10
0
        public void ReadRange(MyStorageData target, MyStorageDataTypeFlags dataToRead, int lodIndex, ref Vector3I lodVoxelRangeMin, ref Vector3I lodVoxelRangeMax, ref MyVoxelRequestFlags requestFlags)
        {
            ProfilerShort.Begin(GetType().Name + ".ReadRange");
            try
            {
                const int SUBRANGE_SIZE_SHIFT = 3;
                const int SUBRANGE_SIZE = 1 << SUBRANGE_SIZE_SHIFT;
                var threshold = new Vector3I(SUBRANGE_SIZE);
                var rangeSize = lodVoxelRangeMax - lodVoxelRangeMin + 1;
                if ((dataToRead & MyStorageDataTypeFlags.Content) != 0)
                {
                    target.ClearContent(0);
                }

                if ((rangeSize.X <= threshold.X &&
                    rangeSize.Y <= threshold.Y &&
                    rangeSize.Z <= threshold.Z) || !MyFakes.ENABLE_SPLIT_VOXEL_READ_QUERIES)
                {
                    using (m_lock.AcquireSharedUsing())
                    {
                        ReadRangeInternal(target, ref Vector3I.Zero, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags);
                    }
                }
                else
                {
                    // These optimizations don't work when splitting the range.
                    requestFlags &= ~(MyVoxelRequestFlags.OneMaterial | MyVoxelRequestFlags.ContentChecked);
                    MyVoxelRequestFlags flags = requestFlags;

                    // splitting to smaller ranges to make sure the lock is not held for too long, preventing write on update thread
                    // subranges could be aligned to multiple of their size for possibly better performance
                    var steps = (rangeSize - 1) >> SUBRANGE_SIZE_SHIFT;
                    for (var it = new Vector3I.RangeIterator(ref Vector3I.Zero, ref steps); it.IsValid(); it.MoveNext())
                    {
                        flags = requestFlags;
                        var offset = it.Current << SUBRANGE_SIZE_SHIFT;
                        var min = lodVoxelRangeMin + offset;
                        var max = min + SUBRANGE_SIZE - 1;
                        Vector3I.Min(ref max, ref lodVoxelRangeMax, out max);
                        Debug.Assert(min.IsInsideInclusive(ref lodVoxelRangeMin, ref lodVoxelRangeMax));
                        Debug.Assert(max.IsInsideInclusive(ref lodVoxelRangeMin, ref lodVoxelRangeMax));
                        using (m_lock.AcquireSharedUsing())
                        {
                            ReadRangeInternal(target, ref offset, dataToRead, lodIndex, ref min, ref max, ref flags);
                        }
                    }

                    // If the storage is consistent this should be fine.
                    requestFlags = flags;
                }
            }
            finally
            {
                ProfilerShort.End();
            }
        }