OSDN Git Service

Split Renderers (W.I.P.)
authormelchior <melchior@users.osdn.me>
Thu, 23 Jan 2020 22:06:29 +0000 (17:06 -0500)
committermelchior <melchior@users.osdn.me>
Thu, 23 Jan 2020 22:06:29 +0000 (17:06 -0500)
Automap/Automap.csproj
Automap/Data/ColumnMeta.cs
Automap/Renderers/AlternateRenderer.cs [new file with mode: 0644]
Automap/Renderers/IChunkRenderer.cs [new file with mode: 0644]
Automap/Renderers/StandardRenerer.cs [new file with mode: 0644]
Automap/Subsystems/AutomapSystem.cs
Automap/modinfo.json

index cc558cb..08f5536 100644 (file)
@@ -81,6 +81,9 @@
     <Compile Include="Data\PngMetadataChunk.cs" />
     <Compile Include="Subsystems\AutomapSystem.cs" />
     <Compile Include="Subsystems\AutomapGUIDialog.cs" />
+    <Compile Include="Renderers\IChunkRenderer.cs" />
+    <Compile Include="Renderers\StandardRenerer.cs" />
+    <Compile Include="Renderers\AlternateRenderer.cs" />
   </ItemGroup>
   <ItemGroup>
     <Folder Include="VS_libs\" />
@@ -91,6 +94,7 @@
     <Folder Include="Designators\" />
     <Folder Include="Libs\" />
     <Folder Include="Subsystems\" />
+    <Folder Include="Renderers\" />
   </ItemGroup>
   <ItemGroup>
     <None Include="modinfo.json">
index b6a7f58..cdec6b2 100644 (file)
@@ -4,9 +4,11 @@ using System.Collections.ObjectModel;
 using System.Linq;
 
 using Vintagestory.API.MathTools;
+using Vintagestory.API.Common;
 
 using ProtoBuf;
 
+
 namespace Automap
 {
        [ProtoContract]
@@ -39,7 +41,16 @@ namespace Automap
                [ProtoMember(9)]
                public float ShrubDensity;
 
-               public ColumnMeta(Vec2i loc)
+               [ProtoMember(10)]
+               public ushort AirBlocks;
+
+               [ProtoMember(11)]
+               public ushort NonAirBlocks;
+
+               [ProtoMember(12)]
+               public ushort[ , ] HeightMap;
+
+               public ColumnMeta(Vec2i loc, int chunkSize = 32)
                {
                Location = loc;
                ChunkAge = TimeSpan.Zero;
@@ -50,6 +61,22 @@ namespace Automap
                ForestDensity = 0f;
                Rainfall = 0f;
                ShrubDensity = 0f;
+               AirBlocks = 0;
+               NonAirBlocks = 0;
+               HeightMap = new ushort[chunkSize, chunkSize];
+               }
+
+               internal void UpdateFieldsFrom(ClimateCondition climate, IMapChunk mapChunk ,TimeSpan chunkAge)
+               {
+               this.ChunkAge = chunkAge;
+               this.Temperature = climate.Temperature;
+               this.Fertility = climate.Fertility;
+               this.ForestDensity = climate.ForestDensity;
+               this.Rainfall = climate.Rainfall;
+               this.ShrubDensity = climate.ShrubDensity;
+
+               this.YMax = mapChunk.YMax;
+                                       
                }
        }
 
