OSDN Git Service

Potential fix for Memory leak - Clear (some) Metadata post persist
[automap/automap.git] / Automap / Data / ColumnMeta.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Collections.Specialized;
4
5
6 using Vintagestory.API.MathTools;
7 using Vintagestory.API.Common;
8
9 using ProtoBuf;
10 using System.IO;
11 using System.Collections.ObjectModel;
12 using System.Text;
13 using Vintagestory.API.Client;
14
15 namespace Automap
16 {
17         [ProtoContract]
18         public struct ColumnMeta
19         {
20                 [ProtoMember(1)]
21                 [DisplayName(0, "Coords.")]
22                 public Vec2i Location;
23
24                 [ProtoMember(2)]
25                 [DisplayName(1, "Age")]
26                 public TimeSpan ChunkAge;//OLDEST CHUNK. from chunk last edit
27
28                 [ProtoMember(3)]
29                 [DisplayName(2, "Temp.")]
30                 public float Temperature;// Temperature - surface
31
32                 [ProtoMember(4)]
33                 [DisplayName(3, "Y Max.")]
34                 public ushort YMax;// Y feature height
35
36                 [ProtoMember(5)]
37                 //[DisplayName(10, "Rocks")]
38                 public Dictionary<int, uint> RockRatio;//[Column] Geographic region (rock) Ratio. [BlockID * count]
39
40                 [ProtoMember(6)]
41                 [DisplayName(4, "Fert.")]
42                 public float Fertility;
43
44                 [ProtoMember(7)]
45                 [DisplayName(5, "Forest")]
46                 public float ForestDensity;
47
48                 [ProtoMember(8)]
49                 [DisplayName(6, "Rain")]
50                 public float Rainfall;
51
52                 [ProtoMember(9)]
53                 [DisplayName(7, "Shrub")]
54                 public float ShrubDensity;
55
56                 [ProtoMember(10)]
57                 [DisplayName(8, "Air blocks")]
58                 public uint AirBlocks;
59
60                 [ProtoMember(11)]
61                 [DisplayName(9, "Non-air")]
62                 public uint NonAirBlocks;
63
64                 [ProtoMember(12)]
65                 public byte ChunkSize;
66
67
68                 [ProtoIgnore]
69                 public ushort[,] HeightMap;//Needs to be 'flattened' for Protocol-Buffer serialization
70
71                 [ProtoMember(13)]
72                 private ushort[] _flattened_HeightMap;
73
74
75                 public ColumnMeta(Vec2i loc, byte chunkSize = 32)
76                 {
77                         Location = loc;
78                         ChunkAge = TimeSpan.Zero;
79                         Temperature = 0f;
80                         YMax = 0;
81                         RockRatio = new Dictionary<int, uint>(10);
82                         Fertility = 0f;
83                         ForestDensity = 0f;
84                         Rainfall = 0f;
85                         ShrubDensity = 0f;
86                         AirBlocks = 0;
87                         NonAirBlocks = 0;
88                         ChunkSize = chunkSize;
89                         HeightMap = new ushort[ChunkSize, ChunkSize];
90                         _flattened_HeightMap = null;
91                 }
92
93                 internal void UpdateFieldsFrom(ClimateCondition climate, IMapChunk mapChunk, TimeSpan chunkAge)
94                 {
95                         this.ChunkAge = chunkAge;
96                         this.Temperature = climate.Temperature;
97                         this.Fertility = climate.Fertility;
98                         this.ForestDensity = climate.ForestDensity;
99                         this.Rainfall = climate.Rainfall;
100                         this.ShrubDensity = climate.ShrubDensity;
101
102                         this.YMax = mapChunk.YMax;
103                 }
104
105                 [ProtoBeforeSerialization]
106                 private void PrepareData()
107                 {
108
109                         if (HeightMap != null)
110                         {
111                                 _flattened_HeightMap = new ushort[ChunkSize * ChunkSize];
112                                 int flatIndex = 0;
113
114                                 for (byte col = 0; col < ChunkSize; col++)
115                                 {
116                                         for (byte row = 0; row < ChunkSize; row++)
117                                         {
118                                                 _flattened_HeightMap[flatIndex] = HeightMap[col, row];
119                                                 flatIndex++;
120                                         }
121                                 }
122
123                         }
124
125                 }
126
127
128                 [ProtoAfterDeserialization]
129                 private void PostProcess()
130                 {
131                         ChunkSize = (ChunkSize == byte.MinValue) ? (byte)32 : ChunkSize;//Not good - if chunk wasn't 32 orignally!
132
133                         if (this.HeightMap == null || this.HeightMap.Length != (ChunkSize * ChunkSize)) {
134                         this.HeightMap = new ushort[ChunkSize, ChunkSize];
135                         }
136
137                         if (_flattened_HeightMap != null)
138                         {
139                                 int col, row;
140                                 var bitMasker = new BitVector32(0);
141                                 var rowSection = BitVector32.CreateSection((short) (ChunkSize - 1));
142                                 var colSection = BitVector32.CreateSection((short) (ChunkSize - 1), rowSection);
143
144                                 for (uint rowcol = 0; rowcol < (ChunkSize * ChunkSize); rowcol++)
145                                 {
146                                         bitMasker = new BitVector32(data: (int) rowcol);
147                                         row = bitMasker[rowSection];
148                                         col = bitMasker[colSection];
149                                         HeightMap[col, row] = _flattened_HeightMap[rowcol];
150                                 }
151
152                         }
153
154                 }
155
156
157         }
158
159         public class ColumnsMetadata : KeyedCollection<Vec2i, ColumnMeta>
160         {
161                 private ColumnsMetadata()
162                 {
163                         throw new NotSupportedException();
164                 }
165
166                 public ColumnsMetadata(Vec2i startChunkColumn)
167                 {
168                         North_mostChunk = startChunkColumn.Y;
169                         South_mostChunk = startChunkColumn.Y;
170                         East_mostChunk = startChunkColumn.X;
171                         West_mostChunk = startChunkColumn.X;
172                 }
173
174                 public int North_mostChunk
175                 {
176                         get; private set;
177                 }
178
179                 public int South_mostChunk
180                 {
181                         get; private set;
182                 }
183
184                 public int East_mostChunk
185                 {
186                         get; private set;
187                 }
188
189                 public int West_mostChunk
190                 {
191                         get; private set;
192                 }
193
194                 protected override Vec2i GetKeyForItem(ColumnMeta item)
195                 {
196                         return item.Location;
197                 }
198
199                 internal void Update(ColumnMeta metaData)
200                 {
201                         if (this.Contains(metaData.Location))
202                         {
203                                 this.Remove(metaData.Location);
204                                 this.Add(metaData);
205                         }
206                         else
207                         {
208                                 this.Add(metaData);
209                         }
210
211                 }
212
213                 public new void Add(ColumnMeta newItem)
214                 {
215                         if (North_mostChunk > newItem.Location.Y)
216                         {
217                                 North_mostChunk = newItem.Location.Y;
218                         }
219
220                         if (South_mostChunk < newItem.Location.Y)
221                         {
222                                 South_mostChunk = newItem.Location.Y;
223                         }
224
225                         if (East_mostChunk < newItem.Location.X)
226                         {
227                                 East_mostChunk = newItem.Location.X;
228                         }
229
230                         if (West_mostChunk > newItem.Location.X)
231                         {
232                                 West_mostChunk = newItem.Location.X;
233                         }
234
235                         base.Add(newItem);
236                 }
237
238                 public void ClearMetadata( )
239                 {
240                 for (int i = 0, maxItemsCount = this.Items.Count; i < maxItemsCount; i++) {
241                 ColumnMeta entry = this.Items[i];
242                 entry.HeightMap = null;
243                 entry.RockRatio = null;//Also regenerated when any chunk in a column is changed...
244                 }
245                 }
246
247         }
248 }