OSDN Git Service

Revisit(er) & ReadOnly chunk use
[automap/automap.git] / Automap / Subsystems / AutomapSystem.cs
index 32cda38..6770ecf 100644 (file)
@@ -44,6 +44,7 @@ namespace Automap
                private static Regex chunkShardRegex = new Regex(@"(?<X>[\d]+)_(?<Z>[\d]+)\.png", RegexOptions.Singleline);
 
                private ConcurrentDictionary<Vec2i, ColumnCounter> columnCounters = new ConcurrentDictionary<Vec2i, ColumnCounter>(3, 150);
+               private Queue<Vec2i> revisitChunkList = new Queue<Vec2i>();
                private ColumnsMetadata chunkTopMetadata;
                internal PointsOfInterest POIs = new PointsOfInterest();
                internal EntitiesOfInterest EOIs = new EntitiesOfInterest();
@@ -175,7 +176,7 @@ namespace Automap
                                }
                        else if (snapshot != null && snapshot.Finished) {
                                #if DEBUG
-                                       Logger.VerboseDebug("COMPLETED Snapshot: {0} Wx{1} Hx{2}, taking {3}", snapshot.fileName, snapshot.Width, snapshot.Height, snapshot.Timer.Elapsed);
+                               Logger.VerboseDebug("COMPLETED Snapshot: {0} Wx{1} Hx{2}, taking {3}", snapshot.fileName, snapshot.Width, snapshot.Height, snapshot.Timer.Elapsed);
                                #endif
                                snapshot = null;
                                CurrentState = CommandType.Run;
@@ -195,10 +196,50 @@ namespace Automap
                                uint updatedChunks = 0;
                                uint updatedPixels = 0;
 
-                               //-- Should dodge enumerator changing underfoot....at a cost.
-                               if (!columnCounters.IsEmpty)
-                               {
-                                       var tempSet = columnCounters.ToArray().Where(cks => cks.Value.WeightedSum > editThreshold) .OrderByDescending(kvp => kvp.Value.WeightedSum);
+
+               //Revisit failed chunks first;
+               while (revisitChunkList.Count > 0) 
+               {
+               var revisitCoord = revisitChunkList.Dequeue( );
+               var rv_mapChunk = ClientAPI.World.BlockAccessor.GetMapChunk(revisitCoord);
+
+               if (rv_mapChunk == null) continue;
+
+               ColumnMeta rv_chunkMeta;
+               if (chunkTopMetadata.Contains(revisitCoord)) 
+               {
+               rv_chunkMeta = chunkTopMetadata[revisitCoord];
+               #if DEBUG
+               Logger.VerboseDebug("(re)Loaded meta-chunk {0}", revisitCoord);
+               #endif
+               }
+               else                                    
+               {
+               rv_chunkMeta = CreateColumnMetadata(revisitCoord, rv_mapChunk);
+               #if DEBUG
+               Logger.VerboseDebug("(re)Created meta-chunk {0}", revisitCoord);
+               #endif
+               }
+
+               ProcessChunkBlocks(revisitCoord, rv_mapChunk, ref rv_chunkMeta);
+
+               ChunkRenderer.SetupPngImage(revisitCoord, path, _chunkPath, ref rv_chunkMeta);
+               ChunkRenderer.GenerateChunkPngShard(revisitCoord, rv_mapChunk, rv_chunkMeta, ref chunkTopMetadata, out updatedPixels);
+
+               if (updatedPixels > 0) 
+                       {
+                       #if DEBUG
+                       Logger.VerboseDebug("(re)Wrote top-chunk shard: ({0}), Pixels#:{2}", revisitCoord, updatedPixels);
+                       #endif
+                       updatedChunks++;
+                       chunkTopMetadata.Update(rv_chunkMeta);
+                       }
+               }//*********** REVISIT'd ******************
+               
+               if (!columnCounters.IsEmpty)
+                               {//-- Should dodge enumerator changing underfoot....at a cost.
+                               var tempSet = columnCounters.ToArray().Where(cks => cks.Value.WeightedSum > editThreshold) .OrderByDescending(kvp => kvp.Value.WeightedSum);
+
                                        UpdateEntityMetadata();
 
                                        foreach (var mostActiveCol in tempSet)
@@ -206,13 +247,13 @@ namespace Automap
                                                var mapChunk = ClientAPI.World.BlockAccessor.GetMapChunk(mostActiveCol.Key);
 
                                                if (mapChunk == null)
-                                               {
-                                                       //TODO: REVISIT THIS CHUNK!
+                                               {                                                       
                                                        #if DEBUG
                                                        Logger.Warning("SKIP CHUNK: ({0}) - Map Chunk NULL!", mostActiveCol.Key);
                                                        #endif
                                                        nullMapCount++;
                                                        columnCounters.TryRemove(mostActiveCol.Key, out ejectedItem);
+                                                       revisitChunkList.Enqueue(mostActiveCol.Key);
                                                        continue;
                                                }
 
@@ -252,6 +293,7 @@ namespace Automap
                                                        #if DEBUG
                                                        Logger.VerboseDebug("Un-painted chunk shard: ({0}) ", mostActiveCol.Key);
                                                        #endif
+                                                       revisitChunkList.Enqueue(mostActiveCol.Key);
                                                }
                                        }
                                }
@@ -276,32 +318,32 @@ namespace Automap
                                columnCounters.Clear( );
 
                                //Then sleep until interupted again, and repeat
-#if DEBUG
+                               #if DEBUG
                                Logger.VerboseDebug("Thread '{0}' about to sleep indefinitely.", Thread.CurrentThread.Name);
-#endif
+                               #endif
                                Thread.Sleep(Timeout.Infinite);
 
                        }
                        catch (ThreadInterruptedException)
                        {
 
-#if DEBUG
+                       #if DEBUG
                                Logger.VerboseDebug("Thread '{0}' interupted [awoken]", Thread.CurrentThread.Name);
-#endif
+                       #endif
                                goto wake;
 
                        }
                        catch (ThreadAbortException)
                        {
-#if DEBUG
+                       #if DEBUG
                                Logger.VerboseDebug("Thread '{0}' aborted.", Thread.CurrentThread.Name);
-#endif
+                       #endif
                        }
                        finally
                        {
-#if DEBUG
+                       #if DEBUG
                                Logger.VerboseDebug("Thread '{0}' executing finally block.", Thread.CurrentThread.Name);
-#endif
+                       #endif
                                PersistPointsData();
                                Write_PlainMetadata( );
                        }
