OSDN Git Service

W.I.P. Heightmap, needs handling for permeable blocks
[automap/automap.git] / Automap / Data / ColumnMeta.cs
index 00d4b09..bdba0f7 100644 (file)
 using System;
+using System.Collections;
 using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Diagnostics;
 using System.Collections.ObjectModel;
-using System.Linq;
+
 
 using Vintagestory.API.MathTools;
 using Vintagestory.API.Common;
+using Vintagestory.API.Client;
 
 using ProtoBuf;
 
 
 namespace Automap
 {
-       [ProtoContract]
+       [ProtoContract(ImplicitFields = ImplicitFields.None)]
        public struct ColumnMeta
        {
                [ProtoMember(1)]
                public Vec2i Location;
 
+               [DisplayName(0, "Coords.")]
+               [ProtoIgnore]
+               public string PrettyLocation;
+
                [ProtoMember(2)]
                public TimeSpan ChunkAge;//OLDEST CHUNK. from chunk last edit
 
+               [DisplayName(1, "Age")]
+               [ProtoIgnore]
+               public string ShortChunkAge { get => ChunkAge.ToString("c"); }
+
+               [DisplayName(2, "Temp.")]
                [ProtoMember(3)]
                public float Temperature;// Temperature - surface
 
+               [DisplayName(3, "Y Max.")]
                [ProtoMember(4)]
                public ushort YMax;// Y feature height
 
                [ProtoMember(5)]
-               public Dictionary<int,uint> RockRatio;//[Column] Geographic region (rock) Ratio. [BlockID * count]
-
+               public Dictionary<int, uint> RockRatio;//[Column] Geographic region (rock) Ratio. [BlockID * count]
+
+               //[DisplayName(10, "Rocks")]
+               //public JArray FlatRocks
+               //{
+               //      get {
+               //              string[] rocks = new string[this.RockRatio.Count];
+               //              int i = 0;
+               //              foreach (var roc in RockRatio)
+               //              {
+               //                      rocks[i++] = $"\"{roc.Key}\":\"{roc.Value}\"";
+               //              }
+               //              return new JArray(rocks);
+               //      }
+               //}
+
+
+               [DisplayName(4, "Fert.")]
                [ProtoMember(6)]
                public float Fertility;
 
+               //[DisplayName(5, "Forest")]
                [ProtoMember(7)]
-               public float ForestDensity;
+               public float ForestDensity; // not given to client
 
+               [DisplayName(6, "Rain")]
                [ProtoMember(8)]
                public float Rainfall;
 
+               //[DisplayName(7, "Shrub")]
                [ProtoMember(9)]
-               public float ShrubDensity;
+               public float ShrubDensity; // not given to client
 
+               [DisplayName(8, "Air blocks")]
                [ProtoMember(10)]
-               public ushort AirBlocks;
+               public uint AirBlocks;
 
+               [DisplayName(9, "Non-air")]
                [ProtoMember(11)]
-               public ushort NonAirBlocks;
+               public uint NonAirBlocks;
+
+               [ProtoMember(12)]
+               public byte ChunkSize;
 
-               //[ProtoMember(12,OverwriteList = true)]
+
+               [ProtoIgnore]
+               public ushort[,] HeightMap;//Needs to be 'flattened' for Protocol-Buffer serialization
+
+               [ProtoMember(13)]
+               private ushort[] _flattened_HeightMap;                  
+
+               /// <summary>
+               /// Column Presense Bitmap
+               /// </summary>
                [ProtoIgnore]
-               public ushort[ , ] HeightMap;
+               public BitArray ColumnPresense;
 
-               public ColumnMeta(Vec2i loc, int chunkSize = 32)
+               public ColumnMeta(Vec2i loc, ICoreClientAPI clientAPI, byte chunkSize = 32, int maxChunkHeight = 16)
                {
-               Location = loc;
-               ChunkAge = TimeSpan.Zero;
-               Temperature = 0f;
-               YMax = 0;
-               RockRatio = new Dictionary<int, uint>( 10 );
-               Fertility = 0f;
-               ForestDensity = 0f;
-               Rainfall = 0f;
-               ShrubDensity = 0f;
+                       Location = loc;
+                       PrettyLocation = loc.PrettyCoords(clientAPI);
+                       ChunkAge = TimeSpan.Zero;
+                       Temperature = 0f;
+                       YMax = 0;
+                       RockRatio = new Dictionary<int, uint>(10);
+                       Fertility = 0f;
+                       ForestDensity = 0f;
+                       Rainfall = 0f;
+                       ShrubDensity = 0f;
+                       AirBlocks = 0;
+                       NonAirBlocks = 0;
+                       ChunkSize = chunkSize;
+                       HeightMap = new ushort[ChunkSize, ChunkSize];
+                       _flattened_HeightMap = null;
+                       ColumnPresense = new BitArray(maxChunkHeight, false);//TODO: get real chunk height MAX
+               }
+
+               internal void UpdateFieldsFrom(ClimateCondition climate, IMapChunk mapChunk, TimeSpan chunkAge)
+               {
+                       this.ChunkAge = chunkAge;
+                       this.Temperature = climate.Temperature;
+                       this.Fertility = climate.Fertility;
+                       this.ForestDensity = climate.ForestDensity;
+                       this.Rainfall = climate.Rainfall;
+                       this.ShrubDensity = climate.ShrubDensity;
+
+                       this.YMax = mapChunk.YMax;
+               }
+
+               internal void ResetMetadata(int mapSizeY )
+               {
+               if (this.ColumnPresense == null) { this.ColumnPresense = new BitArray((mapSizeY / this.ChunkSize), false); }            
+
+               //Start fresh...
+               HeightMap = new ushort[ChunkSize, ChunkSize]; 
+               RockRatio = new Dictionary<int, uint>(this.RockRatio.Count);
                AirBlocks = 0;
                NonAirBlocks = 0;
-               HeightMap = new ushort[chunkSize, chunkSize];
+               YMax = 0;
                }
 
-               internal void UpdateFieldsFrom(ClimateCondition climate, IMapChunk mapChunk ,TimeSpan chunkAge)
+               [ProtoBeforeSerialization]
+               private void PrepareData()
                {
-               this.ChunkAge = chunkAge;
-               this.Temperature = climate.Temperature;
-               this.Fertility = climate.Fertility;
-               this.ForestDensity = climate.ForestDensity;
-               this.Rainfall = climate.Rainfall;
-               this.ShrubDensity = climate.ShrubDensity;
 
-               this.YMax = mapChunk.YMax;
-                                       
+                       if (HeightMap != null)
+                       {
+                               _flattened_HeightMap = new ushort[ChunkSize * ChunkSize];
+                               int flatIndex = 0;
+
+                               for (byte col = 0; col < ChunkSize; col++)
+                               {
+                                       for (byte row = 0; row < ChunkSize; row++)
+                                       {
+                                               _flattened_HeightMap[flatIndex] = HeightMap[col, row];
+                                               flatIndex++;
+                                       }
+                               }
+
+                       }
+
+               }
+
+
+               [ProtoAfterDeserialization]
+               private void PostProcess()
+               {
+                       ChunkSize = (ChunkSize == byte.MinValue) ? (byte)32 : ChunkSize;//Not good - if chunk wasn't 32 orignally!
+
+                       if (this.HeightMap == null || this.HeightMap.Length != (ChunkSize * ChunkSize)) {
+                       this.HeightMap = new ushort[ChunkSize, ChunkSize];
+                       }
+
+                       if (_flattened_HeightMap != null)
+                       {
+                               int col, row;
+                               var bitMasker = new BitVector32(0);
+                               var rowSection = BitVector32.CreateSection((short) (ChunkSize - 1));
+                               var colSection = BitVector32.CreateSection((short) (ChunkSize - 1), rowSection);
+
+                               for (uint rowcol = 0; rowcol < (ChunkSize * ChunkSize); rowcol++)
+                               {
+                                       bitMasker = new BitVector32(data: (int) rowcol);
+                                       row = bitMasker[rowSection];
+                                       col = bitMasker[colSection];
+                                       HeightMap[col, row] = _flattened_HeightMap[rowcol];
+                               }
+
+                       }
+
+               }
+
+
+               internal ColumnMeta Reload(ICoreClientAPI clientAPI)
+               {
+                       this.PrettyLocation = Location.PrettyCoords(clientAPI);
+                       Debug.Write(PrettyLocation == null ? "*" : ",");
+                       return this;
                }
        }
 
        public class ColumnsMetadata : KeyedCollection<Vec2i, ColumnMeta>
        {
-               private ColumnsMetadata( )
+               private ColumnsMetadata()
                {
                        throw new NotSupportedException();
                }
 
                public ColumnsMetadata(Vec2i startChunkColumn)
                {
-               North_mostChunk = startChunkColumn.Y;
-               South_mostChunk = startChunkColumn.Y;
-               East_mostChunk = startChunkColumn.X;
-               West_mostChunk = startChunkColumn.X;
+                       North_mostChunk = startChunkColumn.Y;
+                       South_mostChunk = startChunkColumn.Y;
+                       East_mostChunk = startChunkColumn.X;
+                       West_mostChunk = startChunkColumn.X;
                }
 
-               public int North_mostChunk {
+               public int North_mostChunk
+               {
                        get; private set;
                }
 
-               public int South_mostChunk {
+               public int South_mostChunk
+               {
                        get; private set;
                }
 
-               public int East_mostChunk {
+               public int East_mostChunk
+               {
                        get; private set;
                }
 
-               public int West_mostChunk {
+               public int West_mostChunk
+               {
                        get; private set;
                }
 
                protected override Vec2i GetKeyForItem(ColumnMeta item)
                {
-               return item.Location;
+                       return item.Location;
                }
 
                internal void Update(ColumnMeta metaData)
                {
-               if (this.Contains(metaData.Location)) {
-               this.Remove(metaData.Location);
-               this.Add(metaData);
-               }
-               else {
-               this.Add(metaData);
-               }
+                       if (this.Contains(metaData.Location))
+                       {
+                               this.Remove(metaData.Location);
+                               this.Add(metaData);
+                       }
+                       else
+                       {
+                               this.Add(metaData);
+                       }
 
                }
 
                public new void Add(ColumnMeta newItem)
                {
-               if (North_mostChunk > newItem.Location.Y) {
-               North_mostChunk = newItem.Location.Y;
-               }
-
-               if (South_mostChunk < newItem.Location.Y) {
-               South_mostChunk = newItem.Location.Y;
-               }
-
-               if (East_mostChunk < newItem.Location.X) {
-               East_mostChunk = newItem.Location.X;
+                       if (North_mostChunk > newItem.Location.Y)
+                       {
+                               North_mostChunk = newItem.Location.Y;
+                       }
+
+                       if (South_mostChunk < newItem.Location.Y)
+                       {
+                               South_mostChunk = newItem.Location.Y;
+                       }
+
+                       if (East_mostChunk < newItem.Location.X)
+                       {
+                               East_mostChunk = newItem.Location.X;
+                       }
+
+                       if (West_mostChunk > newItem.Location.X)
+                       {
+                               West_mostChunk = newItem.Location.X;
+                       }
+
+                       base.Add(newItem);
                }
 
-               if (West_mostChunk > newItem.Location.X) {
-               West_mostChunk = newItem.Location.X;
+               public void ClearMetadata( )
+               {
+               for (int i = 0, maxItemsCount = this.Items.Count; i < maxItemsCount; i++) {
+               ColumnMeta entry = this.Items[i];
+               entry.HeightMap = null;
+               entry.RockRatio = null;//Also regenerated when any chunk in a column is changed...
                }
-
-               base.Add(newItem);
                }
 
        }
 }
-