diff --git a/Automap/Renderers/AlternateRenderer.cs b/Automap/Renderers/AlternateRenderer.cs
new file mode 100644 (file)
index 0000000..93fcd16
--- /dev/null
@@ -0,0 +1,127 @@
+using System;
+using System.Linq;
+
+using Hjg.Pngcs;
+
+using Vintagestory.API.Client;
+using Vintagestory.API.Common;
+using Vintagestory.API.MathTools;
+
+namespace Automap
+{
+       public class AlternateRenderer : IChunkRenderer
+       {
+               private readonly int chunkSize;
+
+
+               /// <summary>
+               /// V.G.D:'s Alternative renderer
+               /// </summary>
+               /// <param name="clientAPI">Client API.</param>
+               /// <param name="logger">Logger.</param>
+               public AlternateRenderer(ICoreClientAPI clientAPI, ILogger logger) : base(clientAPI, logger)
+               {
+               chunkSize = ClientAPI.World.BlockAccessor.ChunkSize;
+               }
+
+               public override void GenerateChunkPngShard(Vec2i chunkPos, IMapChunk mc, ColumnMeta metaData, PngWriter pngWriter, out uint pixelCount)
+               { 
+               pixelCount = 0;
+               BlockPos tmpPos = new BlockPos( );
+               Vec2i localpos = new Vec2i( );
+               var chunksColumn = new IWorldChunk[ClientAPI.World.BlockAccessor.MapSizeY / chunkSize];
+
+               int topChunkY = mc.YMax / chunkSize;//Heywaitaminute -- this isn't a highest FEATURE, if Rainmap isn't accurate!
+                                                                                       //Metadata of DateTime chunk was edited, chunk coords.,world-seed? Y-Max feature height
+                                                                                       //Grab a chunk COLUMN... Topmost Y down...
+               for (int chunkY = 0; chunkY <= topChunkY; chunkY++) {
+               chunksColumn[chunkY] = ClientAPI.World.BlockAccessor.GetChunk(chunkPos.X, chunkY, chunkPos.Y);
+               //What to do if chunk is a void? invalid?
+               }
+
+               //pre-create PNG line slices...
+               ImageLine[ ] lines = Enumerable.Repeat(new object( ), chunkSize).Select(l => new ImageLine(pngWriter.ImgInfo)).ToArray( );
+               ushort[ ] allMapYs = mc.RainHeightMap;
+               for (int posIndex = 0; posIndex < (chunkSize * chunkSize); posIndex++) {
+               int currY = allMapYs[posIndex];
+               int localChunkY = currY / chunkSize;
+               if (localChunkY >= (chunksColumn.Length)) continue; //Out of range!
+               if (chunksColumn[localChunkY] == null) continue;
+
+               MapUtil.PosInt2d(posIndex, chunkSize, localpos);
+               int localX = localpos.X;
+               int localZ = localpos.Y;
+
+               chunksColumn[localChunkY].Unpack( );
+               int blockId = chunksColumn[localChunkY].Blocks[MapUtil.Index3d(localX, currY % chunkSize, localZ, chunkSize, chunkSize)];
+
+               Block block = ClientAPI.World.Blocks[blockId];
+
+               tmpPos.Set(chunkSize * chunkPos.X + localX, currY, chunkSize * chunkPos.Y + localZ);
+
+               int red;
+               int green;
+               int blue;
+
+               //============ POI Population =================
+               if (BlockID_Designators.ContainsKey(blockId)) {
+               var desig = BlockID_Designators[blockId];
+               red = desig.OverwriteColor.R;
+               green = desig.OverwriteColor.G;
+               blue = desig.OverwriteColor.B;
+
+               
+               ImageLineHelper.SetPixel(lines[localZ], localX, red, green, blue);
+               continue;
+               }
+
+               float b = GetSlope(localX, localZ, allMapYs);
+
+               int col = block.GetColor(ClientAPI, tmpPos);
+               int packedFormat = ColorUtil.ColorMultiply3Clamped(col, b);
+
+               red = ColorUtil.ColorB(packedFormat);
+               green = ColorUtil.ColorG(packedFormat);
+               blue = ColorUtil.ColorR(packedFormat);
+               ImageLineHelper.SetPixel(lines[localZ], localX, red, green, blue);
+
+               //chunkImage.SetPixel(localX, localZ, pixelColor);
+               pixelCount++;
+               }
+
+               for (int row = 0; row < pngWriter.ImgInfo.Rows; row++) {
+               pngWriter.WriteRow(lines[row], row);
+               }
+
+               pngWriter.End( );
+               }
+
+               private float GetSlope(int x, int y, ushort[ ] heightMap)
+               {
+               int baseY = heightMap[MapUtil.Index2d(x, y, chunkSize)];
+               float runningY = 0;
+               // check bounds. i hate this.
+               int locIndex;
+               if (x > 0) {
+               locIndex = MapUtil.Index2d(x - 1, y, chunkSize);
+               runningY += (baseY - heightMap[locIndex]);
+               }
+               if (x < chunkSize - 1) {
+               locIndex = MapUtil.Index2d(x + 1, y, chunkSize);
+               runningY += (baseY - heightMap[locIndex]);
+               }
+               if (y > 0) {
+               locIndex = MapUtil.Index2d(x, y - 1, chunkSize);
+               runningY += (baseY - heightMap[locIndex]);
+               }
+               if (y < chunkSize - 1) {
+               locIndex = MapUtil.Index2d(x, y + 1, chunkSize);
+               runningY += (baseY - heightMap[locIndex]);
+               }
+               runningY /= 4; // average now
+               runningY /= 5; // idk
+               return 1 + runningY;
+               }
+       }
+}
+
diff --git a/Automap/Renderers/IChunkRenderer.cs b/Automap/Renderers/IChunkRenderer.cs
new file mode 100644 (file)
index 0000000..0912b42
--- /dev/null
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+
+using Hjg.Pngcs;
+
+using Vintagestory.API.Client;
+using Vintagestory.API.Common;
+using Vintagestory.API.MathTools;
+
+namespace Automap
+{
+       public abstract class IChunkRenderer
+       {
+               public virtual ICoreClientAPI ClientAPI { get; protected set; }
+               public virtual ILogger Logger { get; protected set; }
+               public virtual Dictionary<int, Designator> BlockID_Designators { get; set; }
+
+               protected IChunkRenderer(ICoreClientAPI clientAPI, ILogger logger)
+               {
+               this.ClientAPI = clientAPI;
+               this.Logger = logger;
+               }
+
+               public abstract void GenerateChunkPngShard(Vec2i chunkPos, IMapChunk mapChunk, ColumnMeta metaData, PngWriter pngWriter, out uint pixelCount);
+       }
+}
+
diff --git a/Automap/Renderers/StandardRenerer.cs b/Automap/Renderers/StandardRenerer.cs
new file mode 100644 (file)
index 0000000..e388662
--- /dev/null
@@ -0,0 +1,149 @@
+using System;
+using System.Linq;
+
+using Hjg.Pngcs;
+
+using Vintagestory.API.Client;
+using Vintagestory.API.Common;
+using Vintagestory.API.MathTools;
+
+namespace Automap
+{
+       public class StandardRenderer : IChunkRenderer
+       {
+               private readonly int chunkSize;
+
+
+               /// <summary>
+               /// Renders shards similar to the Default VS version, plus P.O.I. markings.
+               /// </summary>
+               /// <param name="clientAPI">Client API.</param>
+               /// <param name="logger">Logger.</param>
+               public StandardRenderer(ICoreClientAPI clientAPI, ILogger logger) : base (clientAPI, logger)
+               {
+               chunkSize = ClientAPI.World.BlockAccessor.ChunkSize;
+               }
+
+               public override void GenerateChunkPngShard(Vec2i chunkPos, IMapChunk mc, ColumnMeta metaData, PngWriter pngWriter, out uint pixelCount)
+               {
+               pixelCount = 0;
+               BlockPos tmpPos = new BlockPos( );
+               Vec2i localpos = new Vec2i( );
+               
+               var chunksColumn = new IWorldChunk[ClientAPI.World.BlockAccessor.MapSizeY / chunkSize];
+
+               int topChunkY = mc.YMax / chunkSize;//Heywaitaminute -- this isn't a highest FEATURE, if Rainmap isn't accurate!
+                                                                                       //Metadata of DateTime chunk was edited, chunk coords.,world-seed? Y-Max feature height
+                                                                                       //Grab a chunk COLUMN... Topmost Y down...
+               for (int chunkY = 0; chunkY <= topChunkY; chunkY++) {
+               chunksColumn[chunkY] = ClientAPI.World.BlockAccessor.GetChunk(chunkPos.X, chunkY, chunkPos.Y);
+               //What to do if chunk is a void? invalid?
+               }
+
+               // Prefetch map chunks, in pattern
+               IMapChunk[ ] mapChunks = new IMapChunk[ ]
+               {
+                       ClientAPI.World.BlockAccessor.GetMapChunk(chunkPos.X - 1, chunkPos.Y - 1),
+                       ClientAPI.World.BlockAccessor.GetMapChunk(chunkPos.X - 1, chunkPos.Y),
+                       ClientAPI.World.BlockAccessor.GetMapChunk(chunkPos.X, chunkPos.Y - 1)
+               };
+
+               //pre-create PNG line slices...
+               ImageLine[ ] lines = Enumerable.Repeat(new object( ), chunkSize).Select(l => new ImageLine(pngWriter.ImgInfo)).ToArray( );
+
+               for (int posIndex = 0; posIndex < (chunkSize * chunkSize); posIndex++) {
+               int mapY = mc.RainHeightMap[posIndex];
+               int localChunkY = mapY / chunkSize;
+               if (localChunkY >= (chunksColumn.Length)) continue;//Out of range!
+
+               MapUtil.PosInt2d(posIndex, chunkSize, localpos);
+               int localX = localpos.X;
+               int localZ = localpos.Y;
+
+               float b = 1;
+               int leftTop, rightTop, leftBot;
+
+               IMapChunk leftTopMapChunk = mc;
+               IMapChunk rightTopMapChunk = mc;
+               IMapChunk leftBotMapChunk = mc;
+
+               int topX = localX - 1;
+               int botX = localX;
+               int leftZ = localZ - 1;
+               int rightZ = localZ;
+
+               if (topX < 0 && leftZ < 0) {
+               leftTopMapChunk = mapChunks[0];
+               rightTopMapChunk = mapChunks[1];
+               leftBotMapChunk = mapChunks[2];
+               }
+               else {
+               if (topX < 0) {
+               leftTopMapChunk = mapChunks[1];
+               rightTopMapChunk = mapChunks[1];
+               }
+               if (leftZ < 0) {
+               leftTopMapChunk = mapChunks[2];
+               leftBotMapChunk = mapChunks[2];
+               }
+               }
+
+               topX = GameMath.Mod(topX, chunkSize);
+               leftZ = GameMath.Mod(leftZ, chunkSize);
+
+               leftTop = leftTopMapChunk == null ? 0 : Math.Sign(mapY - leftTopMapChunk.RainHeightMap[leftZ * chunkSize + topX]);
+               rightTop = rightTopMapChunk == null ? 0 : Math.Sign(mapY - rightTopMapChunk.RainHeightMap[rightZ * chunkSize + topX]);
+               leftBot = leftBotMapChunk == null ? 0 : Math.Sign(mapY - leftBotMapChunk.RainHeightMap[leftZ * chunkSize + botX]);
+
+               float slopeness = (leftTop + rightTop + leftBot);
+
+               if (slopeness > 0) b = 1.2f;
+               if (slopeness < 0) b = 0.8f;
+
+               b -= 0.15f; //Slope boost value 
+
+               if (chunksColumn[localChunkY] == null) {
+
+               continue;
+               }
+
+               chunksColumn[localChunkY].Unpack( );
+               int blockId = chunksColumn[localChunkY].Blocks[MapUtil.Index3d(localpos.X, mapY % chunkSize, localpos.Y, chunkSize, chunkSize)];
+
+               Block block = ClientAPI.World.Blocks[blockId];
+
+               tmpPos.Set(chunkSize * chunkPos.X + localpos.X, mapY, chunkSize * chunkPos.Y + localpos.Y);
+
+               int avgCol = block.GetColor(ClientAPI, tmpPos);
+               int rndCol = block.GetRandomColor(ClientAPI, tmpPos, BlockFacing.UP);
+               int col = ColorUtil.ColorOverlay(avgCol, rndCol, 0.125f);
+               var packedFormat = ColorUtil.ColorMultiply3Clamped(col, b);
+
+               int red = ColorUtil.ColorB(packedFormat);
+               int green = ColorUtil.ColorG(packedFormat);
+               int blue = ColorUtil.ColorR(packedFormat);
+
+
+               //============ POI Population =================
+               if (BlockID_Designators.ContainsKey(blockId)) {
+               var desig = BlockID_Designators[blockId];
+               red = desig.OverwriteColor.R;
+               green = desig.OverwriteColor.G;
+               blue = desig.OverwriteColor.B;
+               }
+
+               ImageLineHelper.SetPixel(lines[localZ], localX, red, green, blue);
+
+               //chunkImage.SetPixel(localX, localZ, pixelColor);
+               pixelCount++;
+               }
+
+               for (int row = 0; row < pngWriter.ImgInfo.Rows; row++) {
+               pngWriter.WriteRow(lines[row], row);
+               }
+
+               pngWriter.End( );
+               }
+       }
+}
+
index ece2be3..deafe94 100644 (file)
@@ -26,6 +26,7 @@ namespace Automap
                private Thread cartographer_thread;
                private ICoreClientAPI ClientAPI { get; set; }
                private ILogger Logger { get; set; }