@@ -310,23 +352,23 @@ namespace Automap
                private void Snap()
                {
                        snapshotTake:
-#if DEBUG
+                       #if DEBUG
                        Logger.VerboseDebug("Snapshot started");
-#endif
+                       #endif
                        try
                        {
                                snapshot.Take();
-#if DEBUG
+                               #if DEBUG
                                Logger.VerboseDebug("Snapshot sleeping");
-#endif
+                               #endif
                                CurrentState = CommandType.Run;
                                Thread.Sleep(Timeout.Infinite);
                        }
                        catch (ThreadInterruptedException)
                        {
-#if DEBUG
+                               #if DEBUG
                                Logger.VerboseDebug("Snapshot intertupted");
-#endif
+                               #endif
                                goto snapshotTake;
                        }
                }
@@ -512,6 +554,19 @@ namespace Automap
                        return data;
                }
 
+        private ColumnMeta CreateColumnMetadata(Vec2i coords, IMapChunk mapChunk)
+               {
+               ColumnMeta data = new ColumnMeta(coords, ClientAPI, ( byte )chunkSize, (ClientAPI.World.BlockAccessor.MapSizeY / chunkSize));
+               BlockPos equivBP = new BlockPos(coords.X * chunkSize,
+                                                                               mapChunk.YMax,
+                                                                               coords.Y * chunkSize);
+
+               var climate = ClientAPI.World.BlockAccessor.GetClimateAt(equivBP);
+               data.UpdateFieldsFrom(climate, mapChunk, TimeSpan.FromHours(ClientAPI.World.Calendar.TotalHours));
+
+               return data;
+               }
+
                /// <summary>
                /// Reload chunk bounds from chunk shards
                /// </summary>
