public static MapChunkData GetMapChunkData(Chunk chunk, bool firstInit) { MapChunkData chunkData = new MapChunkData(); ushort mask = 1; Queue<Section> sectionsToBeSent = new Queue<Section>(); for (int i = 0; i < 16; ++i) { Section currentSection = chunk.Sections[i]; if (currentSection != null && (firstInit || (chunk.SectionsToBeUpdated & 1) << i != 0)) { sectionsToBeSent.Enqueue(currentSection); } } int dataDim = sectionsToBeSent.Count * (Section.BYTESIZE + Section.SIZE); if (firstInit) dataDim += 256; chunkData.Data = new byte[dataDim]; int halfSize = sectionsToBeSent.Count * Section.HALFSIZE; int offsetData = sectionsToBeSent.Count * Section.SIZE; int offsetLight = offsetData + halfSize; int offsetSkyLight = offsetLight + halfSize; int sectionIndex = 0; while(sectionsToBeSent.Count > 0) { Section section = sectionsToBeSent.Dequeue(); Buffer.BlockCopy(section.Types, 0, chunkData.Data, sectionIndex * Section.SIZE, Section.SIZE); Buffer.BlockCopy(section.Data.Data, 0, chunkData.Data, offsetData + (sectionIndex * Section.HALFSIZE), Section.HALFSIZE); Buffer.BlockCopy(chunk.Light.Data, section.SectionId * Section.HALFSIZE, chunkData.Data, offsetLight + (sectionIndex * Section.HALFSIZE), Section.HALFSIZE); Buffer.BlockCopy(chunk.SkyLight.Data, section.SectionId * Section.HALFSIZE, chunkData.Data, offsetSkyLight + (sectionIndex * Section.HALFSIZE), Section.HALFSIZE); chunkData.PrimaryBitMask |= mask << section.SectionId; ++sectionIndex; // TODO: we leave add array and biome array to 0 (ocean), we need to change the chunk generator accordingly } return chunkData; }
public override void Read(PacketReader stream) { int posX = stream.ReadInt(); short posY = stream.ReadShort(); int posZ = stream.ReadInt(); byte sizeX = (byte)(stream.ReadByte() + 1); byte sizeY = (byte)(stream.ReadByte() + 1); byte sizeZ = (byte)(stream.ReadByte() + 1); int o = sizeX * sizeY * sizeZ; Chunk = new Chunk(null, new Vector3I(posX, posY, posZ)); int len = stream.ReadInt(); stream.ReadBytes(len); }
internal static void MakeInitChunk( Chunk chunk, SMPPacketWriter Writer ) { /* byte[] ChunkArray = null; lock ( chunk.blockslock ) { using ( MemoryStream memStream = new MemoryStream() ) { for ( int a = 0; a < 16; a++ ) { for ( int i = 0; i < ( 16 ); i++ ) { // Write Blocks memStream.WriteByte( 5 ); } for ( int i = 0; i < ( 16 ); i++ ) { // Write MetaData memStream.WriteByte( ( ( 0 & 0x0F ) << 4 ) | ( 0 & 0x0F ) ); } for ( int i = 0; i < ( 16 ); i++ ) { // Write BlockLight memStream.WriteByte( 0 ); } for ( int i = 0; i < ( 16 ); i++ ) { // Write SkyLight memStream.WriteByte( ( ( 2 & 0x0F ) << 4 ) | ( 2 & 0x0F ) ); } // for ( int i = 0; i < ( 16 ); i++ ) { //Biomes? // memStream.WriteByte( 0 ); //} } ChunkArray = Ionic.Zlib.ZlibStream.CompressBuffer(memStream.ToArray()); } Logger.LogToConsole( "Init length: " + ChunkArray.Length.ToString() ); }*/ new InitChunkPacket() { X = chunk.X, Z = chunk.Z, PrimaryBitMap = 1, AddBitMap = 1, GroundUp = false, Sunlight = 2 }.Write( Writer ); }
public static void MakeMapChunkPacket( Chunk chunk, SMPPacketWriter Writer ) { var X = ( int )chunk.X; var Z = ( int )chunk.Z; byte[] blockData; byte[] metadata; byte[] blockLight; byte[] skyLight; ushort mask = 1, chunkY = 0; bool nonAir = true; // First pass calculates number of sections to send int totalSections = 0; for ( int i = 15; i >= 0; i-- ) { Section s = chunk.Sections[chunkY++]; if ( s.IsAir ) nonAir = false; if ( nonAir ) totalSections++; } mask = 1; chunkY = 0; nonAir = true; blockData = new byte[totalSections * BlockDataLength]; metadata = new byte[totalSections * NibbleDataLength]; blockLight = new byte[totalSections * NibbleDataLength]; skyLight = new byte[totalSections * NibbleDataLength]; ushort PrimaryBitMap = 0, AddBitMap = 0; // Second pass produces the arrays for ( int i = 15; i >= 0; i-- ) { Section s = chunk.Sections[chunkY++]; if ( s.IsAir ) nonAir = false; if ( nonAir ) { Array.Copy( s.Blocks, 0, blockData, ( chunkY - 1 ) * BlockDataLength, BlockDataLength ); Array.Copy( s.Metadata.Data, 0, metadata, ( chunkY - 1 ) * NibbleDataLength, NibbleDataLength ); Array.Copy( s.BlockLight.Data, 0, blockLight, ( chunkY - 1 ) * NibbleDataLength, NibbleDataLength ); Array.Copy( s.SkyLight.Data, 0, skyLight, ( chunkY - 1 ) * NibbleDataLength, NibbleDataLength ); PrimaryBitMap |= mask; } mask <<= 1; } // Create the final array // TODO: Merge this into the other loop, reduce objects byte[] data = new byte[blockData.Length + metadata.Length + blockLight.Length + skyLight.Length + chunk.Biomes.Length]; int index = 0; Array.Copy( blockData, 0, data, index, blockData.Length ); index += blockData.Length; Array.Copy( metadata, 0, data, index, metadata.Length ); index += metadata.Length; Array.Copy( blockLight, 0, data, index, blockLight.Length ); index += blockLight.Length; Array.Copy( skyLight, 0, data, index, skyLight.Length ); index += skyLight.Length; Array.Copy(chunk.Biomes, 0, data, index, chunk.Biomes.Length); // Compress the array var result = Ionic.Zlib.ZlibStream.CompressBuffer( data ); var GroundUpContiguous = true; Logger.LogToConsole( "Chunk length: "+result.Length.ToString() ); Writer.Write( 0x38 ); Writer.Write( X ); Writer.Write( Z ); Writer.Write( GroundUpContiguous ); Writer.Write( PrimaryBitMap ); Writer.Write( AddBitMap ); Writer.Write( result.Length ); Writer.Write( result ); Writer.Flush(); }
public void UpdateChunks() { lock ( chunkUpdateLock ) { Position pos = WorldManager.MainWorld.Map.Spawn; // Get neccesary chunk range int RequiredMinX = ( int )( ( int )pos.X / 16 ) - ( ChunkArea / 2 ); int RequiredMinZ = ( int )( ( int )pos.Y / 16 ) - ( ChunkArea / 2 ); // Check if new chunks are required if ( RequiredMinX == LoadedChunksMinX && RequiredMinZ == LoadedChunksMinZ ) return; List<Chunk> tosend = new List<Chunk>(); // Send Pre-Chunks and Chunks for ( int Xchunk = RequiredMinX; Xchunk < ( RequiredMinX + ChunkArea ); Xchunk++ ) { for ( int Zchunk = RequiredMinZ; Zchunk < ( RequiredMinZ + ChunkArea ); Zchunk++ ) { if ( ( Xchunk >= ( LoadedChunksMinX + ChunkArea ) || Xchunk < ( LoadedChunksMinX ) || Zchunk >= ( LoadedChunksMinZ + ChunkArea ) || Zchunk < ( LoadedChunksMinZ ) ) || ( !HasChunks ) ) { Chunk chunkToSend = new Chunk( Xchunk, Zchunk, WorldManager.MainWorld ); //Server.world.GetChunk( Xchunk, Zchunk ); if ( chunkToSend == null ) { Logger.Log( LogType.Error, "Player.UpdateChunks: Error loading or generating chunk! ({0}, {1})", Xchunk, Zchunk ); //session.KickNow( "ERROR: Failed to load or generate chunk! (" + Xchunk + ", " + Zchunk + ")" ); return; } // chunkToSend.AddPlayer( this ); if ( !chunkToSend.terrainPopulated ) chunkToSend.CalculateLighting(); tosend.Add( chunkToSend ); SMPPacketWriter.MakeInitChunk( chunkToSend, smpWriter ); SMPPacketWriter.MakeMapChunkPacket( chunkToSend, smpWriter ); // session.SendNow( PacketWriter.MakePreChunk( Xchunk, Zchunk, true ) ); //session.SendNow( PacketWriter.MakeChunk( chunkToSend ) ); } } } } }