+               private IChunkRenderer ChunkRenderer { get; set; }
 
                private const string _mapPath = @"Maps";
                private const string _chunkPath = @"Chunks";
@@ -44,7 +45,7 @@ namespace Automap
                internal uint updatedChunksTotal;
                internal Vec2i startChunkColumn;
 
-
+               private readonly int chunkSize;
                private string path;
                private IAsset stylesFile;
 
@@ -53,7 +54,11 @@ namespace Automap
                {
                this.ClientAPI = clientAPI;
                this.Logger = logger;
+               chunkSize = ClientAPI.World.BlockAccessor.ChunkSize;
                ClientAPI.Event.LevelFinalize += EngageAutomap;
+
+               //TODO:Choose which one from GUI 
+               this.ChunkRenderer = new StandardRenderer(clientAPI, logger);
                }
 
 
@@ -67,7 +72,7 @@ namespace Automap
                Logger.VerboseDebug("CSS loaded: {0} size: {1}",stylesFile.IsLoaded() ,stylesFile.ToText( ).Length);
 
                Prefill_POI_Designators( );
-               startChunkColumn = new Vec2i((ClientAPI.World.Player.Entity.LocalPos.AsBlockPos.X / ClientAPI.World.BlockAccessor.ChunkSize), (ClientAPI.World.Player.Entity.LocalPos.AsBlockPos.Z / ClientAPI.World.BlockAccessor.ChunkSize));
+               startChunkColumn = new Vec2i((ClientAPI.World.Player.Entity.LocalPos.AsBlockPos.X / chunkSize), (ClientAPI.World.Player.Entity.LocalPos.AsBlockPos.Z / chunkSize));
                chunkTopMetadata = new ColumnsMetadata(startChunkColumn);
 
                Logger.Notification("AUTOMAP Start {0}", startChunkColumn);
