OSDN Git Service

W.I.P. Fixes for several issues - plus better Shard processing
[automap/automap.git] / Automap / Data / ColumnMeta.cs
1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.Collections.Specialized;
5 using System.Diagnostics;
6 using System.Collections.ObjectModel;
7
8
9 using Vintagestory.API.MathTools;
10 using Vintagestory.API.Common;
11 using Vintagestory.API.Client;
12
13 using ProtoBuf;
14
15
16 namespace Automap
17 {
18         [ProtoContract(ImplicitFields = ImplicitFields.None)]
19         public struct ColumnMeta
20         {
21                 [ProtoMember(1)]
22                 public Vec2i Location;
23
24                 [DisplayName(0, "Coords.")]
25                 [ProtoIgnore]
26                 public string PrettyLocation;
27
28                 [ProtoMember(2)]
29                 public TimeSpan ChunkAge;//OLDEST CHUNK. from chunk last edit
30
31                 [DisplayName(1, "Age")]
32                 [ProtoIgnore]
33                 public string ShortChunkAge { get => ChunkAge.ToString("c"); }
34
35                 [DisplayName(2, "Temp.")]
36                 [ProtoMember(3)]
37                 public float Temperature;// Temperature - surface
38
39                 [DisplayName(3, "Y Max.")]
40                 [ProtoMember(4)]
41                 public ushort YMax;// Y feature height
42
43                 [ProtoMember(5)]
44                 public Dictionary<int, uint> RockRatio;//[Column] Geographic region (rock) Ratio. [BlockID * count]
45
46                 //[DisplayName(10, "Rocks")]
47                 //public JArray FlatRocks
48                 //{
49                 //      get {
50                 //              string[] rocks = new string[this.RockRatio.Count];
51                 //              int i = 0;
52                 //              foreach (var roc in RockRatio)
53                 //              {
54                 //                      rocks[i++] = $"\"{roc.Key}\":\"{roc.Value}\"";
55                 //              }
56                 //              return new JArray(rocks);
57                 //      }
58                 //}
59
60
61                 [DisplayName(4, "Fert.")]
62                 [ProtoMember(6)]
63                 public float Fertility;
64
65                 //[DisplayName(5, "Forest")]
66                 [ProtoMember(7)]
67                 public float ForestDensity; // not given to client
68
69                 [DisplayName(6, "Rain")]
70                 [ProtoMember(8)]
71                 public float Rainfall;
72
73                 //[DisplayName(7, "Shrub")]
74                 [ProtoMember(9)]
75                 public float ShrubDensity; // not given to client
76
77                 [DisplayName(8, "Air blocks")]
78                 [ProtoMember(10)]
79                 public uint AirBlocks;
80
81                 [DisplayName(9, "Non-air")]
82                 [ProtoMember(11)]
83                 public uint NonAirBlocks;
84
85                 [ProtoMember(12)]
86                 public byte ChunkSize;
87
88
89                 [ProtoIgnore]
90                 public ushort[,] HeightMap;//Needs to be 'flattened' for Protocol-Buffer serialization
91
92                 [ProtoMember(13)]
93                 private ushort[] _flattened_HeightMap;                  
94
95                 /// <summary>
96                 /// Column Presense Bitmap
97                 /// </summary>
98                 [ProtoIgnore]
99                 public BitArray ColumnPresense;
100
101                 public ColumnMeta(Vec2i loc, ICoreClientAPI clientAPI, byte chunkSize = 32, int maxChunkHeight = 16)
102                 {
103                         Location = loc;
104                         PrettyLocation = loc.PrettyCoords(clientAPI);
105                         ChunkAge = TimeSpan.Zero;
106                         Temperature = 0f;
107                         YMax = 0;
108                         RockRatio = new Dictionary<int, uint>(10);
109                         Fertility = 0f;
110                         ForestDensity = 0f;
111                         Rainfall = 0f;
112                         ShrubDensity = 0f;
113                         AirBlocks = 0;
114                         NonAirBlocks = 0;
115                         ChunkSize = chunkSize;
116                         HeightMap = new ushort[ChunkSize, ChunkSize];
117                         _flattened_HeightMap = null;
118                         ColumnPresense = new BitArray(maxChunkHeight, false);//TODO: get real chunk height MAX
119                 }
120
121                 internal void UpdateFieldsFrom(ClimateCondition climate, IMapChunk mapChunk, TimeSpan chunkAge)
122                 {
123                         this.ChunkAge = chunkAge;
124                         this.Temperature = climate.Temperature;
125                         this.Fertility = climate.Fertility;
126                         this.ForestDensity = climate.ForestDensity;
127                         this.Rainfall = climate.Rainfall;
128                         this.ShrubDensity = climate.ShrubDensity;
129
130                         this.YMax = mapChunk.YMax;
131                 }
132
133                 internal void ResetMetadata(int mapSizeY )
134                 {
135                 if (this.ColumnPresense == null) { this.ColumnPresense = new BitArray((mapSizeY / this.ChunkSize), false); }            
136
137                 //Start fresh...
138                 HeightMap = new ushort[ChunkSize, ChunkSize]; 
139                 RockRatio = new Dictionary<int, uint>(this.RockRatio.Count);
140                 AirBlocks = 0;
141                 NonAirBlocks = 0;
142                 YMax = 0;
143                 }
144
145                 [ProtoBeforeSerialization]
146                 private void PrepareData()
147                 {
148
149                         if (HeightMap != null)
150                         {
151                                 _flattened_HeightMap = new ushort[ChunkSize * ChunkSize];
152                                 int flatIndex = 0;
153
154                                 for (byte col = 0; col < ChunkSize; col++)
155                                 {
156                                         for (byte row = 0; row < ChunkSize; row++)
157                                         {
158                                                 _flattened_HeightMap[flatIndex] = HeightMap[col, row];
159                                                 flatIndex++;
160                                         }
161                                 }
162
163                         }
164
165                 }
166
167
168                 [ProtoAfterDeserialization]
169                 private void PostProcess()
170                 {
171                         ChunkSize = (ChunkSize == byte.MinValue) ? (byte)32 : ChunkSize;//Not good - if chunk wasn't 32 orignally!
172
173                         if (this.HeightMap == null || this.HeightMap.Length != (ChunkSize * ChunkSize)) {
174                         this.HeightMap = new ushort[ChunkSize, ChunkSize];
175                         }
176
177                         if (_flattened_HeightMap != null)
178                         {
179                                 int col, row;
180                                 var bitMasker = new BitVector32(0);
181                                 var rowSection = BitVector32.CreateSection((short) (ChunkSize - 1));
182                                 var colSection = BitVector32.CreateSection((short) (ChunkSize - 1), rowSection);
183
184                                 for (uint rowcol = 0; rowcol < (ChunkSize * ChunkSize); rowcol++)
185                                 {
186                                         bitMasker = new BitVector32(data: (int) rowcol);
187                                         row = bitMasker[rowSection];
188                                         col = bitMasker[colSection];
189                                         HeightMap[col, row] = _flattened_HeightMap[rowcol];
190                                 }
191
192                         }
193
194                 }
195
196                 internal void ClearMetadata( )
197                 {
198                 this.HeightMap = null;
199                 this.RockRatio = null;
200                 this._flattened_HeightMap = null;
201                 }
202
203                 internal ColumnMeta Reload(ICoreClientAPI clientAPI)
204                 {
205                         this.PrettyLocation = Location.PrettyCoords(clientAPI);
206                         Debug.Write(PrettyLocation == null ? "*" : ",");
207                         return this;
208                 }
209         }
210
211         public class ColumnsMetadata : KeyedCollection<Vec2i, ColumnMeta>
212         {
213                 private ColumnsMetadata()
214                 {
215                         throw new NotSupportedException();
216                 }
217
218                 public ColumnsMetadata(Vec2i startChunkColumn)
219                 {
220                         North_mostChunk = startChunkColumn.Y;
221                         South_mostChunk = startChunkColumn.Y;
222                         East_mostChunk = startChunkColumn.X;
223                         West_mostChunk = startChunkColumn.X;
224                 }
225
226                 public int North_mostChunk
227                 {
228                         get; private set;
229                 }
230
231                 public int South_mostChunk
232                 {
233                         get; private set;
234                 }
235
236                 public int East_mostChunk
237                 {
238                         get; private set;
239                 }
240
241                 public int West_mostChunk
242                 {
243                         get; private set;
244                 }
245
246                 protected override Vec2i GetKeyForItem(ColumnMeta item)
247                 {
248                         return item.Location;
249                 }
250
251                 internal void Update(ColumnMeta metaData)
252                 {
253                         if (this.Contains(metaData.Location))
254                         {
255                                 this.Remove(metaData.Location);
256                                 this.Add(metaData);
257                         }
258                         else
259                         {
260                                 this.Add(metaData);
261                         }
262
263                 }
264
265                 public new void Add(ColumnMeta newItem)
266                 {
267                         if (North_mostChunk > newItem.Location.Y)
268                         {
269                                 North_mostChunk = newItem.Location.Y;
270                         }
271
272                         if (South_mostChunk < newItem.Location.Y)
273                         {
274                                 South_mostChunk = newItem.Location.Y;
275                         }
276
277                         if (East_mostChunk < newItem.Location.X)
278                         {
279                                 East_mostChunk = newItem.Location.X;
280                         }
281
282                         if (West_mostChunk > newItem.Location.X)
283                         {
284                                 West_mostChunk = newItem.Location.X;
285                         }
286
287                         base.Add(newItem);
288                 }
289
290                 public void ClearMetadata( )
291                 {
292                 for (int i = 0, maxItemsCount = this.Items.Count; i < maxItemsCount; i++) {
293                 ColumnMeta entry = this.Items[i];
294                 entry.ClearMetadata( );
295                 }
296                 }
297
298         }
299 }