/// <summary> /// Tries loading the chunk at the specified position. This is done automatically /// when an area is requested. /// </summary> public Chunk?LoadChunk(Point <int> Pos) { Chunk?chunk; if (SMPInterface.IsSMP) { chunk = SMPInterface.GetChunk(Pos, this._Trans); } else if (!this._Chunks.TryGetValue(Pos, out chunk)) { long regionX = (long)Math.Floor((decimal)Pos.X / 32); long regionZ = (long)Math.Floor((decimal)Pos.Y / 32); string file = this._Source + Path.DirectorySeparatorChar + "region" + Path.DirectorySeparatorChar + "r." + Convert.ToString(regionX) + "." + Convert.ToString(regionZ) + ".mca"; if (File.Exists(file)) { try { using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) //File.OpenRead(file)) { NBTNamedTag <INBTData> dat = NBT.ReadChunk(fs, Pos); NBTCompound level = (NBTCompound)(((NBTCompound)dat.Data).Data["Level"]).Data; this._Chunks.Add(Pos, chunk = ParseChunkFromNBT(level) ); } } catch { this._Chunks.Add(Pos, null); } } else { this._Chunks.Add(Pos, null); } } return(chunk); }
/// <summary> /// Parses the NBT compound "level" tag into a chunk /// </summary> Chunk?ParseChunkFromNBT(NBTCompound level) { byte[] Blocks = new byte[16 * 1256 * 16]; byte[] BlockLight = new byte[16 * 256 * 16 / 2]; byte[] SkyLight = new byte[16 * 256 * 16 / 2]; const int BLOCKS_PER_SECTION = 16 * 16 * 16; const int NIBBLES_PER_SECTION = 16 * 16 * 16 / 2; // Parse each section: NBTList Sections = (NBTList)(level.Data["Sections"].Data); foreach (INBTData Section in Sections.Data) { NBTCompound CompS = (NBTCompound)Section; int y = ((NBTByte)(CompS.Data["Y"].Data)).Data; byte[] SectionBlocks = ((NBTByteArray)(CompS.Data["Blocks"].Data)).Data; Buffer.BlockCopy(SectionBlocks, 0, Blocks, y * BLOCKS_PER_SECTION, BLOCKS_PER_SECTION); byte[] SectionBlockLight = ((NBTByteArray)(CompS.Data["BlockLight"].Data)).Data; Buffer.BlockCopy(SectionBlockLight, 0, BlockLight, y * NIBBLES_PER_SECTION, NIBBLES_PER_SECTION); byte[] SectionSkyLight = ((NBTByteArray)(CompS.Data["BlockLight"].Data)).Data; Buffer.BlockCopy(SectionSkyLight, 0, SkyLight, y * NIBBLES_PER_SECTION, NIBBLES_PER_SECTION); } // foreach Section return(new Chunk(Blocks, BlockLight, SkyLight, this._Trans)); }
public Window(string World, bool Nether, Dictionary <string, Scheme> Schemes) : base(640, 480, GraphicsMode.Default, DefaultTitle) { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmHelp)); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); GL.Enable(EnableCap.Lighting); GL.Enable(EnableCap.CullFace); GL.Enable(EnableCap.ColorMaterial); GL.Enable(EnableCap.DepthTest); GL.Enable(EnableCap.Blend); // support transparencey GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); //GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); MinecraftLevel mcl; MinecraftLevel mclt; if (Nether) { mcl = new MinecraftLevel(World + Path.DirectorySeparatorChar + "DIM-1", false); mclt = new MinecraftLevel(World + Path.DirectorySeparatorChar + "DIM-1", true); } else { mcl = new MinecraftLevel(World, false); mclt = new MinecraftLevel(World, true); } int s = 128; DateTime starttime = DateTime.Now; string leveldat = World + Path.DirectorySeparatorChar + "level.dat"; // we still dont change this, level.dat is still used this._Renderer = new MinecraftRenderer(mcl); this._RendererTrans = new MinecraftRenderer(mclt); Scheme schm; Schemes.TryGetValue("Default", out schm); this._Renderer.CurrentScheme = schm; this._RendererTrans.CurrentScheme = schm; Vector <double> acpos = new Vector <double>(); if (File.Exists(leveldat) && !SMPInterface.IsSMP) { try { NBTCompound data = ((NBT.Read(File.OpenRead(leveldat)).Data as NBTCompound?).Value.Data["Data"].Data as NBTCompound?).Value; NBTNamedTag <INBTData> player = null; double hellscale = 8.0; bool tryget = data.Data.TryGetValue("Player", out player); bool nether = !(((player.Data as NBTCompound?).Value.Data["Dimension"].Data as NBTInt?).Value.Data == 0); if (tryget & Nether == nether) { NBTList pos = (((player.Data as NBTCompound?).Value.Data["Pos"]).Data as NBTList?).Value; acpos = new Vector <double>( (pos.Data[0] as NBTDouble?).Value.Data, (pos.Data[1] as NBTDouble?).Value.Data, (pos.Data[2] as NBTDouble?).Value.Data); } else if (tryget && !Nether) // the correct positions are not in the correct places { // Not the nether, but player location is in the nether // Lets make the view 16 times further away, this is the chunk they will come up on. NBTList pos = (((player.Data as NBTCompound?).Value.Data["Pos"]).Data as NBTList?).Value; acpos = new Vector <double>( (pos.Data[0] as NBTDouble?).Value.Data * hellscale, (pos.Data[1] as NBTDouble?).Value.Data, (pos.Data[2] as NBTDouble?).Value.Data * hellscale); } else if (tryget && Nether) // Lets see where we will end up on the nether from up top { NBTList pos = (((player.Data as NBTCompound?).Value.Data["Pos"]).Data as NBTList?).Value; acpos = new Vector <double>( (pos.Data[0] as NBTDouble?).Value.Data / hellscale, (pos.Data[1] as NBTDouble?).Value.Data, (pos.Data[2] as NBTDouble?).Value.Data / hellscale); } else { acpos = new Vector <double>( ((data.Data["SpawnX"]).Data as NBTInt?).Value.Data, ((data.Data["SpawnY"]).Data as NBTInt?).Value.Data, ((data.Data["SpawnZ"]).Data as NBTInt?).Value.Data); } } catch { } } else if (SMPInterface.IsSMP) { MineViewer.SMPPackets.PlayerSpawnPos.UpdateSpawnPos = new Action <Vector <int> >(delegate(Vector <int> pos) { Point <int> c; Point <int> o; MinecraftRenderer.ChunkOffset(new Point <int>((int)pos.Z, (int)pos.X), out c, out o); this._Renderer.GetChunk(c); this._RendererTrans.GetChunk(c); this._CamPos = new Vector <double>(s + 10.1 + c.X * MinecraftRenderer.ChunkSize, s + 10.1 + c.Y * MinecraftRenderer.ChunkSize, s + 10.1); }); } Point <int> chunk; Point <int> offset; MinecraftRenderer.ChunkOffset(new Point <int>((int)acpos.Z, (int)acpos.X), out chunk, out offset); if (!SMPInterface.IsSMP) { this._Renderer.GetChunk(chunk); this._RendererTrans.GetChunk(chunk); } this._CamPos = new Vector <double>(s + 10.1 + chunk.X * MinecraftRenderer.ChunkSize, s + 10.1 + chunk.Y * MinecraftRenderer.ChunkSize, s + 10.1); this._LookZAngle = 4.0; this._LookXAngle = -0.6; DateTime endtime = DateTime.Now; TimeSpan loadtime = endtime - starttime; this._LastHit = null; _Bookmarks = new Bookmarks(World + Path.DirectorySeparatorChar, delegate(Vector <double> vec, Vector <double> ang) { this._CamPos = vec; //this._LookXAngle = ang.X; //this._LookZAngle = ang.Z; Point <int> dchunk; Point <int> doffset; MinecraftRenderer.ChunkOffset(new Point <int>((int)vec.X, (int)vec.Y), out dchunk, out doffset); this._Renderer.GetChunk(dchunk); this._RendererTrans.GetChunk(dchunk); }); this.KeyPress += delegate(object sender, OpenTK.KeyPressEventArgs e) { char key = e.KeyChar.ToString().ToLower()[0]; if (key == 'b') { this._Bookmarks.ShowForm(this._CamPos, new Vector <double>(this._LookXAngle, 0.0, this._LookZAngle)); } if (key == ',') { this._SliceLevel = this._SlicePolarity == Polarity.Negative ? this._SliceLevel - 1 : this._SliceLevel + 1; } if (key == '.') { this._SliceLevel = this._SlicePolarity == Polarity.Negative ? this._SliceLevel + 1 : this._SliceLevel - 1; } if (key == 'h') { frmHelp frm = new frmHelp(); frm.Show(); } if (key == 'k') { frmKey k = new frmKey(this._Renderer.CurrentScheme); k.Show(); } if (key == 't') { frmSchemes schemeform = new frmSchemes(delegate(string item) { if (item.Length < 1) { return; } this._Renderer.CurrentScheme = this._Schemes[item]; this._RendererTrans.CurrentScheme = this._Schemes[item]; }); int index = 0; foreach (string k in this._Schemes.Keys) { ListViewItem item = new ListViewItem(k); schemeform.Schemes.Items.Add(item); Scheme o; this._Schemes.TryGetValue(k, out o); if (this._Renderer.CurrentScheme == o) { schemeform.Schemes.Items[index].Selected = true; } index++; } schemeform.Show(); } }; this.Keyboard.KeyDown += delegate(object sender, KeyboardKeyEventArgs e) { if (e.Key == Key.Escape) { this.Close(); } if (e.Key == Key.R) { this._SliceAxis = null; } }; this.Mouse.ButtonDown += delegate(object sender, MouseButtonEventArgs bea) { if (bea.Button == MouseButton.Left) { if (this._LastHit != null) { Border <MinecraftRenderer.HitBorder> hit = this._LastHit.Value; MinecraftRenderer.Chunk c; bool loaded = this._Renderer.Chunks.TryGetValue(hit.Value.Chunk.Value, out c); if (loaded) { if (this.Keyboard[Key.Q]) { this._Renderer.UnloadChunk(hit.Value.Chunk.Value); this._RendererTrans.UnloadChunk(hit.Value.Chunk.Value); } else if (this.Keyboard[Key.I]) { // TODO!!!!!!!!!!!!!!!!!! Point <int> pos = hit.Value.Chunk.Value; long regionX = (long)Math.Floor((decimal)pos.X / 32); long regionZ = (long)Math.Floor((decimal)pos.Y / 32); string file = Path.DirectorySeparatorChar + "region" + Path.DirectorySeparatorChar + "r." + Convert.ToString(regionX) + "." + Convert.ToString(regionZ) + ".mcr"; string msg = String.Format("Chunk: X {0} Y {1}\nFile: {2}", pos.X, pos.Y, file); msg += String.Format("\nX {0} Y {1} Z {2}", hit.Position.Y, hit.Position.Z, hit.Position.X); MessageBox.Show(msg); } else { this._SliceAxis = hit.Direction; this._SliceLevel = hit.Position[hit.Direction] + (hit.Value.Polarity == Polarity.Negative ? 1 : 0); this._SlicePolarity = hit.Value.Polarity; } } else { if (this.Keyboard[Key.E]) { bool a; Point <int> pos = hit.Value.Chunk.Value; if (this._Renderer.ChunksSelected.TryGetValue(pos, out a)) { this._Renderer.ChunksSelected.Remove(pos); } else { this._Renderer.ChunksSelected.Add(pos, true); } } else { if (this._Renderer.ChunksSelected.Count > 0) { foreach (KeyValuePair <Point <int>, bool> kv in this._Renderer.ChunksSelected) { this._Renderer.GetChunk(kv.Key); this._RendererTrans.GetChunk(kv.Key); } this._Renderer.ChunksSelected.Clear(); } else { this._Renderer.GetChunk(hit.Value.Chunk.Value); this._RendererTrans.GetChunk(hit.Value.Chunk.Value); } } } } } else { if (this._Renderer.ChunksSelected.Count > 0 && this.Keyboard[Key.E]) { this._Renderer.ChunksSelected.Clear(); } } }; this._Schemes = Schemes; this._Renderer.CurrentScheme = this._Schemes["Default"]; this._AverageFPS = 60.0; }