/// <summary> /// Deserialisiert die Chunksäule aus dem angegebenen Stream. /// </summary> /// <param name="stream">Quellstream</param> /// <param name="definitionManager">Der verwendete DefinitionManager</param> /// <param name="columnIndex">Die Position der Säule</param> /// <param name="planetId">Der Index des Planeten</param> public void Deserialize(BinaryReader reader, IDefinitionManager definitionManager) { bool longIndex = reader.ReadByte() > 0; // Phase 1 (Column Meta: Heightmap, populated, chunkcount) Chunks = new Chunk[reader.ReadByte()]; // Chunk Count Populated = reader.ReadBoolean(); // Populated Index = new Index2(reader.ReadInt32(), reader.ReadInt32()); Planet = reader.ReadInt32(); for (int y = 0; y < Chunk.CHUNKSIZE_Y; y++) // Heightmap { for (int x = 0; x < Chunk.CHUNKSIZE_X; x++) { Heights[x, y] = reader.ReadUInt16(); } } int[] counter = new int[Chunks.Length]; for (int i = 0; i < Chunks.Length; i++) // ChangeCounter { counter[i] = reader.ReadInt32(); } // Phase 2 (Block Definitionen) List <IDefinition> types = new List <IDefinition>(); Dictionary <ushort, ushort> map = new Dictionary <ushort, ushort>(); int typecount = longIndex ? reader.ReadUInt16() : reader.ReadByte(); for (int i = 0; i < typecount; i++) { string typeName = reader.ReadString(); IDefinition[] definitions = definitionManager.GetDefinitions().ToArray(); var blockDefinition = definitions.FirstOrDefault(d => d.GetType().FullName == typeName); types.Add(blockDefinition); map.Add((ushort)types.Count, (ushort)(Array.IndexOf(definitions, blockDefinition) + 1)); } // Phase 3 (Chunk Infos) for (int c = 0; c < Chunks.Length; c++) { IChunk chunk = Chunks[c] = new Chunk(new Index3(Index, c), Planet); chunk.Changed += OnChunkChanged; chunk.SetColumn(this); for (int i = 0; i < chunk.Blocks.Length; i++) { ushort typeIndex = longIndex ? reader.ReadUInt16() : reader.ReadByte(); chunk.MetaData[i] = 0; if (typeIndex > 0) { chunk.Blocks[i] = map[typeIndex]; var definition = (IBlockDefinition)definitionManager.GetDefinitionByIndex(map[typeIndex]); if (definition.HasMetaData) { chunk.MetaData[i] = reader.ReadInt32(); } } } chunk.ChangeCounter = counter[c]; } //Entities lesen var count = reader.ReadInt32(); for (int i = 0; i < count; i++) { var name = reader.ReadString(); var length = reader.ReadInt32(); byte[] buffer = new byte[length]; reader.Read(buffer, 0, length); try { var type = Type.GetType(name); if (type == null) { continue; } Entity entity = (Entity)Activator.CreateInstance(type); using (MemoryStream memorystream = new MemoryStream(buffer)) { using (BinaryReader componentbinarystream = new BinaryReader(memorystream)) { entity.Deserialize(componentbinarystream, definitionManager); } } Entities.Add(entity); } catch (Exception) { } } }
public bool RegenerateVertexBuffer() { if (!ChunkPosition.HasValue) { return(false); } // Chunk nachladen if (this.chunk == null) { this.chunk = _manager.GetChunk(ChunkPosition.Value); if (this.chunk == null) { //Thread.Sleep(10); //RegenerateVertexBuffer(); //NeedsUpdate = false; return(false); } this.chunk.Changed += OnChunkChanged; } var chunk = this.chunk; List <VertexPositionNormalTextureLight> vertices = new List <VertexPositionNormalTextureLight>(); int textureColumns = textures.Width / SceneControl.TEXTURESIZE; float textureWidth = 1f / textureColumns; float texelSize = 1f / SceneControl.TEXTURESIZE; float textureSizeGap = texelSize; float textureGap = texelSize / 2; // BlockTypes sammlen Dictionary <IBlockDefinition, int> textureOffsets = new Dictionary <IBlockDefinition, int>(); // Dictionary<Type, BlockDefinition> definitionMapping = new Dictionary<Type, BlockDefinition>(); int definitionIndex = 0; foreach (var definition in definitionManager.GetBlockDefinitions()) { int textureCount = definition.Textures.Count(); textureOffsets.Add(definition, definitionIndex); // definitionMapping.Add(definition.GetBlockType(), definition); definitionIndex += textureCount; } Vector2[] uvOffsets = new[] { new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1) }; for (int z = 0; z < Chunk.CHUNKSIZE_Z; z++) { for (int y = 0; y < Chunk.CHUNKSIZE_Y; y++) { for (int x = 0; x < Chunk.CHUNKSIZE_X; x++) { ushort block = chunk.GetBlock(x, y, z); if (block == 0) { continue; } IBlockDefinition blockDefinition = (IBlockDefinition)definitionManager.GetDefinitionByIndex(block); if (blockDefinition == null) { continue; } int textureIndex; if (!textureOffsets.TryGetValue(blockDefinition, out textureIndex)) { continue; } // Textur-Koordinate "berechnen" Vector2 textureOffset = new Vector2(); //Vector2 textureSize = new Vector2(textureWidth - textureSizeGap, textureWidth - textureSizeGap); ushort topBlock = _manager.GetBlock((ChunkPosition.Value * Chunk.CHUNKSIZE) + new Index3(x, y, z + 1)); IBlockDefinition topBlockDefintion = (IBlockDefinition)definitionManager.GetDefinitionByIndex(topBlock); var globalX = x + chunk.Index.X * Chunk.CHUNKSIZE_X; var globalY = y + chunk.Index.Y * Chunk.CHUNKSIZE_Y; var globalZ = z + chunk.Index.Z * Chunk.CHUNKSIZE_Z; // Top if (topBlock == 0 || (!topBlockDefintion.IsSolidWall(Wall.Bottom) && topBlock != block)) { textureOffset = new Vector2( (((textureIndex + blockDefinition.GetTextureIndex(Wall.Top, _manager, globalX, globalY, globalZ)) % textureColumns) * textureWidth) + textureGap, (((textureIndex + blockDefinition.GetTextureIndex(Wall.Top, _manager, globalX, globalY, globalZ)) / textureColumns) * textureWidth) + textureGap); int rotation = -blockDefinition.GetTextureRotation(Wall.Top, _manager, globalX, globalY, globalZ); int localOffset = vertices.Count; vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 0, y + 1, z + 1), new Vector3(0, 0, 1), uvOffsets[(6 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Top, _manager, globalX, globalY, globalZ)), 0)); vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 1, y + 1, z + 1), new Vector3(0, 0, 1), uvOffsets[(7 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Top, _manager, globalX, globalY, globalZ)), 0)); vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 0, y + 0, z + 1), new Vector3(0, 0, 1), uvOffsets[(5 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Top, _manager, globalX, globalY, globalZ)), 0)); vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 1, y + 0, z + 1), new Vector3(0, 0, 1), uvOffsets[(4 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Top, _manager, globalX, globalY, globalZ)), 0)); } ushort bottomBlock = _manager.GetBlock((ChunkPosition.Value * Chunk.CHUNKSIZE) + new Index3(x, y, z - 1)); IBlockDefinition bottomBlockDefintion = (IBlockDefinition)definitionManager.GetDefinitionByIndex(bottomBlock); // Unten if (bottomBlock == 0 || (!bottomBlockDefintion.IsSolidWall(Wall.Top) && bottomBlock != block)) { textureOffset = new Vector2( (((textureIndex + blockDefinition.GetTextureIndex(Wall.Bottom, _manager, globalX, globalY, globalZ)) % textureColumns) * textureWidth) + textureGap, (((textureIndex + blockDefinition.GetTextureIndex(Wall.Bottom, _manager, globalX, globalY, globalZ)) / textureColumns) * textureWidth) + textureGap); int rotation = -blockDefinition.GetTextureRotation(Wall.Bottom, _manager, globalX, globalY, globalZ); int localOffset = vertices.Count; vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 1, y + 1, z + 0), new Vector3(0, 0, -1), uvOffsets[(6 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Bottom, _manager, globalX, globalY, globalZ)), 0)); vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 0, y + 1, z + 0), new Vector3(0, 0, -1), uvOffsets[(7 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Bottom, _manager, globalX, globalY, globalZ)), 0)); vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 1, y + 0, z + 0), new Vector3(0, 0, -1), uvOffsets[(5 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Bottom, _manager, globalX, globalY, globalZ)), 0)); vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 0, y + 0, z + 0), new Vector3(0, 0, -1), uvOffsets[(4 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Bottom, _manager, globalX, globalY, globalZ)), 0)); } ushort southBlock = _manager.GetBlock((ChunkPosition.Value * Chunk.CHUNKSIZE) + new Index3(x, y + 1, z)); IBlockDefinition southBlockDefintion = (IBlockDefinition)definitionManager.GetDefinitionByIndex(southBlock); // South if (southBlock == 0 || (!southBlockDefintion.IsSolidWall(Wall.Front) && southBlock != block)) { textureOffset = new Vector2( (((textureIndex + blockDefinition.GetTextureIndex(Wall.Front, _manager, globalX, globalY, globalZ)) % textureColumns) * textureWidth) + textureGap, (((textureIndex + blockDefinition.GetTextureIndex(Wall.Front, _manager, globalX, globalY, globalZ)) / textureColumns) * textureWidth) + textureGap); int rotation = -blockDefinition.GetTextureRotation(Wall.Front, _manager, globalX, globalY, globalZ); int localOffset = vertices.Count; vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 0, y + 1, z + 0), new Vector3(0, 1, 0), uvOffsets[(6 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Front, _manager, globalX, globalY, globalZ)), 0)); vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 1, y + 1, z + 0), new Vector3(0, 1, 0), uvOffsets[(7 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Front, _manager, globalX, globalY, globalZ)), 0)); vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 0, y + 1, z + 1), new Vector3(0, 1, 0), uvOffsets[(5 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Front, _manager, globalX, globalY, globalZ)), 0)); vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 1, y + 1, z + 1), new Vector3(0, 1, 0), uvOffsets[(4 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Front, _manager, globalX, globalY, globalZ)), 0)); } ushort northBlock = _manager.GetBlock((ChunkPosition.Value * Chunk.CHUNKSIZE) + new Index3(x, y - 1, z)); IBlockDefinition northBlockDefintion = (IBlockDefinition)definitionManager.GetDefinitionByIndex(northBlock); // North if (northBlock == 0 || (!northBlockDefintion.IsSolidWall(Wall.Back) && northBlock != block)) { textureOffset = new Vector2( (((textureIndex + blockDefinition.GetTextureIndex(Wall.Back, _manager, globalX, globalY, globalZ)) % textureColumns) * textureWidth) + textureGap, (((textureIndex + blockDefinition.GetTextureIndex(Wall.Back, _manager, globalX, globalY, globalZ) / textureColumns) * textureWidth) + textureGap)); int rotation = -blockDefinition.GetTextureRotation(Wall.Back, _manager, globalX, globalY, globalZ); int localOffset = vertices.Count; vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 0, y + 0, z + 1), new Vector3(0, -1, 0), uvOffsets[(4 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Back, _manager, globalX, globalY, globalZ)), 0)); vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 1, y + 0, z + 1), new Vector3(0, -1, 0), uvOffsets[(5 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Back, _manager, globalX, globalY, globalZ)), 0)); vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 0, y + 0, z + 0), new Vector3(0, -1, 0), uvOffsets[(7 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Back, _manager, globalX, globalY, globalZ)), 0)); vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 1, y + 0, z + 0), new Vector3(0, -1, 0), uvOffsets[(6 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Back, _manager, globalX, globalY, globalZ)), 0)); } ushort westBlock = _manager.GetBlock((ChunkPosition.Value * Chunk.CHUNKSIZE) + new Index3(x - 1, y, z)); IBlockDefinition westBlockDefintion = (IBlockDefinition)definitionManager.GetDefinitionByIndex(westBlock); // West if (westBlock == 0 || (!westBlockDefintion.IsSolidWall(Wall.Right) && westBlock != block)) { textureOffset = new Vector2( (((textureIndex + blockDefinition.GetTextureIndex(Wall.Left, _manager, globalX, globalY, globalZ)) % textureColumns) * textureWidth) + textureGap, (((textureIndex + blockDefinition.GetTextureIndex(Wall.Left, _manager, globalX, globalY, globalZ)) / textureColumns) * textureWidth) + textureGap); int rotation = -blockDefinition.GetTextureRotation(Wall.Left, _manager, globalX, globalY, globalZ); int localOffset = vertices.Count; vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 0, y + 1, z + 0), new Vector3(-1, 0, 0), uvOffsets[(7 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Left, _manager, globalX, globalY, globalZ)), 0)); vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 0, y + 1, z + 1), new Vector3(-1, 0, 0), uvOffsets[(4 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Left, _manager, globalX, globalY, globalZ)), 0)); vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 0, y + 0, z + 0), new Vector3(-1, 0, 0), uvOffsets[(6 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Left, _manager, globalX, globalY, globalZ)), 0)); vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 0, y + 0, z + 1), new Vector3(-1, 0, 0), uvOffsets[(5 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Left, _manager, globalX, globalY, globalZ)), 0)); } ushort eastBlock = _manager.GetBlock((ChunkPosition.Value * Chunk.CHUNKSIZE) + new Index3(x + 1, y, z)); IBlockDefinition eastBlockDefintion = (IBlockDefinition)definitionManager.GetDefinitionByIndex(eastBlock); // Ost if (eastBlock == 0 || (!eastBlockDefintion.IsSolidWall(Wall.Left) && eastBlock != block)) { textureOffset = new Vector2( (((textureIndex + blockDefinition.GetTextureIndex(Wall.Right, _manager, globalX, globalY, globalZ)) % textureColumns) * textureWidth) + textureGap, (((textureIndex + blockDefinition.GetTextureIndex(Wall.Right, _manager, globalX, globalY, globalZ)) / textureColumns) * textureWidth) + textureGap); int rotation = -blockDefinition.GetTextureRotation(Wall.Right, _manager, globalX, globalY, globalZ); int localOffset = vertices.Count; vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 1, y + 1, z + 1), new Vector3(1, 0, 0), uvOffsets[(5 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Right, _manager, globalX, globalY, globalZ)), 0)); vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 1, y + 1, z + 0), new Vector3(1, 0, 0), uvOffsets[(6 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Right, _manager, globalX, globalY, globalZ)), 0)); vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 1, y + 0, z + 1), new Vector3(1, 0, 0), uvOffsets[(4 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Right, _manager, globalX, globalY, globalZ)), 0)); vertices.Add( new VertexPositionNormalTextureLight( new Vector3(x + 1, y + 0, z + 0), new Vector3(1, 0, 0), uvOffsets[(7 + rotation) % 4], (byte)(textureIndex + blockDefinition.GetTextureIndex(Wall.Right, _manager, globalX, globalY, globalZ)), 0)); } } } } vertexCount = vertices.Count; indexCount = vertices.Count * 6 / 4; if (vertexCount > 0) { Dispatch(() => { if (vb == null || ib == null) { vb = new VertexBuffer(graphicsDevice, VertexPositionNormalTextureLight.VertexDeclaration, vertexCount + 2); } if (vertexCount + 2 > vb.VertexCount) { vb.Resize(vertexCount + 2); } vb.SetData(vertices.ToArray()); }); } lock (this) { if (chunk != null && chunk.Index != ChunkPosition) { return(loaded); } loaded = true; NeedsUpdate |= chunk != this.chunk; return(!NeedsUpdate); } }
/// <summary> /// Serialisiert die Chunksäule in den angegebenen Stream. /// </summary> /// <param name="writer">Zielschreiber</param> /// <param name="definitionManager">Der verwendete DefinitionManager</param> public void Serialize(BinaryWriter writer, IDefinitionManager definitionManager) { // Definitionen sammeln List <IBlockDefinition> definitions = new List <IBlockDefinition>(); for (int c = 0; c < Chunks.Length; c++) { IChunk chunk = Chunks[c]; for (int i = 0; i < chunk.Blocks.Length; i++) { if (chunk.Blocks[i] != 0) { IBlockDefinition definition = (IBlockDefinition)definitionManager.GetDefinitionByIndex(chunk.Blocks[i]); if (!definitions.Contains(definition)) { definitions.Add(definition); } } } } bool longIndex = definitions.Count > 254; writer.Write((byte)((longIndex) ? 1 : 0)); // Schreibe Phase 1 (Column Meta: Heightmap, populated, chunkcount) writer.Write((byte)Chunks.Length); // Chunk Count writer.Write(Populated); // Populated writer.Write(Index.X); writer.Write(Index.Y); writer.Write(Planet); for (int y = 0; y < Chunk.CHUNKSIZE_Y; y++) // Heightmap { for (int x = 0; x < Chunk.CHUNKSIZE_X; x++) { writer.Write((ushort)Heights[x, y]); } } for (int i = 0; i < Chunks.Length; i++) // Change Counter { writer.Write(Chunks[i].ChangeCounter); } // Schreibe Phase 2 (Block Definitionen) if (longIndex) { writer.Write((ushort)definitions.Count); } else { writer.Write((byte)definitions.Count); } foreach (var definition in definitions) { writer.Write(definition.GetType().FullName); } // Schreibe Phase 3 (Chunk Infos) for (int c = 0; c < Chunks.Length; c++) { IChunk chunk = Chunks[c]; for (int i = 0; i < chunk.Blocks.Length; i++) { if (chunk.Blocks[i] == 0) { // Definition Index (Air) if (longIndex) { writer.Write((ushort)0); } else { writer.Write((byte)0); } } else { // Definition Index IBlockDefinition definition = (IBlockDefinition)definitionManager.GetDefinitionByIndex(chunk.Blocks[i]); if (longIndex) { writer.Write((ushort)(definitions.IndexOf(definition) + 1)); } else { writer.Write((byte)(definitions.IndexOf(definition) + 1)); } // Meta Data if (definition.HasMetaData) { writer.Write(chunk.MetaData[i]); } } } } //Entities schreiben writer.Write(Entities.Count); foreach (var entity in Entities) { using (MemoryStream memorystream = new MemoryStream()) { writer.Write(entity.GetType().AssemblyQualifiedName); using (BinaryWriter componentbinarystream = new BinaryWriter(memorystream)) { try { entity.Serialize(componentbinarystream, definitionManager); writer.Write((int)memorystream.Length); memorystream.WriteTo(writer.BaseStream); } catch (Exception) { writer.Write(0); //throw; } } } } }