@@ -626,7 +681,7 @@ namespace Automap
                                if (worldChunk == null || worldChunk.BlockEntities == null)
                                {
                                        #if DEBUG
-                                       Logger.VerboseDebug("WORLD chunk: null or empty X{0} Y{1} Z{2} !", key.X, targetChunkY, key.Y);
+                                       Logger.VerboseDebug("WORLD chunk: null, B.E. null X{0} Y{1} Z{2} !", key.X, targetChunkY, key.Y);
                                        #endif
                                        nullChunkCount++;
                                        continue;
@@ -637,7 +692,13 @@ namespace Automap
                                #if DEBUG
                                Logger.VerboseDebug("WORLD chunk: Compressed: X{0} Y{1} Z{2}", key.X, targetChunkY, key.Y);
                                #endif
-                               worldChunk.Unpack( );//RESEARCH: Thread Unsafe? 
+                               //VALIDATE: check Read-only applicable
+                               if (worldChunk.Unpack_ReadOnly( ) == false) 
+                                       { 
+                                       Logger.Warning("Failed to unpack chunk: X{0} Y{1} Z{2}", key.X, targetChunkY, key.Y);
+                                       nullChunkCount++;
+                                       continue;
+                                       };
                                }
 
                                /*************** Chunk Entities Scanning *********************/
@@ -649,7 +710,7 @@ namespace Automap
 
                                        foreach (var blockEnt in worldChunk.BlockEntities)
                                        {
-                                               if (blockEnt.Key != null && blockEnt.Value != null && blockEnt.Value.Block != null && BlockID_Designators.ContainsKey(blockEnt.Value.Block.BlockId))
+                                               if (blockEnt.Key != null && blockEnt.Value != null && blockEnt.Value.Block != null && blockEnt.Value.Pos != null  && BlockID_Designators.ContainsKey(blockEnt.Value.Block.BlockId))
                                                {
                                                        var designator = BlockID_Designators[blockEnt.Value.Block.BlockId];
                                                        designator?.SpecialAction(ClientAPI, POIs, blockEnt.Value.Pos.Copy(), blockEnt.Value.Block);
@@ -663,7 +724,7 @@ namespace Automap
                                int X_index, Y_index, Z_index;
 
                                //First Chance fail-safe;
-                               if (worldChunk.Blocks == null || worldChunk.Blocks.Length <= 0) {
+                               if (worldChunk.MaybeBlocks == null || worldChunk.MaybeBlocks.Length <= 0) {
                                #if DEBUG
                                Logger.VerboseDebug("WORLD chunk; Missing block DATA⁈ X{0} Y{1} Z{2} ⁈", key.X, targetChunkY, key.Y);
                                #endif
@@ -682,7 +743,7 @@ namespace Automap
                                                var indicie = MapUtil.Index3d(X_index, Y_index, Z_index, chunkSize, chunkSize);
 
                                                //'Last' Chance fail-safe;
-                                               if (worldChunk.Blocks == null || worldChunk.Blocks.Length <= 0) {
+                                               if (worldChunk.MaybeBlocks == null || worldChunk.MaybeBlocks.Length <= 0) {
                                                #if DEBUG
                                                Logger.VerboseDebug("Processing Block: Missing block DATA⁈ X{0} Y{1} Z{2} ⁈", X_index, Y_index, Z_index);
                                                #endif
@@ -690,7 +751,7 @@ namespace Automap
                                                goto loop_bustout; 
                                                }
 
-                                               int aBlockId = worldChunk.Blocks[indicie];
+                                               int aBlockId = worldChunk.MaybeBlocks[indicie];
 
                                                if (aBlockId == 0 || AiryIdCodes.ContainsKey(aBlockId)) {//Airy blocks,,,
                                                chunkMeta.AirBlocks++;