@@ -134,11 +139,13 @@ namespace Automap
                continue;
                }
                
-               ColumnMeta chunkMeta = UpdateColumnMetadata(mostActiveCol,mapChunk);
+               ColumnMeta chunkMeta = CreateColumnMetadata(mostActiveCol,mapChunk);
                PngWriter pngWriter = SetupPngImage(mostActiveCol.Key, chunkMeta);
+               ProcessChunkBlocks(mostActiveCol.Key, mapChunk, chunkMeta);
 
                uint updatedPixels = 0;
-               GenerateChunkImage(mostActiveCol.Key, mapChunk, pngWriter , out updatedPixels);
+
+               ChunkRenderer.GenerateChunkPngShard(mostActiveCol.Key, mapChunk, chunkMeta, pngWriter , out updatedPixels);
                
                if (updatedPixels > 0) {                
                
@@ -158,7 +165,7 @@ namespace Automap
                }
 
                if (updatedChunks > 0) {
-               //TODO: ONLY update if chunk bounds have changed!
+               //What about chunk updates themselves; a update bitmap isn't kept...
                updatedChunksTotal += updatedChunks;
                GenerateMapHTML( );
                updatedChunks = 0;
@@ -183,9 +190,6 @@ namespace Automap
                }
                }
 
-
-
-
                private void Prefill_POI_Designators( )
                {
                this.POIs = new PointsOfInterest( );
@@ -193,14 +197,14 @@ namespace Automap
 
                //Add special marker types for BlockID's of "Interest", overwrite colour, and method
 
-               var theDesignators = new List<Designator>{
+               var standardDesignators = new List<Designator>{
                                DefaultDesignators.Roads,
                 DefaultDesignators.GroundSigns,
                 DefaultDesignators.WallSigns,
                 DefaultDesignators.PostSigns,
                                };
 
-               Install_POI_Designators(theDesignators);
+               Install_POI_Designators(standardDesignators);
                }
 
                private void Install_POI_Designators(ICollection<Designator> designators)
@@ -213,10 +217,10 @@ namespace Automap
                        BlockID_Designators.Add(entry.Key, designator);
                        }
                }
