• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#objective-cqt誰得windowscocoapythonphprubygameguibathyscaphec翻訳omegat計画中(planning stage)frameworktwittertestdomvb.netdirectxbtronarduinopreviewerゲームエンジン

Automap (client) [VS plugin mod]


Commit MetaInfo

Revision9bdf8ce56ace68807c37ef8a0c116140635f68f4 (tree)
Time2020-01-01 06:55:09
Authormelchior <melchior@user...>
Commitermelchior

Log Message

RC.ZERO; Metadata persistence on PNG chunk shards

Change Summary

Incremental Difference

--- a/Automap/Automap.csproj
+++ b/Automap/Automap.csproj
@@ -62,6 +62,13 @@
6262 </Reference>
6363 <Reference Include="System.Drawing" />
6464 <Reference Include="System.Web" />
65+ <Reference Include="protobuf-net">
66+ <HintPath>VS_libs\protobuf-net.dll</HintPath>
67+ <Private>False</Private>
68+ </Reference>
69+ <Reference Include="Pngcs">
70+ <HintPath>Libs\Pngcs.dll</HintPath>
71+ </Reference>
6572 </ItemGroup>
6673 <ItemGroup>
6774 <Compile Include="AutomapMod.cs" />
@@ -72,6 +79,7 @@
7279 <Compile Include="Automap_Internals.cs" />
7380 <Compile Include="Designators\DefaultDesignators.cs" />
7481 <Compile Include="Data\ColumnMeta.cs" />
82+ <Compile Include="Data\PngMetadataChunk.cs" />
7583 </ItemGroup>
7684 <ItemGroup>
7785 <Folder Include="VS_libs\" />
@@ -80,6 +88,7 @@
8088 <Folder Include="assets\automap\" />
8189 <Folder Include="assets\automap\config\" />
8290 <Folder Include="Designators\" />
91+ <Folder Include="Libs\" />
8392 </ItemGroup>
8493 <ItemGroup>
8594 <None Include="modinfo.json">
--- a/Automap/Automap_Internals.cs
+++ b/Automap/Automap_Internals.cs
@@ -2,16 +2,17 @@
22 using System.Collections.Concurrent;
33 using System.Collections.Generic;
44 using System.Collections.ObjectModel;
5-using System.Drawing;
6-using System.Drawing.Imaging;
5+
76 using System.IO;
87 using System.Linq;
98 using System.Text;
109 using System.Text.RegularExpressions;
1110 using System.Threading;
12-
1311 using System.Web.UI;
1412
13+using Hjg.Pngcs;
14+using Hjg.Pngcs.Chunks;
15+
1516 using Vintagestory.API.Common;
1617 using Vintagestory.API.MathTools;
1718
@@ -27,6 +28,9 @@ namespace Automap
2728 private const string _chunkPath = @"Chunks";
2829 private const string _domain = @"automap";
2930
31+ private const string chunkFile_filter = @"*_*.png";
32+ private static Regex chunkShardRegex = new Regex(@"(?<X>[\d]+)_(?<Z>[\d]+).png", RegexOptions.Singleline);
33+
3034 private ConcurrentDictionary<Vec2i, uint> columnCounter = new ConcurrentDictionary<Vec2i, uint>(3, 150 );
3135 private ColumnsMetadata chunkTopMetadata;
3236
@@ -117,19 +121,17 @@ namespace Automap
117121 columnCounter.TryRemove(mostActiveCol.Key, out ejectedItem );
118122 continue;
119123 }
124+
125+ ColumnMeta chunkMeta = UpdateColumnMetadata(mostActiveCol,mapChunk);
126+ PngWriter pngWriter = SetupPngImage(mostActiveCol.Key, chunkMeta);
120127
121- string filename = $"{mostActiveCol.Key.X}_{mostActiveCol.Key.Y}.png";
122- filename = Path.Combine(path, filename);
123-
124- var chunkMeta = UpdateColumnMetadata(mostActiveCol,mapChunk);
125-
126- uint pixels = 0;
127- var chkImg = GenerateChunkImage(mostActiveCol.Key, mapChunk, out pixels);
128-
129- if (pixels > 0) {
130- chkImg.Save(filename, ImageFormat.Png);
128+ uint updatedPixels = 0;
129+ GenerateChunkImage(mostActiveCol.Key, mapChunk, pngWriter , out updatedPixels);
130+
131+ if (updatedPixels > 0) {
132+
131133 #if DEBUG
132- Logger.VerboseDebug("Wrote chunk shard: ({0}) - Edits#:{1}, Pixels#:{2}", mostActiveCol.Key, mostActiveCol.Value, pixels);
134+ Logger.VerboseDebug("Wrote chunk shard: ({0}) - Edits#:{1}, Pixels#:{2}", mostActiveCol.Key, mostActiveCol.Value, updatedPixels);
133135 #endif
134136 updatedChunks++;
135137 chunkTopMetadata.Update(chunkMeta);
@@ -169,7 +171,7 @@ namespace Automap
169171 }
170172 }
171173
172- #endregion
174+ #endregion
173175
174176
175177 private void Prefill_POI_Designators( )
@@ -206,15 +208,15 @@ namespace Automap
206208
207209 #region COPYPASTA
208210 //TODO: rewrite - with vertical ray caster, down to bottom-most chunk (for object detection...)
209- //A slightly re-written; ChunkMapLayer :: public int[] GenerateChunkImage(Vec2i chunkPos, IMapChunk mc)
210- internal Bitmap GenerateChunkImage(Vec2i chunkPos, IMapChunk mc, out uint pixelCount)
211+ //A partly re-written; ChunkMapLayer :: public int[] GenerateChunkImage(Vec2i chunkPos, IMapChunk mc)
212+ internal void GenerateChunkImage(Vec2i chunkPos, IMapChunk mc, PngWriter pngWriter, out uint pixelCount)
211213 {
212214 pixelCount = 0;
213215 BlockPos tmpPos = new BlockPos( );
214216 Vec2i localpos = new Vec2i( );
215217 int chunkSize = ClientAPI.World.BlockAccessor.ChunkSize;
216218 var chunksColumn = new IWorldChunk[ClientAPI.World.BlockAccessor.MapSizeY / chunkSize];
217- Bitmap chunkImage = new Bitmap(chunkSize, chunkSize, PixelFormat.Format24bppRgb);
219+
218220 int topChunkY = mc.YMax / chunkSize;//Heywaitaminute -- this isn't a highest FEATURE, if Rainmap isn't accurate!
219221 //Metadata of DateTime chunk was edited, chunk coords.,world-seed? Y-Max feature height
220222 //Grab a chunk COLUMN... Topmost Y down...
@@ -231,6 +233,8 @@ namespace Automap
231233 ClientAPI.World.BlockAccessor.GetMapChunk(chunkPos.X, chunkPos.Y - 1)
232234 };
233235
236+ //pre-create PNG line slices...
237+ ImageLine[ ] lines = Enumerable.Repeat(new object(), chunkSize).Select(l => new ImageLine(pngWriter.ImgInfo)).ToArray();
234238
235239 for (int posIndex = 0; posIndex < (chunkSize * chunkSize); posIndex++) {
236240 int mapY = mc.RainHeightMap[posIndex];
@@ -296,29 +300,38 @@ namespace Automap
296300 tmpPos.Set(chunkSize * chunkPos.X + localpos.X, mapY, chunkSize * chunkPos.Y + localpos.Y);
297301
298302 int avgCol = block.GetColor(ClientAPI, tmpPos);
299- int rndCol = block.GetRandomColor(ClientAPI, tmpPos, BlockFacing.UP);
300- //This is still, an abnormal color - the tint is too blue
303+ int rndCol = block.GetRandomColor(ClientAPI, tmpPos, BlockFacing.UP);
301304 int col = ColorUtil.ColorOverlay(avgCol, rndCol, 0.125f);
302305 var packedFormat = ColorUtil.ColorMultiply3Clamped(col, b);
303306
304- Color pixelColor = Color.FromArgb(ColorUtil.ColorB(packedFormat), ColorUtil.ColorG(packedFormat), ColorUtil.ColorR(packedFormat));
307+ int red = ColorUtil.ColorB(packedFormat);
308+ int green = ColorUtil.ColorG(packedFormat);
309+ int blue = ColorUtil.ColorR(packedFormat);
310+
305311
306312 //============ POI Population =================
307313 if (BlockID_Designators.ContainsKey(blockId)) {
308314 var desig = BlockID_Designators[blockId];
309- pixelColor = desig.OverwriteColor;
315+ red = desig.OverwriteColor.R;
316+ green = desig.OverwriteColor.G;
317+ blue = desig.OverwriteColor.B;
310318
311319 if (desig.SpecialAction != null) {
312320 desig.SpecialAction(ClientAPI, this.POIs, tmpPos, block);
313321 }
314322 }
323+
324+ ImageLineHelper.SetPixel(lines[localZ], localX, red, green, blue);
315325
316- chunkImage.SetPixel(localX, localZ, pixelColor);
326+ //chunkImage.SetPixel(localX, localZ, pixelColor);
317327 pixelCount++;
318328 }
319329
330+ for (int row = 0; row < pngWriter.ImgInfo.Rows; row++) {
331+ pngWriter.WriteRow(lines[row], row);
332+ }
320333
321- return chunkImage;
334+ pngWriter.End( );
322335 }
323336 #endregion
324337
@@ -533,10 +546,7 @@ namespace Automap
533546 /// </summary>
534547 /// <returns>The metadata.</returns>
535548 private void Reload_Metadata( )
536- {
537- string chunkFile_filter = @"*_*.png";
538- Regex chunkShardRegex = new Regex(@"(?<X>[\d]+)_(?<Z>[\d]+).png", RegexOptions.Singleline);
539-
549+ {
540550 var worldmapDir = new DirectoryInfo(path);
541551
542552 if (worldmapDir.Exists) {
@@ -548,13 +558,26 @@ namespace Automap
548558 Logger.VerboseDebug("{0} Existing world chunk shards", files.Length);
549559 #endif
550560
561+ PngChunk.FactoryRegister(PngMetadataChunk.ID, typeof(PngMetadataChunk));
562+
551563 foreach (var shardFile in files) {
552564 var result = chunkShardRegex.Match(shardFile.Name);
553565 if (result.Success) {
554566 int X_chunk_pos = int.Parse(result.Groups["X"].Value );
555567 int Z_chunk_pos = int.Parse(result.Groups["Z"].Value );
556- //TODO: METADATA from shard
557- chunkTopMetadata.Add(new ColumnMeta(new Vec2i(X_chunk_pos, Z_chunk_pos)));
568+
569+ //Parse PNG chunks for METADATA in shard
570+ using (var fileStream = shardFile.OpenRead( ))
571+ {
572+ PngReader pngRead = new PngReader(fileStream );
573+ pngRead.ReadSkippingAllRows( );
574+ pngRead.End( );
575+
576+ PngMetadataChunk metadataFromPng = pngRead.GetChunksList( ).GetById1(PngMetadataChunk.ID) as PngMetadataChunk;
577+
578+ chunkTopMetadata.Add(metadataFromPng.ChunkMetadata);
579+ }
580+
558581 }
559582 }
560583
@@ -569,6 +592,26 @@ namespace Automap
569592
570593
571594 }
595+
596+ private PngWriter SetupPngImage(Vec2i coord, ColumnMeta metadata)
597+ {
598+ ImageInfo imageInf = new ImageInfo(ClientAPI.World.BlockAccessor.ChunkSize, ClientAPI.World.BlockAccessor.ChunkSize, 8, false);
599+
600+ string filename = $"{coord.X}_{coord.Y}.png";
601+ filename = Path.Combine(path, filename);
602+
603+ PngWriter pngWriter = FileHelper.CreatePngWriter(filename, imageInf, true);
604+ PngMetadata meta = pngWriter.GetMetadata( );
605+ meta.SetTimeNow( );
606+ meta.SetText("Chunk_X", coord.X.ToString("D"));
607+ meta.SetText("Chunk_Y", coord.Y.ToString("D"));
608+ //Setup specialized meta-data PNG chunks here...
609+ PngMetadataChunk pngChunkMeta = new PngMetadataChunk(pngWriter.ImgInfo);
610+ pngChunkMeta.ChunkMetadata = metadata;
611+ pngWriter.GetChunksList( ).Queue(pngChunkMeta);
612+
613+ return pngWriter;
614+ }
572615 }
573616
574617 }
\ No newline at end of file
--- a/Automap/Data/ColumnMeta.cs
+++ b/Automap/Data/ColumnMeta.cs
@@ -5,23 +5,44 @@ using System.Linq;
55
66 using Vintagestory.API.MathTools;
77
8+using ProtoBuf;
9+
810 namespace Automap
911 {
10-
12+ [ProtoContract]
1113 public struct ColumnMeta
1214 {
15+ [ProtoMember(1)]
1316 public Vec2i Location;
17+
18+ [ProtoMember(2)]
19+ public TimeSpan ChunkAge;//In game, calendar?
20+
21+ [ProtoMember(3)]
1422 public float Temperature;// Temperature
23+
24+ [ProtoMember(4)]
1525 public ushort YMax;// Y feature height
26+
27+ [ProtoMember(5)]
1628 public Dictionary<int,uint> RockRatio;//(surface) Geographic region (rock) Ratio. [BlockID * count]
29+
30+ [ProtoMember(6)]
1731 public float Fertility;
32+
33+ [ProtoMember(7)]
1834 public float ForestDensity;
35+
36+ [ProtoMember(8)]
1937 public float Rainfall;
38+
39+ [ProtoMember(9)]
2040 public float ShrubDensity;
2141
2242 public ColumnMeta(Vec2i loc)
2343 {
2444 Location = loc;
45+ ChunkAge = TimeSpan.Zero;
2546 Temperature = 0f;
2647 YMax = 0;
2748 RockRatio = new Dictionary<int, uint>( 10 );
--- /dev/null
+++ b/Automap/Data/PngMetadataChunk.cs
@@ -0,0 +1,55 @@
1+using System;
2+
3+using Vintagestory.API.Util;
4+
5+using Hjg.Pngcs;
6+using Hjg.Pngcs.Chunks;
7+
8+namespace Automap
9+{
10+ /// <summary>
11+ /// Png metadata chunk.
12+ /// </summary>
13+ /// <remarks>There can be only one. (per PNG file)</remarks>
14+ public class PngMetadataChunk : PngChunkSingle
15+ {
16+ // ID must follow the PNG conventions: four ascii letters,
17+ public readonly static string ID = "cHUK";
18+
19+ public ColumnMeta ChunkMetadata { get; set; }
20+
21+
22+ public PngMetadataChunk(ImageInfo info) : base(ID, info)
23+ {
24+
25+ }
26+
27+ public override ChunkOrderingConstraint GetOrderingConstraint( )
28+ {
29+ return ChunkOrderingConstraint.NONE;
30+ }
31+
32+ public override ChunkRaw CreateRawChunk( )
33+ {
34+ var datas = SerializerUtil.Serialize<ColumnMeta>(ChunkMetadata);
35+
36+ ChunkRaw rawChunk = createEmptyChunk(datas.Length, true);
37+ rawChunk.Data = datas;
38+
39+ return rawChunk;
40+ }
41+
42+ public override void ParseFromRaw(ChunkRaw rawChunk)
43+ {
44+ this.ChunkMetadata = SerializerUtil.Deserialize<ColumnMeta>(rawChunk.Data);
45+ }
46+
47+ public override void CloneDataFromRead(PngChunk other)
48+ {
49+ PngMetadataChunk clone = ( PngMetadataChunk )other;
50+ this.ChunkMetadata = clone.ChunkMetadata;
51+ }
52+
53+ }
54+}
55+