private HashSet <Block> GetBlocks(RawSchematic rawSchematic) { if (rawSchematic.Heigth > 2016 || rawSchematic.Length > 2016 || rawSchematic.Width > 2016) { throw new Exception("Schematic is too big"); } Console.WriteLine($"[LOG] Started to read all blocks of the schematic..."); Console.WriteLine($"[INFO] Raw schematic Width: {rawSchematic.Width}"); Console.WriteLine($"[INFO] Raw schematic Length: {rawSchematic.Length}"); Console.WriteLine($"[INFO] Raw schematic Height: {rawSchematic.Heigth}"); Console.WriteLine($"[INFO] Raw schematic total blocks: {rawSchematic.Data.Length}"); LoadedSchematic.WidthSchematic = (short)(rawSchematic.Width * _scale); LoadedSchematic.LengthSchematic = (short)(rawSchematic.Length * _scale); LoadedSchematic.HeightSchematic = (short)(rawSchematic.Heigth * _scale); //Sorted by height (bottom to top) then length then width -- the index of the block at X,Y,Z is (Y×length + Z)×width + X. ConcurrentBag <Block> blocks = new ConcurrentBag <Block>(); int minY = Math.Max(_ignoreMinY, 0); int maxY = 0; if (rawSchematic.Heigth <= _ignoreMaxY) { maxY = Math.Min(_ignoreMaxY, rawSchematic.Heigth); } else { maxY = rawSchematic.Heigth; } Parallel.For(minY, (maxY * _scale), y => { for (int z = 0; z < (rawSchematic.Length * _scale); z++) { for (int x = 0; x < (rawSchematic.Width * _scale); x++) { int yProgress = (y / _scale); int zProgress = (z / _scale); int xProgress = (x / _scale); int index = (yProgress * rawSchematic.Length + zProgress) * rawSchematic.Width + xProgress; int blockId = rawSchematic.Blocks[index]; if (blockId != 0) { Block block = new Block((short)x, (short)y, (short)z, GetBlockColor(rawSchematic.Blocks[index], rawSchematic.Data[index]).ColorToUInt()); if ((_excavate && IsBlockConnectedToAir(rawSchematic, block, minY, maxY) || !_excavate)) { blocks.Add(block); } } } } }); Console.WriteLine($"[LOG] Done."); return(blocks.ToHashSet()); }
private Schematic LoadSchematic(NbtFile nbtFile) { RawSchematic raw = LoadRaw(nbtFile); HashSet <Voxel> blocks = GetBlocks(raw); Schematic schematic = new Schematic(blocks); return(schematic); }
private Schematic LoadSchematic(NbtFile nbtFile) { RawSchematic raw = LoadRaw(nbtFile); HashSet <Block> blocks = GetBlocks(raw); string name = Path.GetFileNameWithoutExtension(nbtFile.FileName); Schematic schematic = new Schematic((ushort)raw.Width, (ushort)raw.Heigth, (ushort)raw.Length, blocks); schematic.Width *= (ushort)_scale; schematic.Height *= (ushort)_scale; schematic.Length *= (ushort)_scale; return(schematic); }
private HashSet <Voxel> GetBlocks(RawSchematic rawSchematic) { if (rawSchematic.Heigth > Schematic.MAX_WORLD_HEIGHT || rawSchematic.Length > Schematic.MAX_WORLD_LENGTH || rawSchematic.Width > Schematic.MAX_WORLD_WIDTH) { throw new Exception("Schematic is too big"); } Console.WriteLine($"[LOG] Started to read all blocks of the schematic..."); //Sorted by height (bottom to top) then length then width -- the index of the block at X,Y,Z is (Y×length + Z)×width + X. HashSet <Voxel> blocks = new HashSet <Voxel>(); int minY = Math.Max(mIgnoreMinY, 0); int maxY = rawSchematic.Heigth <= mIgnoreMaxY?Math.Min(mIgnoreMaxY, rawSchematic.Heigth) : rawSchematic.Heigth; int total = (maxY * mScale) * (rawSchematic.Length * mScale) * (rawSchematic.Width * mScale); int indexProgress = 0; using (ProgressBar progressbar = new ProgressBar()) { for (int y = minY; y < (maxY * mScale); y++) { for (int z = 0; z < (rawSchematic.Length * mScale); z++) { for (int x = 0; x < (rawSchematic.Width * mScale); x++) { int yProgress = (y / mScale); int zProgress = (z / mScale); int xProgress = (x / mScale); int index = (yProgress * rawSchematic.Length + zProgress) * rawSchematic.Width + xProgress; int blockId = rawSchematic.Blocks[index]; if (blockId != 0) { Voxel voxel = new Voxel((ushort)x, (ushort)y, (ushort)z, GetBlockColor(rawSchematic.Blocks[index], rawSchematic.Data[index]).ColorToUInt()); if ((mExcavate && IsBlockConnectedToAir(rawSchematic, voxel, minY, maxY) || !mExcavate)) { if (!blocks.Contains(voxel)) { blocks.Add(voxel); } } } progressbar.Report(indexProgress++ / (float)total); } } } } Console.WriteLine($"[LOG] Done."); return(blocks); }
private RawSchematic LoadRaw(NbtFile nbtFile) { RawSchematic raw = new RawSchematic(); var rootTag = nbtFile.RootTag; foreach (NbtTag tag in rootTag.Tags) { switch (tag.Name) { case "Width": //Short raw.Width = tag.ShortValue; LoadedSchematic.WidthSchematic = (ushort)raw.Width; break; case "Height": //Short raw.Heigth = tag.ShortValue; LoadedSchematic.HeightSchematic = (ushort)raw.Heigth; break; case "Length": //Short raw.Length = tag.ShortValue; break; case "Blocks": //ByteArray raw.Blocks = tag.ByteArrayValue; break; case "Data": //ByteArray raw.Data = tag.ByteArrayValue; break; case "Entities": //List break; //Ignore case "TileEntities": //List break; case "Icon": //Compound break; //Ignore case "SchematicaMapping": //Compound tag.ToString(); break; //Ignore default: break; } } return(raw); }
private Schematic CreateSchematic(RawSchematic rawSchematic) { if (rawSchematic.Heigth > Schematic.MAX_WORLD_HEIGHT || rawSchematic.Length > Schematic.MAX_WORLD_LENGTH || rawSchematic.Width > Schematic.MAX_WORLD_WIDTH) { throw new Exception("Schematic is too big"); } Console.WriteLine($"[INFO] Started to read all blocks of the schematic..."); //Sorted by height (bottom to top) then length then width -- the index of the block at X,Y,Z is (Y×length + Z)×width + X. Schematic schematic = new Schematic(); int total = (rawSchematic.Heigth) * (rawSchematic.Length) * (rawSchematic.Width); int indexProgress = 0; using (ProgressBar progressbar = new ProgressBar()) { for (int y = 0; y < (rawSchematic.Heigth); y++) { for (int z = 0; z < (rawSchematic.Length); z++) { for (int x = 0; x < (rawSchematic.Width); x++) { int index = (y * rawSchematic.Length + z) * rawSchematic.Width + x; int blockId = rawSchematic.Blocks[index]; if (blockId != 0) { Voxel voxel = new Voxel((ushort)x, (ushort)y, (ushort)z, GetBlockColor(rawSchematic.Blocks[index], rawSchematic.Data[index]).ColorToUInt()); if ((mExcavate && IsBlockConnectedToAir(rawSchematic, voxel, 0, rawSchematic.Heigth) || !mExcavate)) { if (!schematic.ContainsVoxel(x, y, z)) { schematic.AddVoxel(x, y, z, voxel.Color); } } } progressbar.Report(indexProgress++ / (float)total); } } } } Console.WriteLine($"[INFO] Done."); return(schematic); }
private bool IsBlockConnectedToAir(RawSchematic rawSchematic, Block block, int minY, int maxY) { if (block.X - 1 >= 0 && block.X + 1 < rawSchematic.Width && block.Y - 1 >= minY && block.Y + 1 < maxY && block.Z - 1 >= 0 && block.Z < rawSchematic.Length) { int indexLeftX = (block.Y * rawSchematic.Length + block.Z) * rawSchematic.Width + (block.X - 1); int indexRightX = (block.Y * rawSchematic.Length + block.Z) * rawSchematic.Width + (block.X + 1); int indexTop = ((block.Y + 1) * rawSchematic.Length + block.Z) * rawSchematic.Width + block.X; int indexBottom = ((block.Y - 1) * rawSchematic.Length + block.Z) * rawSchematic.Width + block.X; int indexAhead = (block.Y * rawSchematic.Length + block.Z + 1) * rawSchematic.Width + block.X; int indexBehind = (block.Y * rawSchematic.Length + block.Z - 1) * rawSchematic.Width + block.X; return(rawSchematic.Blocks[indexLeftX] == 0 || rawSchematic.Blocks[indexRightX] == 0 || rawSchematic.Blocks[indexTop] == 0 || rawSchematic.Blocks[indexBottom] == 0 || rawSchematic.Blocks[indexAhead] == 0 || rawSchematic.Blocks[indexBehind] == 0); } return(false); }
private Schematic LoadSchematic(NbtFile nbtFile) { RawSchematic raw = LoadRaw(nbtFile); return(CreateSchematic(raw)); }