-
+               this.ChunkRenderer.BlockID_Designators = BlockID_Designators;
                }
 
-
+               //TODO: Convert to RAZOR model
                private void GenerateMapHTML( )
                {
                string mapFilename = Path.Combine(path, "Automap.html");
@@ -409,32 +413,17 @@ namespace Automap
 
 
 
-               private ColumnMeta UpdateColumnMetadata(KeyValuePair<Vec2i, uint> mostActiveCol, IMapChunk mapChunk)
+               private ColumnMeta CreateColumnMetadata(KeyValuePair<Vec2i, uint> mostActiveCol, IMapChunk mapChunk)
                {
-               ColumnMeta data = new ColumnMeta(mostActiveCol.Key.Copy());
-               BlockPos equivBP = new BlockPos(mostActiveCol.Key.X * ClientAPI.World.BlockAccessor.ChunkSize,
+               ColumnMeta data = new ColumnMeta(mostActiveCol.Key.Copy(), chunkSize);
+               BlockPos equivBP = new BlockPos(mostActiveCol.Key.X * chunkSize,
                                                                                mapChunk.YMax,
-                                                                               mostActiveCol.Key.Y * ClientAPI.World.BlockAccessor.ChunkSize);
+                                                                               mostActiveCol.Key.Y * chunkSize);
 
                var climate = ClientAPI.World.BlockAccessor.GetClimateAt(equivBP);
-               data.ChunkAge = TimeSpan.FromHours(ClientAPI.World.Calendar.TotalHours);
-               data.Temperature = climate.Temperature;
-               data.Fertility = climate.Fertility;
-               data.ForestDensity = climate.ForestDensity;
-               data.Rainfall = climate.Rainfall;
-               data.ShrubDensity = climate.ShrubDensity;
-
-               data.YMax = mapChunk.YMax;
-
+               data.UpdateFieldsFrom(climate, mapChunk,TimeSpan.FromHours(ClientAPI.World.Calendar.TotalHours));
+                                       
                
-               /* Only present on server....
-               if (mapChunk.TopRockIdMap != null) {
-               foreach (var topRockId in mapChunk.TopRockIdMap) {
-
-               if (data.RockRatio.ContainsKey(topRockId)) { data.RockRatio[topRockId]++; }
-               else { data.RockRatio.Add(topRockId, 1); }
-               }
-               }*/
 
 
                return data;
@@ -494,7 +483,7 @@ namespace Automap
 
                private PngWriter SetupPngImage(Vec2i coord, ColumnMeta metadata)
                {
-               ImageInfo imageInf = new ImageInfo(ClientAPI.World.BlockAccessor.ChunkSize, ClientAPI.World.BlockAccessor.ChunkSize, 8, false);
+               ImageInfo imageInf = new ImageInfo(chunkSize, chunkSize, 8, false);
                
                string filename = $"{coord.X}_{coord.Y}.png";
                filename = Path.Combine(path, filename);
@@ -512,137 +501,23 @@ namespace Automap
                return pngWriter;
                }
 
-               #endregion
-
-
-               #region COPYPASTA
-               //TODO: rewrite - with vertical ray caster, down to bottom-most chunk (for object detection...)
-               //A partly re-written; ChunkMapLayer :: public int[] GenerateChunkImage(Vec2i chunkPos, IMapChunk mc)
-               private void GenerateChunkImage(Vec2i chunkPos, IMapChunk mc, PngWriter pngWriter, out uint pixelCount)
-               {
-               pixelCount = 0;
-               BlockPos tmpPos = new BlockPos( );
-               Vec2i localpos = new Vec2i( );
-               int chunkSize = ClientAPI.World.BlockAccessor.ChunkSize;
-               var chunksColumn = new IWorldChunk[ClientAPI.World.BlockAccessor.MapSizeY / chunkSize];
-
-               int topChunkY = mc.YMax / chunkSize;//Heywaitaminute -- this isn't a highest FEATURE, if Rainmap isn't accurate!
-                                                                                       //Metadata of DateTime chunk was edited, chunk coords.,world-seed? Y-Max feature height
-                                                                                       //Grab a chunk COLUMN... Topmost Y down...
-               for (int chunkY = 0; chunkY <= topChunkY; chunkY++) {
-               chunksColumn[chunkY] = ClientAPI.World.BlockAccessor.GetChunk(chunkPos.X, chunkY, chunkPos.Y);
-               //What to do if chunk is a void? invalid?
-               }
-
-               // Prefetch map chunks, in pattern
-               IMapChunk[ ] mapChunks = new IMapChunk[ ]
+               /// <summary>
+               /// Does the heavy lifting of Scanning the whole (surface) chunk - creates Heightmap and Processes POIs, and stats...
+               /// </summary>
+               /// <param name="key">Chunk Coordinate</param>
+               /// <param name="mapChunk">Map chunk.</param>
+               /// <param name="chunkMeta">Chunk metadata</param>
+               private void ProcessChunkBlocks(Vec2i key, IMapChunk mapChunk, ColumnMeta chunkMeta)
                {
-                       ClientAPI.World.BlockAccessor.GetMapChunk(chunkPos.X - 1, chunkPos.Y - 1),
-                       ClientAPI.World.BlockAccessor.GetMapChunk(chunkPos.X - 1, chunkPos.Y),
-                       ClientAPI.World.BlockAccessor.GetMapChunk(chunkPos.X, chunkPos.Y - 1)
-               };
-
-               //pre-create PNG line slices...
-               ImageLine[ ] lines = Enumerable.Repeat(new object( ), chunkSize).Select(l => new ImageLine(pngWriter.ImgInfo)).ToArray( );
-
-               for (int posIndex = 0; posIndex < (chunkSize * chunkSize); posIndex++) {
-               int mapY = mc.RainHeightMap[posIndex];
-               int localChunkY = mapY / chunkSize;
-               if (localChunkY >= (chunksColumn.Length)) continue;//Out of range!
-
-               MapUtil.PosInt2d(posIndex, chunkSize, localpos);
-               int localX = localpos.X;
-               int localZ = localpos.Y;
-
-               float b = 1;
-               int leftTop, rightTop, leftBot;
-
-               IMapChunk leftTopMapChunk = mc;
-               IMapChunk rightTopMapChunk = mc;
-               IMapChunk leftBotMapChunk = mc;
-
-               int topX = localX - 1;
-               int botX = localX;
-               int leftZ = localZ - 1;
-               int rightZ = localZ;
-
-               if (topX < 0 && leftZ < 0) {
-               leftTopMapChunk = mapChunks[0];
-               rightTopMapChunk = mapChunks[1];
-               leftBotMapChunk = mapChunks[2];
-               }
-               else {
-               if (topX < 0) {
-               leftTopMapChunk = mapChunks[1];
-               rightTopMapChunk = mapChunks[1];
-               }
-               if (leftZ < 0) {
-               leftTopMapChunk = mapChunks[2];
-               leftBotMapChunk = mapChunks[2];
-               }
-               }
-
-               topX = GameMath.Mod(topX, chunkSize);
-               leftZ = GameMath.Mod(leftZ, chunkSize);
-
-               leftTop = leftTopMapChunk == null ? 0 : Math.Sign(mapY - leftTopMapChunk.RainHeightMap[leftZ * chunkSize + topX]);
-               rightTop = rightTopMapChunk == null ? 0 : Math.Sign(mapY - rightTopMapChunk.RainHeightMap[rightZ * chunkSize + topX]);
-               leftBot = leftBotMapChunk == null ? 0 : Math.Sign(mapY - leftBotMapChunk.RainHeightMap[leftZ * chunkSize + botX]);
 
-               float slopeness = (leftTop + rightTop + leftBot);
-
-               if (slopeness > 0) b = 1.2f;
-               if (slopeness < 0) b = 0.8f;
-
-               b -= 0.15f; //Slope boost value 
-
-               if (chunksColumn[localChunkY] == null) {
-
-               continue;
                }
 
-               chunksColumn[localChunkY].Unpack( );
-               int blockId = chunksColumn[localChunkY].Blocks[MapUtil.Index3d(localpos.X, mapY % chunkSize, localpos.Y, chunkSize, chunkSize)];
-
-               Block block = ClientAPI.World.Blocks[blockId];
 
-               tmpPos.Set(chunkSize * chunkPos.X + localpos.X, mapY, chunkSize * chunkPos.Y + localpos.Y);
 
-               int avgCol = block.GetColor(ClientAPI, tmpPos);
-               int rndCol = block.GetRandomColor(ClientAPI, tmpPos, BlockFacing.UP);
-               int col = ColorUtil.ColorOverlay(avgCol, rndCol, 0.125f);
-               var packedFormat = ColorUtil.ColorMultiply3Clamped(col, b);
 
-               int red = ColorUtil.ColorB(packedFormat);
-               int green = ColorUtil.ColorG(packedFormat);
-               int blue = ColorUtil.ColorR(packedFormat);
-
-
-               //============ POI Population =================
-               if (BlockID_Designators.ContainsKey(blockId)) {
-               var desig = BlockID_Designators[blockId];
-               red = desig.OverwriteColor.R;
-               green = desig.OverwriteColor.G;
-               blue = desig.OverwriteColor.B;
-
-               if (desig.SpecialAction != null) {
-               desig.SpecialAction(ClientAPI, this.POIs, tmpPos, block);
-               }
-               }
-
-               ImageLineHelper.SetPixel(lines[localZ], localX, red, green, blue);
-
-               //chunkImage.SetPixel(localX, localZ, pixelColor);
-               pixelCount++;
-               }
+               #endregion
 
-               for (int row = 0; row < pngWriter.ImgInfo.Rows; row++) {
-               pngWriter.WriteRow(lines[row], row);
-               }
 
-               pngWriter.End( );
-               }
-               #endregion
        }
 
 }
\ No newline at end of file
index a388592..3be7d12 100644 (file)
@@ -2,8 +2,9 @@
   "type": "code",
   "name": "Automap",
   "description" : "Automap; Generates a static HTML map dynamically, with Points of Interest!",
-  "authors": ["Melchior"],
-  "version": "0.1.1",
+  "authors": ["Melchior","VeryGoodDog"],
+  "contributors":["VeryGoodDog"],
+  "version": "0.1.2",
     "side":"Client",
   "dependencies": { 
        "game": "1.11.0"