Automap (client) [VS plugin mod]
修订版 | b5737970d216cb6abba36243b7437fa092b88fdf (tree) |
---|---|
时间 | 2021-08-27 05:15:41 |
作者 | melchior <melchior@user...> |
Commiter | melchior |
Minimap Export
Shard Processor experimental Mini-map (from DB) EXPORT feature
@@ -0,0 +1,36 @@ | ||
1 | +using System; | |
2 | +using System.IO; | |
3 | + | |
4 | +using Vintagestory.API.Common; | |
5 | + | |
6 | +namespace ShardProcessor | |
7 | +{ | |
8 | + public class LogAdaptor : LoggerBase | |
9 | + { | |
10 | + private StreamWriter fileOutput; | |
11 | + | |
12 | + public LogAdaptor( ) | |
13 | + { | |
14 | + fileOutput = File.CreateText("SP_Log.txt"); | |
15 | + fileOutput.AutoFlush = true; | |
16 | + } | |
17 | + | |
18 | + protected override void LogImpl(EnumLogType logType, string format, params object[ ] args) | |
19 | + { | |
20 | + string formatedText = null; | |
21 | + if (args != null && args.Length > 0) { | |
22 | + formatedText = string.Format(format, args); | |
23 | + } | |
24 | + else { formatedText = format; } | |
25 | + | |
26 | + fileOutput.WriteLine($"«{logType}» {formatedText}"); | |
27 | + } | |
28 | + | |
29 | + ~LogAdaptor( ) | |
30 | + { | |
31 | + fileOutput.Flush( ); | |
32 | + fileOutput.Close( ); | |
33 | + } | |
34 | + } | |
35 | +} | |
36 | + |
@@ -0,0 +1,354 @@ | ||
1 | +using System; | |
2 | +using System.Diagnostics; | |
3 | +using System.IO; | |
4 | +using System.Linq; | |
5 | +using System.Text.RegularExpressions; | |
6 | + | |
7 | +using Automap; | |
8 | + | |
9 | +using Hjg.Pngcs; | |
10 | +using Hjg.Pngcs.Chunks; | |
11 | + | |
12 | +using ProtoBuf; | |
13 | +using Vintagestory.API.Common; | |
14 | +using Vintagestory.API.MathTools; | |
15 | +using Vintagestory.GameContent; | |
16 | + | |
17 | +namespace ShardProcessor | |
18 | +{ | |
19 | + public partial class MainClass | |
20 | + { | |
21 | + internal const int chunkDefaultSize = 32; | |
22 | + | |
23 | + private static void Process_ShardData( ) | |
24 | + { | |
25 | + var shardsDir = new DirectoryInfo(Path.Combine(mapPath, _chunkPath)); | |
26 | + | |
27 | + var shardFiles = shardsDir.GetFiles(chunkFile_filter); | |
28 | + | |
29 | + if (shardFiles.Length > 0) { | |
30 | + #if DEBUG | |
31 | + //Logger.VerboseDebug("Metadata reloading from {0} shards", shardFiles.Length); | |
32 | + #endif | |
33 | + | |
34 | + foreach (var shardFile in shardFiles) { | |
35 | + | |
36 | + if (shardFile.Length < 1024) continue; | |
37 | + var result = chunkShardRegex.Match(shardFile.Name); | |
38 | + if (!result.Success) continue; | |
39 | + | |
40 | + int X_chunk_pos = int.Parse(result.Groups["X"].Value); | |
41 | + int Z_chunk_pos = int.Parse(result.Groups["Z"].Value); | |
42 | + | |
43 | + try { | |
44 | + using (var fileStream = shardFile.OpenRead( )) { | |
45 | + | |
46 | + PngReader pngRead = new PngReader(fileStream); | |
47 | + pngRead.ReadSkippingAllRows( ); | |
48 | + pngRead.End( ); | |
49 | + //Parse PNG chunks for METADATA in shard | |
50 | + PngMetadataChunk metadataFromPng = pngRead.GetChunksList( ).GetById1(PngMetadataChunk.ID) as PngMetadataChunk; | |
51 | + ColumnMeta columnData = metadataFromPng.ChunkMetadata; | |
52 | + //columnData.HeightMap //Should be sane Heightmap... | |
53 | + | |
54 | + | |
55 | + | |
56 | + } | |
57 | + | |
58 | + } catch (PngjException someEx) { | |
59 | + //Logger.Error("PNG Corruption file '{0}' - Reason: {1}", shardFile.Name, someEx); | |
60 | + continue; | |
61 | + } catch (ProtoException protoEx) { | |
62 | + //Logger.Error("ProtoBuf invalid! file:'{0}' - Reason: {1}", shardFile.Name, protoEx); | |
63 | + continue; | |
64 | + } | |
65 | + } | |
66 | + } | |
67 | + | |
68 | + | |
69 | + } | |
70 | + | |
71 | + | |
72 | + private static void Scan_PointsData( ) | |
73 | + { | |
74 | + try { | |
75 | + var eoiFile = new FileInfo(Path.Combine(mapPath, @"eoi_binary")); | |
76 | + var poiFile = new FileInfo(Path.Combine(mapPath, @"poi_binary")); | |
77 | + uint entities = 0, points = 0; | |
78 | + | |
79 | + if (eoiFile.Exists) { | |
80 | + using (var eoiStream = eoiFile.OpenRead( )) { | |
81 | + | |
82 | + EntitiesOfInterest eoiData = Serializer.Deserialize<EntitiesOfInterest>(eoiStream); | |
83 | + | |
84 | + foreach (var entry in eoiData) { | |
85 | + Console.WriteLine("#{0}, [{1}], '{2}', {3}", | |
86 | + entry.EntityId, | |
87 | + entry.Location, | |
88 | + entry.Name, | |
89 | + entry.Timestamp.ToUniversalTime( ) | |
90 | + ); | |
91 | + entities++; | |
92 | + } | |
93 | + Console.WriteLine("Entities Of Interest: {0}", entities); | |
94 | + } | |
95 | + | |
96 | + | |
97 | + if (poiFile.Exists) { | |
98 | + using (var poiStream = poiFile.OpenRead( )) { | |
99 | + | |
100 | + PointsOfInterest poiData = Serializer.Deserialize<PointsOfInterest>(poiStream); | |
101 | + foreach (var entry in poiData) { | |
102 | + Console.WriteLine("[{0}], {1}, {2}, {3}", | |
103 | + entry.Location, | |
104 | + entry.Name, | |
105 | + entry.Destination, | |
106 | + entry.Timestamp.ToUniversalTime( ) | |
107 | + ); | |
108 | + points++; | |
109 | + } | |
110 | + } | |
111 | + Console.WriteLine("Points Of Interest: {0}", points); | |
112 | + } | |
113 | + | |
114 | + } | |
115 | + } catch (Exception uhOh) { | |
116 | + Console.WriteLine(uhOh); | |
117 | + } | |
118 | + | |
119 | + } | |
120 | + | |
121 | + private static void Scan_ShardData( ) | |
122 | + { | |
123 | + var shardsDir = new DirectoryInfo(Path.Combine(mapPath, _chunkPath)); | |
124 | + ulong count = 0, errors = 0, flat = 0; | |
125 | + var shardFiles = shardsDir.GetFiles(chunkFile_filter); | |
126 | + | |
127 | + if (shardFiles.Length > 0) { | |
128 | + #if DEBUG | |
129 | + //Logger.VerboseDebug("Metadata reloading from {0} shards", shardFiles.Length); | |
130 | + #endif | |
131 | + | |
132 | + foreach (var shardFile in shardFiles) { | |
133 | + | |
134 | + if (shardFile.Length < 1024) { | |
135 | + Console.WriteLine("File: '{0}' too small to be valid; skipping!", shardFile.FullName); | |
136 | + errors++; | |
137 | + continue; | |
138 | + } | |
139 | + | |
140 | + var result = chunkShardRegex.Match(shardFile.Name); | |
141 | + if (!result.Success) continue; | |
142 | + | |
143 | + int X_chunk_pos = int.Parse(result.Groups["X"].Value); | |
144 | + int Z_chunk_pos = int.Parse(result.Groups["Z"].Value); | |
145 | + | |
146 | + try { | |
147 | + using (var fileStream = shardFile.OpenRead( )) { | |
148 | + | |
149 | + PngReader pngRead = new PngReader(fileStream); | |
150 | + pngRead.ReadSkippingAllRows( ); | |
151 | + pngRead.End( ); | |
152 | + //Parse PNG chunks for METADATA in shard | |
153 | + PngMetadataChunk metadataFromPng = pngRead.GetChunksList( ).GetById1(PngMetadataChunk.ID) as PngMetadataChunk; | |
154 | + ColumnMeta columnData = metadataFromPng.ChunkMetadata; | |
155 | + | |
156 | + Console.Write("X{0,6:D} Y{1,6:D} Age:{2:N1} ", columnData.Location.X, columnData.Location.Y, columnData.ChunkAge.TotalDays); | |
157 | + Console.Write("YMax:{0:D3} ChkS:{1} Air:{2,7:D} NotAir:{3,7:D} ", | |
158 | + columnData.YMax, columnData.ChunkSize, columnData.AirBlocks, columnData.NonAirBlocks | |
159 | + ); | |
160 | + if (columnData.HeightMap != null) { | |
161 | + Console.Write("(Heights [{0}x{1}] ", columnData.HeightMap.GetLength(0), columnData.HeightMap.GetLength(1)); | |
162 | + ushort lowest = ushort.MaxValue, highest = 0; | |
163 | + ulong sum = 0; | |
164 | + foreach (var hmEntry in columnData.HeightMap) { | |
165 | + lowest = Math.Min(lowest, hmEntry); | |
166 | + highest = Math.Max(highest, hmEntry); | |
167 | + sum += hmEntry; | |
168 | + } | |
169 | + Console.Write("Max:{0,3}, Min:{1,3}, ", highest, lowest); | |
170 | + if (sum > 0) Console.Write("Avg:{0:F1})", ( float )sum / (columnData.ChunkSize * columnData.ChunkSize)); | |
171 | + Console.WriteLine( ); | |
172 | + /*------ROCK RATIOs mini-table----------*/ | |
173 | + if (columnData.RockRatio != null && columnData.RockRatio.Count > 0) { | |
174 | + Console.Write("Ratios({0,2:D})[", columnData.RockRatio.Count); | |
175 | + foreach (var rock in columnData.RockRatio) { | |
176 | + Console.Write("ID:{0,5:D} x{1,4:D}, ", rock.Key, rock.Value); | |
177 | + } | |
178 | + Console.Write(" ]\n"); | |
179 | + } | |
180 | + | |
181 | + if (sum == 0 || columnData.YMax == 0) flat++; | |
182 | + } | |
183 | + else { | |
184 | + flat++; | |
185 | + } | |
186 | + | |
187 | + | |
188 | + } | |
189 | + | |
190 | + } catch (PngjException someEx) { | |
191 | + Console.WriteLine("PNG Corruption file '{0}' - Reason: {1}", shardFile.Name, someEx); | |
192 | + errors++; | |
193 | + continue; | |
194 | + } catch (ProtoException protoEx) { | |
195 | + Console.WriteLine("ProtoBuf invalid! file:'{0}' - Reason: {1}", shardFile.Name, protoEx); | |
196 | + errors++; | |
197 | + continue; | |
198 | + } | |
199 | + count++; | |
200 | + } | |
201 | + } | |
202 | + | |
203 | + Console.WriteLine("Scanned {0} files, {1} errors, {2} FLAT entries", count, errors, flat); | |
204 | + } | |
205 | + | |
206 | + private static void Scan_OneShard( ) | |
207 | + { | |
208 | + //--oneshard ~/ApplicationData/vintagestory/Maps/World_1316328588/Chunks/9363_9379.png | |
209 | + var oneChunkFile = new FileInfo(mapPath); | |
210 | + if (oneChunkFile.Exists) { | |
211 | + | |
212 | + | |
213 | + try { | |
214 | + using (var fileStream = oneChunkFile.OpenRead( )) { | |
215 | + | |
216 | + PngReader pngRead = new PngReader(fileStream); | |
217 | + pngRead.ReadSkippingAllRows( ); | |
218 | + | |
219 | + //Parse PNG chunks for METADATA in shard | |
220 | + PngMetadataChunk metadataFromPng = pngRead.GetChunksList( ).GetById1(PngMetadataChunk.ID) as PngMetadataChunk; | |
221 | + ColumnMeta columnData = metadataFromPng.ChunkMetadata; | |
222 | + var metadata = pngRead.GetMetadata( ); | |
223 | + var pngWriteTime = metadata.GetTime( ); | |
224 | + var chunkX = metadata.GetTxtForKey(@"Chunk_X"); | |
225 | + var chunkY = metadata.GetTxtForKey(@"Chunk_Y"); | |
226 | + var pixelSize = metadata.GetTxtForKey(@"PxSz"); | |
227 | + var gameDate = metadata.GetTxtForKey(@"GameDY"); | |
228 | + var dateBlob = pngWriteTime.GetYMDHMS( ); | |
229 | + /* | |
230 | + return new int[] { | |
231 | + this.year, | |
232 | + this.mon, | |
233 | + this.day, | |
234 | + this.hour, | |
235 | + this.min, | |
236 | + this.sec | |
237 | + */ | |
238 | + | |
239 | + Console.WriteLine($"PNG-Timestamp: Y{dateBlob[0] - 456960} M{dateBlob[1]} D{dateBlob[2]} H{dateBlob[3]} M {dateBlob[4]} S{dateBlob[5]} Chunk: X {chunkX} Y {chunkY} PixelSize:{pixelSize} Game-Date: {gameDate}"); | |
240 | + | |
241 | + pngRead.End( ); | |
242 | + } | |
243 | + } catch (Exception darn) { | |
244 | + Debug.Write("Oops! File causes: {0}", darn.ToString( )); | |
245 | + } | |
246 | + | |
247 | + } | |
248 | + } | |
249 | + | |
250 | + private static void Emit_ProtoHeader( ) | |
251 | + { | |
252 | + Console.WriteLine("Created Protobuf Header files."); | |
253 | + using (var entitiesProto = File.CreateText("Entities.proto")) { | |
254 | + entitiesProto.Write(Serializer.GetProto<EntitiesOfInterest>( )); | |
255 | + entitiesProto.Flush( ); | |
256 | + } | |
257 | + | |
258 | + | |
259 | + using (var pointsProto = File.CreateText("Points.proto")) { | |
260 | + pointsProto.Write(Serializer.GetProto<PointsOfInterest>( )); | |
261 | + pointsProto.Flush( ); | |
262 | + } | |
263 | + | |
264 | + using (var metadataProto = File.CreateText("ColumnMeta.proto")) { | |
265 | + metadataProto.Write(Serializer.GetProto<ColumnMeta>( )); | |
266 | + metadataProto.Flush( ); | |
267 | + } | |
268 | + } | |
269 | + | |
270 | + private static void Dump_Minimap( ) | |
271 | + { | |
272 | + //Extract MapDB -> Shard compatible PNG? | |
273 | + var logger = new LogAdaptor( ); | |
274 | + WalkableMapDB minimapDatabase = new WalkableMapDB(logger); | |
275 | + string outmsg = string.Empty; | |
276 | + logger.Event("Started Logging @{0}", DateTimeOffset.UtcNow.ToString("u")); | |
277 | + Console.WriteLine("Starting to Dump Minimap data"); | |
278 | + var tilesPath = Path.GetDirectoryName(mapPath); | |
279 | + Directory.CreateDirectory(Path.Combine(tilesPath, _minimapTilesPath)); | |
280 | + | |
281 | + if (minimapDatabase.OpenOrCreate(mapPath, ref outmsg, false, false, false)) { | |
282 | + | |
283 | + foreach (var mapPiece in minimapDatabase.WalkMapTiles( )) { | |
284 | + logger.VerboseDebug("ScanDB Tile - X:{0} Y:{1}, Bitmap Int#{2}", mapPiece.ChunkPos.X, mapPiece.ChunkPos.Y, mapPiece.Pixels.Length); | |
285 | + MinimalShardWriter(mapPiece.ChunkPos, mapPiece.Pixels, tilesPath,logger); | |
286 | + } | |
287 | + | |
288 | + } | |
289 | + else { | |
290 | + logger.Error("Failed to access Minimap Database: '{0}'", outmsg); | |
291 | + } | |
292 | + | |
293 | + Console.WriteLine("DONE Dumping Minimap data!"); | |
294 | + } | |
295 | + | |
296 | + private static void MinimalShardWriter(Vec2i coord, int[] pixelData, string tilesPath, ILogger logger ) | |
297 | + { | |
298 | + ImageInfo imageInf = new ImageInfo(chunkDefaultSize, chunkDefaultSize, 8, false); | |
299 | + | |
300 | + string filename = $"{coord.X}_{coord.Y}.png"; | |
301 | + filename = Path.Combine(tilesPath, _minimapTilesPath, filename); | |
302 | + | |
303 | + var PngWriter = FileHelper.CreatePngWriter(filename, imageInf, true); | |
304 | + PngMetadata meta = PngWriter.GetMetadata( ); | |
305 | + meta.SetTimeYMDHMS( | |
306 | + DateTime.UtcNow.Year, | |
307 | + DateTime.UtcNow.Month, | |
308 | + DateTime.UtcNow.Day, | |
309 | + DateTime.UtcNow.Hour, | |
310 | + DateTime.UtcNow.Minute, | |
311 | + DateTime.UtcNow.Second); | |
312 | + meta.SetText("Chunk_X", coord.X.ToString("D")); | |
313 | + meta.SetText("Chunk_Y", coord.Y.ToString("D")); | |
314 | + meta.SetText("PxSz", "1"); | |
315 | + /* | |
316 | + var transparencyChunk = meta.CreateTRNSChunk( ); | |
317 | + transparencyChunk.SetRGB(0, 0, 0);//Same as Snapshots | |
318 | + */ | |
319 | + var minimalMetadata = new ColumnMeta(coord); | |
320 | + | |
321 | + //Setup specialized meta-data PNG chunks here... | |
322 | + PngMetadataChunk pngChunkMeta = new PngMetadataChunk(PngWriter.ImgInfo) { | |
323 | + ChunkMetadata = minimalMetadata | |
324 | + }; | |
325 | + PngWriter.GetChunksList( ).Queue(pngChunkMeta); | |
326 | + PngWriter.CompLevel = 5;// 9 is the maximum compression but thats too high for the small benefit it gives | |
327 | + PngWriter.CompressionStrategy = Hjg.Pngcs.Zlib.EDeflateCompressStrategy.Huffman; | |
328 | + | |
329 | + //pre-create PNG line slices... | |
330 | + ImageLine[ ] lines = Enumerable.Repeat(new object( ), chunkDefaultSize).Select(l => new ImageLine(PngWriter.ImgInfo)).ToArray( ); | |
331 | + | |
332 | + Vec2i pixelPosn = new Vec2i(); | |
333 | + for (int pixelIndex = 0; pixelIndex < (chunkDefaultSize * chunkDefaultSize); pixelIndex++) { | |
334 | + MapUtil.PosInt2d(pixelIndex, chunkDefaultSize, pixelPosn); | |
335 | + int red, green, blue; | |
336 | + red = ColorUtil.ColorB(pixelData[pixelIndex]); | |
337 | + green = ColorUtil.ColorG(pixelData[pixelIndex]); | |
338 | + blue = ColorUtil.ColorR(pixelData[pixelIndex]); | |
339 | + | |
340 | + ImageLineHelper.SetPixel(lines[pixelPosn.Y], pixelPosn.X, red, green, blue); | |
341 | + | |
342 | + | |
343 | + } | |
344 | + | |
345 | + for (int row = 0; row < PngWriter.ImgInfo.Rows; row++) { | |
346 | + PngWriter.WriteRow(lines[row], row); | |
347 | + } | |
348 | + PngWriter.End( ); | |
349 | + | |
350 | + logger.Debug("Wrote mini map tile: {0}", coord); | |
351 | + } | |
352 | + } | |
353 | +} | |
354 | + |
@@ -9,16 +9,18 @@ using Hjg.Pngcs; | ||
9 | 9 | using Hjg.Pngcs.Chunks; |
10 | 10 | |
11 | 11 | using ProtoBuf; |
12 | +using Vintagestory.GameContent; | |
12 | 13 | |
13 | 14 | namespace ShardProcessor |
14 | 15 | { |
15 | - class MainClass | |
16 | + public partial class MainClass | |
16 | 17 | { |
17 | 18 | //private ILogger Logger { get; set; } |
18 | 19 | const string chunkFile_filter = @"*_*.png"; |
19 | 20 | static Regex chunkShardRegex = new Regex(@"(?<X>[\d]+)_(?<Z>[\d]+)\.png", RegexOptions.Singleline); |
20 | 21 | static string mapPath; |
21 | 22 | internal const string _chunkPath = @"Chunks"; |
23 | + internal const string _minimapTilesPath = @"Tiles"; | |
22 | 24 | |
23 | 25 | /* TODO: |
24 | 26 | -Process existing PNGs: Report/Dump contents of Chunk Metadata, as per current version |
@@ -67,6 +69,10 @@ namespace ShardProcessor | ||
67 | 69 | Emit_ProtoHeader(); |
68 | 70 | break; |
69 | 71 | |
72 | + case "--minidump": | |
73 | + Dump_Minimap( ); | |
74 | + break; | |
75 | + | |
70 | 76 | default: |
71 | 77 | Console.WriteLine("Unrecognized Command: {0}", command); |
72 | 78 | break; |
@@ -76,247 +82,7 @@ namespace ShardProcessor | ||
76 | 82 | |
77 | 83 | } |
78 | 84 | |
79 | - private static void Process_ShardData( ) | |
80 | - { | |
81 | - var shardsDir = new DirectoryInfo( Path.Combine(mapPath , _chunkPath)); | |
82 | - | |
83 | - var shardFiles = shardsDir.GetFiles(chunkFile_filter); | |
84 | - | |
85 | - if (shardFiles.Length > 0) { | |
86 | - #if DEBUG | |
87 | - //Logger.VerboseDebug("Metadata reloading from {0} shards", shardFiles.Length); | |
88 | - #endif | |
89 | - | |
90 | - foreach (var shardFile in shardFiles) { | |
91 | - | |
92 | - if (shardFile.Length < 1024) continue; | |
93 | - var result = chunkShardRegex.Match(shardFile.Name); | |
94 | - if (!result.Success) continue; | |
95 | - | |
96 | - int X_chunk_pos = int.Parse(result.Groups["X"].Value); | |
97 | - int Z_chunk_pos = int.Parse(result.Groups["Z"].Value); | |
98 | - | |
99 | - try { | |
100 | - using (var fileStream = shardFile.OpenRead( )) { | |
101 | - | |
102 | - PngReader pngRead = new PngReader(fileStream); | |
103 | - pngRead.ReadSkippingAllRows( ); | |
104 | - pngRead.End( ); | |
105 | - //Parse PNG chunks for METADATA in shard | |
106 | - PngMetadataChunk metadataFromPng = pngRead.GetChunksList( ).GetById1(PngMetadataChunk.ID) as PngMetadataChunk; | |
107 | - ColumnMeta columnData = metadataFromPng.ChunkMetadata; | |
108 | - //columnData.HeightMap //Should be sane Heightmap... | |
109 | - | |
110 | - | |
111 | - | |
112 | - } | |
113 | - | |
114 | - } catch (PngjException someEx) { | |
115 | - //Logger.Error("PNG Corruption file '{0}' - Reason: {1}", shardFile.Name, someEx); | |
116 | - continue; | |
117 | - } catch (ProtoException protoEx) { | |
118 | - //Logger.Error("ProtoBuf invalid! file:'{0}' - Reason: {1}", shardFile.Name, protoEx); | |
119 | - continue; | |
120 | - } | |
121 | - } | |
122 | - } | |
123 | - | |
124 | - | |
125 | - } | |
126 | - | |
127 | - | |
128 | - private static void Scan_PointsData( ) | |
129 | - { | |
130 | - try { | |
131 | - var eoiFile = new FileInfo(Path.Combine(mapPath, @"eoi_binary")); | |
132 | - var poiFile = new FileInfo(Path.Combine(mapPath, @"poi_binary")); | |
133 | - uint entities = 0, points = 0; | |
134 | - | |
135 | - if (eoiFile.Exists) { | |
136 | - using (var eoiStream = eoiFile.OpenRead( )) { | |
137 | - | |
138 | - EntitiesOfInterest eoiData = Serializer.Deserialize<EntitiesOfInterest>(eoiStream); | |
139 | - | |
140 | - foreach (var entry in eoiData) { | |
141 | - Console.WriteLine("#{0}, [{1}], '{2}', {3}", | |
142 | - entry.EntityId, | |
143 | - entry.Location, | |
144 | - entry.Name, | |
145 | - entry.Timestamp.ToUniversalTime( ) | |
146 | - ); | |
147 | - entities++; | |
148 | - } | |
149 | - Console.WriteLine("Entities Of Interest: {0}", entities); | |
150 | - } | |
151 | - | |
152 | - | |
153 | - if (poiFile.Exists) { | |
154 | - using (var poiStream = poiFile.OpenRead( )) { | |
155 | - | |
156 | - PointsOfInterest poiData = Serializer.Deserialize<PointsOfInterest>(poiStream); | |
157 | - foreach (var entry in poiData) { | |
158 | - Console.WriteLine("[{0}], {1}, {2}, {3}", | |
159 | - entry.Location, | |
160 | - entry.Name, | |
161 | - entry.Destination, | |
162 | - entry.Timestamp.ToUniversalTime( ) | |
163 | - ); | |
164 | - points++; | |
165 | - } | |
166 | - } | |
167 | - Console.WriteLine("Points Of Interest: {0}", points); | |
168 | - } | |
169 | - | |
170 | - } | |
171 | - } catch (Exception uhOh) { | |
172 | - Console.WriteLine(uhOh); | |
173 | - } | |
174 | - | |
175 | - } | |
176 | - | |
177 | - private static void Scan_ShardData( ) | |
178 | - { | |
179 | - var shardsDir = new DirectoryInfo(Path.Combine(mapPath, _chunkPath)); | |
180 | - ulong count = 0,errors = 0, flat = 0; | |
181 | - var shardFiles = shardsDir.GetFiles(chunkFile_filter); | |
182 | - | |
183 | - if (shardFiles.Length > 0) { | |
184 | - #if DEBUG | |
185 | - //Logger.VerboseDebug("Metadata reloading from {0} shards", shardFiles.Length); | |
186 | - #endif | |
187 | 85 | |
188 | - foreach (var shardFile in shardFiles) { | |
189 | 86 | |
190 | - if (shardFile.Length < 1024) { | |
191 | - Console.WriteLine("File: '{0}' too small to be valid; skipping!", shardFile.FullName); | |
192 | - errors++; | |
193 | - continue; | |
194 | - } | |
195 | - | |
196 | - var result = chunkShardRegex.Match(shardFile.Name); | |
197 | - if (!result.Success) continue; | |
198 | - | |
199 | - int X_chunk_pos = int.Parse(result.Groups["X"].Value); | |
200 | - int Z_chunk_pos = int.Parse(result.Groups["Z"].Value); | |
201 | - | |
202 | - try { | |
203 | - using (var fileStream = shardFile.OpenRead( )) { | |
204 | - | |
205 | - PngReader pngRead = new PngReader(fileStream); | |
206 | - pngRead.ReadSkippingAllRows( ); | |
207 | - pngRead.End( ); | |
208 | - //Parse PNG chunks for METADATA in shard | |
209 | - PngMetadataChunk metadataFromPng = pngRead.GetChunksList( ).GetById1(PngMetadataChunk.ID) as PngMetadataChunk; | |
210 | - ColumnMeta columnData = metadataFromPng.ChunkMetadata; | |
211 | - | |
212 | - Console.Write("X{0,6:D} Y{1,6:D} Age:{2:N1} ", columnData.Location.X, columnData.Location.Y, columnData.ChunkAge.TotalDays); | |
213 | - Console.Write("YMax:{0:D3} ChkS:{1} Air:{2,7:D} NotAir:{3,7:D} ", | |
214 | - columnData.YMax,columnData.ChunkSize , columnData.AirBlocks, columnData.NonAirBlocks | |
215 | - ); | |
216 | - if (columnData.HeightMap != null) { | |
217 | - Console.Write("(Heights [{0}x{1}] ", columnData.HeightMap.GetLength(0), columnData.HeightMap.GetLength(1)); | |
218 | - ushort lowest = ushort.MaxValue, highest = 0; | |
219 | - ulong sum = 0; | |
220 | - foreach (var hmEntry in columnData.HeightMap) { | |
221 | - lowest = Math.Min(lowest, hmEntry); | |
222 | - highest = Math.Max(highest, hmEntry); | |
223 | - sum += hmEntry; | |
224 | - } | |
225 | - Console.Write("Max:{0,3}, Min:{1,3}, ", highest, lowest); | |
226 | - if (sum > 0) Console.Write("Avg:{0:F1})", ( float )sum / (columnData.ChunkSize * columnData.ChunkSize)); | |
227 | - Console.WriteLine( ); | |
228 | - /*------ROCK RATIOs mini-table----------*/ | |
229 | - if (columnData.RockRatio != null && columnData.RockRatio.Count > 0) { | |
230 | - Console.Write("Ratios({0,2:D})[",columnData.RockRatio.Count); | |
231 | - foreach (var rock in columnData.RockRatio) { | |
232 | - Console.Write("ID:{0,5:D} x{1,4:D}, ", rock.Key, rock.Value); | |
233 | - } | |
234 | - Console.Write(" ]\n"); | |
235 | - } | |
236 | - | |
237 | - if ( sum == 0 || columnData.YMax == 0) flat++; | |
238 | - } | |
239 | - else { | |
240 | - flat++; | |
241 | - } | |
242 | - | |
243 | - | |
244 | - } | |
245 | - | |
246 | - } catch (PngjException someEx) { | |
247 | - Console.WriteLine("PNG Corruption file '{0}' - Reason: {1}", shardFile.Name, someEx); | |
248 | - errors++; | |
249 | - continue; | |
250 | - } catch (ProtoException protoEx) { | |
251 | - Console.WriteLine("ProtoBuf invalid! file:'{0}' - Reason: {1}", shardFile.Name, protoEx); | |
252 | - errors++; | |
253 | - continue; | |
254 | - } | |
255 | - count++; | |
256 | - } | |
257 | - } | |
258 | - | |
259 | - Console.WriteLine("Scanned {0} files, {1} errors, {2} FLAT entries", count, errors, flat); | |
260 | - } | |
261 | - | |
262 | - private static void Scan_OneShard( ) | |
263 | - { | |
264 | - //--oneshard ~/ApplicationData/vintagestory/Maps/World_1316328588/Chunks/9363_9379.png | |
265 | - var oneChunkFile = new FileInfo(mapPath); | |
266 | - if (oneChunkFile.Exists) { | |
267 | - | |
268 | - | |
269 | - try { | |
270 | - using (var fileStream = oneChunkFile.OpenRead( )) { | |
271 | - | |
272 | - PngReader pngRead = new PngReader(fileStream); | |
273 | - pngRead.ReadSkippingAllRows( ); | |
274 | - | |
275 | - //Parse PNG chunks for METADATA in shard | |
276 | - PngMetadataChunk metadataFromPng = pngRead.GetChunksList( ).GetById1(PngMetadataChunk.ID) as PngMetadataChunk; | |
277 | - ColumnMeta columnData = metadataFromPng.ChunkMetadata; | |
278 | - var metadata = pngRead.GetMetadata( ); | |
279 | - var pngWriteTime = metadata.GetTime( ); | |
280 | - var chunkX = metadata.GetTxtForKey(@"Chunk_X"); | |
281 | - var chunkY = metadata.GetTxtForKey(@"Chunk_Y"); | |
282 | - var pixelSize = metadata.GetTxtForKey(@"PxSz"); | |
283 | - var gameDate = metadata.GetTxtForKey(@"GameDY"); | |
284 | - var dateBlob = pngWriteTime.GetYMDHMS( ); | |
285 | - /* | |
286 | - return new int[] { | |
287 | - this.year, | |
288 | - this.mon, | |
289 | - this.day, | |
290 | - this.hour, | |
291 | - this.min, | |
292 | - this.sec | |
293 | - */ | |
294 | - | |
295 | - Console.WriteLine($"PNG-Timestamp: Y{dateBlob[0] - 456960} M{dateBlob[1]} D{dateBlob[2]} H{dateBlob[3]} M {dateBlob[4]} S{dateBlob[5]} Chunk: X {chunkX} Y {chunkY} PixelSize:{pixelSize} Game-Date: {gameDate}"); | |
296 | - | |
297 | - pngRead.End( ); | |
298 | - } | |
299 | - } catch (Exception darn) { | |
300 | - Debug.Write("Oops! File causes: {0}", darn.ToString( )); | |
301 | - } | |
302 | - | |
303 | - } | |
304 | - } | |
305 | - | |
306 | - private static void Emit_ProtoHeader( ) | |
307 | - { | |
308 | - Console.WriteLine("Created Protobuf Header files."); | |
309 | - using (var entitiesProto = File.CreateText("Entities.protoc")) | |
310 | - { | |
311 | - entitiesProto.Write(Serializer.GetProto<EntitiesOfInterest>( )); | |
312 | - entitiesProto.Flush( ); | |
313 | - } | |
314 | - | |
315 | - | |
316 | - using (var pointsProto = File.CreateText("Points.protoc")) { | |
317 | - pointsProto.Write(Serializer.GetProto<PointsOfInterest>( )); | |
318 | - pointsProto.Flush( ); | |
319 | - } | |
320 | - } | |
321 | 87 | } |
322 | 88 | } |
@@ -53,10 +53,17 @@ | ||
53 | 53 | <Reference Include="VSSurvivalMod"> |
54 | 54 | <HintPath>..\Automap\VS_libs\VSSurvivalMod.dll</HintPath> |
55 | 55 | </Reference> |
56 | + <Reference Include="System.Data" /> | |
57 | + <Reference Include="System.Data.SQLite"> | |
58 | + <HintPath>..\Automap\VS_libs\System.Data.SQLite.dll</HintPath> | |
59 | + </Reference> | |
56 | 60 | </ItemGroup> |
57 | 61 | <ItemGroup> |
58 | 62 | <Compile Include="Program.cs" /> |
59 | 63 | <Compile Include="Properties\AssemblyInfo.cs" /> |
64 | + <Compile Include="LogAdaptor.cs" /> | |
65 | + <Compile Include="WalkableMapDB.cs" /> | |
66 | + <Compile Include="ProcessingMethods.cs" /> | |
60 | 67 | </ItemGroup> |
61 | 68 | <ItemGroup> |
62 | 69 | <ProjectReference Include="..\Automap\Automap.csproj"> |
@@ -0,0 +1,81 @@ | ||
1 | +using System; | |
2 | +using System.Linq; | |
3 | +using System.Collections.Generic; | |
4 | +using System.Data; | |
5 | +using System.Data.Common; | |
6 | +using System.Data.SQLite; | |
7 | + | |
8 | +using ProtoBuf; | |
9 | + | |
10 | + | |
11 | + | |
12 | +using Vintagestory.API.Common; | |
13 | +using Vintagestory.GameContent; | |
14 | +using Vintagestory.API.Util; | |
15 | +using Vintagestory.API.MathTools; | |
16 | + | |
17 | +namespace ShardProcessor | |
18 | +{ | |
19 | + public class WalkableMapDB : MapDB | |
20 | + { | |
21 | + private SQLiteCommand walkMapPieceCmd; | |
22 | + | |
23 | + public WalkableMapDB(ILogger logger) : base(logger) | |
24 | + { | |
25 | + } | |
26 | + | |
27 | + public override void OnOpened( ) | |
28 | + { | |
29 | + base.OnOpened( ); | |
30 | + | |
31 | + walkMapPieceCmd = sqliteConn.CreateCommand( ); | |
32 | + walkMapPieceCmd.CommandText = @"SELECT position, data FROM mappiece"; | |
33 | + walkMapPieceCmd.Prepare( ); | |
34 | + } | |
35 | + | |
36 | + | |
37 | + public IEnumerable<LocalizedMapPiece> WalkMapTiles( ) | |
38 | + { | |
39 | + using (SQLiteDataReader sqlite_datareader = walkMapPieceCmd.ExecuteReader( )) | |
40 | + { | |
41 | + int numForPos = sqlite_datareader.GetOrdinal(@"position"); | |
42 | + int numForData = sqlite_datareader.GetOrdinal(@"data"); | |
43 | + | |
44 | + while (sqlite_datareader.Read( )) | |
45 | + { | |
46 | + var posInteger = sqlite_datareader.GetInt64(numForPos);//[];//Integer KEY | |
47 | + object data = sqlite_datareader[numForData]; | |
48 | + if (data == null) yield return null; | |
49 | + | |
50 | + var rawMapP = SerializerUtil.Deserialize<MapPieceDB>(data as byte[ ]); | |
51 | + | |
52 | + var nextPiece = new LocalizedMapPiece( ) { | |
53 | + ChunkPos = posInteger.Convert(), | |
54 | + Pixels = rawMapP.Pixels, | |
55 | + }; | |
56 | + | |
57 | + yield return nextPiece; | |
58 | + } | |
59 | + } | |
60 | + } | |
61 | + } | |
62 | + | |
63 | + public class LocalizedMapPiece : MapPieceDB | |
64 | + { | |
65 | + public Vec2i ChunkPos; | |
66 | + | |
67 | + } | |
68 | + | |
69 | + public static class MapDB_Assist | |
70 | + { | |
71 | + public static Vec2i Convert(this long input) | |
72 | + { | |
73 | + var vector = new Vec2i( ); | |
74 | + vector.X = ( int )(0x7FFFFFF & input); //Passthru only last 27 bits | |
75 | + vector.Y = ( int )(input >> 27 );//Shift 27 right | |
76 | + return vector; | |
77 | + } | |
78 | + } | |
79 | + | |
80 | +} | |
81 | + |