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; }
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); }
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); }
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(); }
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))); } }
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)); }
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); }