OSDN Git Service

Pre-RC0: Pass 2; JSON Field metadata dynamic generation.
[automap/automap.git] / Automap / Subsystems / JsonGenerator.cs
1 using System;
2 using System.Collections.Generic;
3 using System.IO;
4 using System.Linq;
5 using System.Reflection;
6 using System.Text;
7
8 using Newtonsoft.Json;
9 using Newtonsoft.Json.Linq;
10
11 using Vintagestory.API.Client;
12 using Vintagestory.API.Common;
13 using Vintagestory.API.Config;
14 using Vintagestory.API.Datastructures;
15 using Vintagestory.API.MathTools;
16 using Vintagestory.Common;
17
18
19 namespace Automap
20 {
21         public class JsonGenerator
22         {
23                 private ICoreClientAPI ClientAPI { get; set; }
24                 private ILogger Logger { get; set; }
25                 private string path { get; set; }
26                 private readonly int chunkSize;
27
28                 internal JArray ColumnMeta_fieldNames,PointsOfInterest_fieldNames,EntitiesOfInterest_fieldNames;
29
30                 public JsonGenerator(ICoreClientAPI _ClientAPI,  ILogger _Logger, string _path )
31                 {
32                 this.ClientAPI = _ClientAPI;
33                 this.Logger = _Logger;
34                 this.path = _path;
35                 this.chunkSize = ClientAPI.World.BlockAccessor.ChunkSize;
36
37                 ColumnMeta_fieldNames = Dynamic_Names<ColumnMeta>( );
38                 PointsOfInterest_fieldNames = Dynamic_Names<PointOfInterest>( );
39                 EntitiesOfInterest_fieldNames = Dynamic_Names<EntityOfInterest>( );
40                 Logger.VerboseDebug("JSON Ready");
41                 }
42
43
44                 /// <summary>
45                 /// Generates the JSON Metadata. (in Map object format )
46                 /// </summary>
47                 public void GenerateJSONMetadata(ColumnsMetadata chunkTopMetadata, Vec2i startChunkColumn, PointsOfInterest POIs, EntitiesOfInterest EOIs, Dictionary<int, string> RockIdCodes )
48                 {
49                 string jsonFilename = Path.Combine(path, "Metadata.js");
50
51                 StreamWriter stream = new StreamWriter(jsonFilename, false, Encoding.UTF8);
52
53                 using (stream) {
54                 JsonTextWriter jsonWriter = new JsonTextWriter(stream);
55
56                 jsonWriter.Formatting = Formatting.None;
57                 jsonWriter.StringEscapeHandling = StringEscapeHandling.EscapeHtml;
58                 jsonWriter.Indentation = 0;
59                 //jsonWriter.AutoCompleteOnClose = true;
60                 jsonWriter.QuoteChar = '\'';
61                 jsonWriter.DateFormatHandling = DateFormatHandling.IsoDateFormat;
62                 jsonWriter.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
63
64                                 /*
65 ViewFrame.chunks
66 vfc ={};
67 // the basic metadata right now
68 vfc.edges = [northmostedge, eastmost, west, south];
69 vfc.chunkMetadataNames=[...]; // the implementation with reflection
70 vfc.chunkMetadata = new Map([['the keys we have', [...metadatas in the same order as the names, stringified(maybe not for rocks thats complicated)],...]);
71 */
72
73                 using (jsonWriter) {
74                 jsonWriter.WriteRaw("ViewFrame.chunks={};\n");
75                 jsonWriter.WriteRaw("ViewFrame.chunks.worldSeedNum=");
76                 jsonWriter.WriteValue(ClientAPI.World.Seed);
77                 jsonWriter.WriteRaw(";\n");
78
79                 jsonWriter.WriteRaw("ViewFrame.chunks.genTime=");
80                 jsonWriter.WriteValue(DateTimeOffset.UtcNow);
81                 jsonWriter.WriteRaw(";\n");
82
83                 jsonWriter.WriteRaw("ViewFrame.chunks.startCoords=");
84                 jsonWriter.WriteStartArray( );
85                 jsonWriter.WriteValue(startChunkColumn.X);
86                 jsonWriter.WriteValue(startChunkColumn.Y);
87                 jsonWriter.WriteEndArray( );
88                 jsonWriter.WriteRaw(";\n");
89
90                 jsonWriter.WriteRaw("ViewFrame.chunks.chunkSize=");
91                 jsonWriter.WriteValue(chunkSize);
92                 jsonWriter.WriteRaw(";\n");
93
94                 jsonWriter.WriteRaw("ViewFrame.chunks.edges=");//whats NEWS
95                 jsonWriter.WriteStartArray( );
96                 jsonWriter.WriteValue(chunkTopMetadata.North_mostChunk);
97                 jsonWriter.WriteValue(chunkTopMetadata.East_mostChunk);
98                 jsonWriter.WriteValue(chunkTopMetadata.South_mostChunk);                
99                 jsonWriter.WriteValue(chunkTopMetadata.West_mostChunk);         
100                 jsonWriter.WriteEndArray( );
101                 jsonWriter.WriteRaw(";\n");
102                                                         
103                 jsonWriter.WriteRaw("ViewFrame.chunks.chunkMetadataNames=");            
104                 ColumnMeta_fieldNames.WriteTo(jsonWriter);
105                 jsonWriter.WriteRaw(";\n");
106
107                 jsonWriter.WriteRaw("ViewFrame.chunks.pointsOfInterestNames=");         
108                 PointsOfInterest_fieldNames.WriteTo(jsonWriter);
109                 jsonWriter.WriteRaw(";\n");
110
111                 jsonWriter.WriteRaw("ViewFrame.chunks.entityOfInterestNames=");         
112                 EntitiesOfInterest_fieldNames.WriteTo(jsonWriter);              
113                 jsonWriter.WriteRaw(";\n");
114
115                 //MAP object format - [key, value]: key is "x_y"
116                 jsonWriter.WriteRaw("ViewFrame.chunks.chunkMetadata=");
117                 jsonWriter.WriteStartConstructor("Map");
118                 jsonWriter.WriteStartArray( );//An array of... 2-component arrays
119
120
121                 foreach (var shard in chunkTopMetadata) {
122                 //TODO:Flatten to array of values...Dynamism!
123                 jsonWriter.WriteStartArray( );//Start tuple
124                 jsonWriter.WriteValue($"{shard.Location.X}_{shard.Location.Y}");//Key of Tuple
125
126                 jsonWriter.WriteStartObject( );
127                 jsonWriter.WritePropertyName("prettyCoord");
128                 jsonWriter.WriteValue(shard.Location.PrettyCoords(ClientAPI));
129
130                 jsonWriter.WritePropertyName("chunkAge");
131                 jsonWriter.WriteValue(shard.ChunkAge);
132
133                 jsonWriter.WritePropertyName("temp");
134                 jsonWriter.WriteValue(shard.Temperature);
135
136                 jsonWriter.WritePropertyName("YMax");
137                 jsonWriter.WriteValue(shard.YMax);
138
139                 jsonWriter.WritePropertyName("fert");
140                 jsonWriter.WriteValue(shard.Fertility);
141
142                 jsonWriter.WritePropertyName("forestDens");
143                 jsonWriter.WriteValue(shard.ForestDensity);
144
145                 jsonWriter.WritePropertyName("rain");
146                 jsonWriter.WriteValue(shard.Rainfall);
147
148                 jsonWriter.WritePropertyName("shrubDens");
149                 jsonWriter.WriteValue(shard.ShrubDensity);
150
151                 jsonWriter.WritePropertyName("airBlocks");
152                 jsonWriter.WriteValue(shard.AirBlocks);
153
154                 jsonWriter.WritePropertyName("nonAirBlocks");
155                 jsonWriter.WriteValue(shard.NonAirBlocks);
156
157                 //TODO: Heightmap ?
158                 //Start rockMap ; FOR a Ratio....on tooltip GUI
159                 jsonWriter.WritePropertyName("rockRatio");
160                 jsonWriter.WriteStartConstructor("Map");
161                 jsonWriter.WriteStartArray( );
162                 foreach (var rockEntry in shard.RockRatio) {
163                 var rockBlock = ClientAPI.World.GetBlock(rockEntry.Key);
164                 jsonWriter.WriteStartArray( );
165                 jsonWriter.WriteValue(rockBlock.Code.Path);
166                 jsonWriter.WriteValue(rockEntry.Value);//Total per chunk-column
167                 jsonWriter.WriteEndArray( );
168                 }
169                 jsonWriter.WriteEndArray( );
170                 jsonWriter.WriteEndConstructor( );//end rock-map
171
172                 jsonWriter.WriteEndObject( );//end Map value: {Object}
173                 jsonWriter.WriteEndArray( );//end Tuple
174                 }
175
176                 jsonWriter.WriteEndArray( );//Enclose tuples of chunkMetadata
177                 jsonWriter.WriteEndConstructor( );//Close constructor of Map (chunkMetadata)
178                 jsonWriter.WriteRaw(";\n");
179
180                 jsonWriter.WriteRaw("ViewFrame.chunks.pointsOfInterest=");
181                 jsonWriter.WriteStartConstructor("Map");
182                 jsonWriter.WriteStartArray( );//An array of... 2-component arrays
183
184                 foreach (var poi in POIs) {
185                 EmitJsonMap(poi, jsonWriter);
186                 }
187
188                 foreach (var poi in EOIs) {
189                 EmitJsonMap(poi, jsonWriter);
190                 }
191
192                 jsonWriter.WriteEndArray( );
193                 jsonWriter.WriteEndConstructor( );
194                 jsonWriter.WriteRaw(";\n");
195
196                 jsonWriter.WriteWhitespace("\n");
197                 jsonWriter.WriteComment("============= BlockID's for Rockmap / Rock-ratios ===============");
198                 jsonWriter.WriteWhitespace("\n");
199
200                 jsonWriter.WriteRaw("ViewFrame.chunks.rock_Lookup =");
201                 jsonWriter.WriteStartConstructor("Map");
202                 jsonWriter.WriteStartArray( );//An array of... 2-component arrays
203
204                 foreach (var entry in RockIdCodes) {
205                 var block = ClientAPI.World.GetBlock(entry.Key);
206                 //      stream.Write("{0},", Lang.GetUnformatted(block.Code.Path));
207                 jsonWriter.WriteStartArray( );
208                 jsonWriter.WriteValue(block.Code.Path);
209
210                 jsonWriter.WriteStartObject( );
211                 jsonWriter.WritePropertyName("assetCode");
212                 jsonWriter.WriteValue(entry.Value);
213
214                 jsonWriter.WritePropertyName("name");
215                 jsonWriter.WriteValue(Lang.GetUnformatted(block.Code.Path));
216                 //}
217
218                 jsonWriter.WriteEndObject( );
219                 jsonWriter.WriteEndArray( );
220                 }
221                 jsonWriter.WriteEndArray( );
222                 jsonWriter.WriteEndConstructor( );
223                 //stream.Write("]);\n");
224                 jsonWriter.WriteRaw(";\n");
225
226                 jsonWriter.Flush( );
227                 }
228                 }
229
230                 }
231
232                 public void EmitJsonMap(PointOfInterest @this, JsonTextWriter jsonWriter)
233                 {
234                 jsonWriter.WriteStartArray( );
235                 jsonWriter.WriteValue($"{@this.Location.X}_{@this.Location.Z}");
236
237                 jsonWriter.WriteStartArray( );
238                 //jsonWriter.WriteValue(@this.Name);
239
240                 jsonWriter.WriteValue(@this.Location.X);
241                 jsonWriter.WriteValue(@this.Location.Z); //Y is HEIGHT from Mantle... Z is Right from edge of world
242
243                 jsonWriter.WriteValue(@this.Location.PrettyCoords(ClientAPI));
244
245                 jsonWriter.WriteValue(@this.Notes.Replace('\\', ' '));//put more escaping in Java-script if needed
246
247                 jsonWriter.WriteValue(@this.Timestamp);
248
249                 jsonWriter.WriteEndArray( );
250                 jsonWriter.WriteEndArray( );
251                 }
252
253                 public void EmitJsonMap(EntityOfInterest @this, JsonTextWriter jsonWriter)
254                 {
255                 jsonWriter.WriteStartArray( );
256                 jsonWriter.WriteValue($"{@this.Location.X}_{@this.Location.Z}");
257
258
259                 jsonWriter.WriteStartArray( );
260                 //jsonWriter.WriteValue(@this.Name);
261
262                 jsonWriter.WriteValue(@this.Location.X);
263                 jsonWriter.WriteValue(@this.Location.Z); //Y is HEIGHT from Mantle... Z is Right from edge of world
264
265                 jsonWriter.WriteValue(@this.Location.PrettyCoords(ClientAPI));
266
267                 jsonWriter.WriteValue(@this.Notes.Replace('\\', ' '));//put more escaping in Java-script if needed
268
269                 jsonWriter.WriteValue(@this.Timestamp);
270
271                 //jsonWriter.WriteValue(@this.EntityId);                
272
273                 jsonWriter.WriteEndArray( );
274                 jsonWriter.WriteEndArray( );
275                 }
276
277
278                 internal JArray Dynamic_Names<TData>( ) where TData : struct
279                 {
280                 Dictionary<byte, string> fieldNames = new Dictionary<byte, string>( );
281
282                 foreach (var fieldInfo in typeof(TData).GetFields(BindingFlags.Instance | BindingFlags.Public)) {               
283                 DisplayNameAttribute displayName = fieldInfo.GetCustomAttribute<DisplayNameAttribute>();
284                         if (displayName != null) 
285                         {
286                                 if (!fieldNames.ContainsKey(displayName.order)) 
287                                 {//No duplicates, no overwrites
288                                 fieldNames.Add(displayName.order, displayName.name);
289                                 }                               
290                         }
291                 }
292
293                 return new JArray(fieldNames.OrderBy(kf => kf.Key).Select(kf => kf.Value).ToArray());   
294                 }
295
296
297         }
298 }
299