X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=Automap%2FSubsystems%2FAutomapSystem.cs;h=4013b9aa0a5a03ecb314489d3d95dd84239cf73a;hb=989738939a2e623b8bf6db337968e3114a9a99ee;hp=8bbb0c12e14b7c9485abafb732cc1ac5a1a91626;hpb=354b2bb20acf06e5a19ab832ef714d6658c2f1a6;p=automap%2Fautomap.git diff --git a/Automap/Subsystems/AutomapSystem.cs b/Automap/Subsystems/AutomapSystem.cs index 8bbb0c1..4013b9a 100644 --- a/Automap/Subsystems/AutomapSystem.cs +++ b/Automap/Subsystems/AutomapSystem.cs @@ -1,17 +1,14 @@ using System; +using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Reflection; using System.Text; using System.Text.RegularExpressions; using System.Threading; using Hjg.Pngcs; -using Hjg.Pngcs.Chunks; - -using Newtonsoft.Json; using ProtoBuf; @@ -31,7 +28,7 @@ namespace Automap private Snapshotter snapshot; private ICoreClientAPI ClientAPI { get; set; } private ILogger Logger { get; set; } - private IChunkRenderer ChunkRenderer { get; set; } + private AChunkRenderer ChunkRenderer { get; set; } private JsonGenerator JsonGenerator { get; set; } internal const string _mapPath = @"Maps"; @@ -51,6 +48,7 @@ namespace Automap internal Dictionary BlockID_Designators { get; private set; } internal Dictionary Entity_Designators { get; private set; } internal Dictionary RockIdCodes { get; private set; } + internal Dictionary AiryIdCodes { get; private set; } internal CommandType CurrentState { get; set; } //Run status, Chunks processed, stats, center of map.... @@ -75,7 +73,7 @@ namespace Automap configuration = config; //TODO:Choose which one from GUI - this.ChunkRenderer = new StandardRenderer(clientAPI, logger); + this.ChunkRenderer = new StandardRenderer(clientAPI, logger, this.configuration.SeasonalColors); //Listen on bus for commands ClientAPI.Event.RegisterEventBusListener(CommandListener, 1.0, AutomapSystem.AutomapCommandEventKey); @@ -107,7 +105,7 @@ namespace Automap outputText.Flush(); Prefill_POI_Designators(); - startChunkColumn = new Vec2i((ClientAPI.World.Player.Entity.LocalPos.AsBlockPos.X / chunkSize), (ClientAPI.World.Player.Entity.LocalPos.AsBlockPos.Z / chunkSize)); + startChunkColumn = new Vec2i((ClientAPI.World.Player.Entity.Pos.AsBlockPos.X / chunkSize), (ClientAPI.World.Player.Entity.Pos.AsBlockPos.Z / chunkSize)); chunkTopMetadata = new ColumnsMetadata(startChunkColumn); Logger.Notification("AUTOMAP Start {0}", startChunkColumn); Reload_Metadata(); @@ -198,6 +196,7 @@ namespace Automap if (mapChunk == null) { + //TODO: REVISIT THIS CHUNK! Logger.Warning("SKIP CHUNK: ({0}) - Map Chunk NULL!", mostActiveCol.Key); nullMapCount++; columnCounter.TryRemove(mostActiveCol.Key, out ejectedItem); @@ -208,27 +207,27 @@ namespace Automap if (chunkTopMetadata.Contains(mostActiveCol.Key)) { chunkMeta = chunkTopMetadata[mostActiveCol.Key]; -#if DEBUG - Logger.VerboseDebug("Loaded chunk {0}", mostActiveCol.Key); -#endif + #if DEBUG + Logger.VerboseDebug("Loaded meta-chunk {0}", mostActiveCol.Key); + #endif } else { chunkMeta = CreateColumnMetadata(mostActiveCol, mapChunk); -#if DEBUG - Logger.VerboseDebug("Created chunk {0}", mostActiveCol.Key); -#endif + #if DEBUG + Logger.VerboseDebug("Created meta-chunk {0}", mostActiveCol.Key); + #endif } ProcessChunkBlocks(mostActiveCol.Key, mapChunk, ref chunkMeta); - PngWriter pngWriter = SetupPngImage(mostActiveCol.Key, ref chunkMeta); - ChunkRenderer.GenerateChunkPngShard(mostActiveCol.Key, mapChunk, chunkMeta, pngWriter, out updatedPixels); + ChunkRenderer.SetupPngImage(mostActiveCol.Key, path, _chunkPath, ref chunkMeta); + ChunkRenderer.GenerateChunkPngShard(mostActiveCol.Key, mapChunk, chunkMeta, out updatedPixels); if (updatedPixels > 0) { -#if DEBUG - Logger.VerboseDebug("Wrote chunk shard: ({0}) - Edits#:{1}, Pixels#:{2}", mostActiveCol.Key, mostActiveCol.Value, updatedPixels); -#endif + #if DEBUG + Logger.VerboseDebug("Wrote top-chunk shard: ({0}) - Edits#:{1}, Pixels#:{2}", mostActiveCol.Key, mostActiveCol.Value, updatedPixels); + #endif updatedChunks++; chunkTopMetadata.Update(chunkMeta); columnCounter.TryRemove(mostActiveCol.Key, out ejectedItem); @@ -236,13 +235,11 @@ namespace Automap else { columnCounter.TryRemove(mostActiveCol.Key, out ejectedItem); -#if DEBUG - Logger.VerboseDebug("Un-painted chunk: ({0}) ", mostActiveCol.Key); -#endif + #if DEBUG + Logger.VerboseDebug("Un-painted chunk shard: ({0}) ", mostActiveCol.Key); + #endif } } - //Cleanup persisted Metadata... - chunkTopMetadata.ClearMetadata(); } UpdateStatus(this.updatedChunksTotal, this.nullChunkCount, updatedChunks); @@ -253,6 +250,9 @@ namespace Automap updatedChunksTotal += updatedChunks; JsonGenerator.GenerateJSONMetadata(chunkTopMetadata, startChunkColumn, POIs, EOIs, RockIdCodes); updatedChunks = 0; + + //Cleanup in-memory Metadata... + chunkTopMetadata.ClearMetadata( ); } //Then sleep until interupted again, and repeat @@ -323,6 +323,7 @@ namespace Automap this.BlockID_Designators = new Dictionary(); this.Entity_Designators = new Dictionary(); this.RockIdCodes = Helpers.ArbitrarytBlockIdHunter(ClientAPI, new AssetLocation(GlobalConstants.DefaultDomain, "rock-"), EnumBlockMaterial.Stone); + this.AiryIdCodes = Helpers.ArbitrarytBlockIdHunter(ClientAPI, new AssetLocation(GlobalConstants.DefaultDomain, "tallgrass-"), EnumBlockMaterial.Plant); //Add special marker types for BlockID's of "Interest", overwrite colour, and method @@ -395,7 +396,7 @@ namespace Automap using (var tsvWriter = new StreamWriter(pointsTsvPath, false, Encoding.UTF8)) { - tsvWriter.WriteLine("Name\tDescription\tLocation\tTime\t"); + tsvWriter.WriteLine("Name\tDescription\tLocation\tTime\tDestination"); foreach (var point in this.POIs) { tsvWriter.Write(point.Name + "\t"); @@ -406,6 +407,7 @@ namespace Automap tsvWriter.Write(notes + "\t"); tsvWriter.Write(point.Location.PrettyCoords(ClientAPI) + "\t"); tsvWriter.Write(point.Timestamp.ToString("u") + "\t"); + tsvWriter.Write((point.Destination != null ? point.Destination.PrettyCoords(ClientAPI) : "---") +"\t"); tsvWriter.WriteLine(); } foreach (var entity in this.EOIs) @@ -418,6 +420,7 @@ namespace Automap tsvWriter.Write(notes + "\t"); tsvWriter.Write(entity.Location.PrettyCoords(ClientAPI) + "\t"); tsvWriter.Write(entity.Timestamp.ToString("u") + "\t"); + tsvWriter.Write("n/a\t"); tsvWriter.WriteLine(); } tsvWriter.WriteLine(); @@ -428,7 +431,7 @@ namespace Automap private ColumnMeta CreateColumnMetadata(KeyValuePair mostActiveCol, IMapChunk mapChunk) { - ColumnMeta data = new ColumnMeta(mostActiveCol.Key.Copy(), ClientAPI, (byte) chunkSize); + ColumnMeta data = new ColumnMeta(mostActiveCol.Key.Copy(), ClientAPI, (byte) chunkSize, (ClientAPI.World.BlockAccessor.MapSizeY / chunkSize)); BlockPos equivBP = new BlockPos(mostActiveCol.Key.X * chunkSize, mapChunk.YMax, mostActiveCol.Key.Y * chunkSize); @@ -494,6 +497,11 @@ namespace Automap Logger.Error("PNG Corruption file '{0}' - Reason: {1}", shardFile.Name, someEx); continue; } + catch (ProtoException protoEx) + { + Logger.Error("ProtoBuf invalid! file:'{0}' - Reason: {1}", shardFile.Name, protoEx); + continue; + } } } @@ -522,29 +530,7 @@ namespace Automap } - private PngWriter SetupPngImage(Vec2i coord, ref ColumnMeta metadata) - { - ImageInfo imageInf = new ImageInfo(chunkSize, chunkSize, 8, false); - - string filename = $"{coord.X}_{coord.Y}.png"; - filename = Path.Combine(path, _chunkPath ,filename); - - PngWriter pngWriter = FileHelper.CreatePngWriter(filename, imageInf, true); - PngMetadata meta = pngWriter.GetMetadata(); - meta.SetTimeNow(); - meta.SetText("Chunk_X", coord.X.ToString("D")); - meta.SetText("Chunk_Y", coord.Y.ToString("D")); - //Setup specialized meta-data PNG chunks here... - PngMetadataChunk pngChunkMeta = new PngMetadataChunk(pngWriter.ImgInfo) - { - ChunkMetadata = metadata - }; - pngWriter.GetChunksList().Queue(pngChunkMeta); - pngWriter.CompLevel = 5;// 9 is the maximum compression but thats too high for the small benefit it gives - pngWriter.CompressionStrategy = Hjg.Pngcs.Zlib.EDeflateCompressStrategy.Huffman; - return pngWriter; - } /// /// Does the heavy lifting of Scanning columns of chunks - scans for BlockEntity, creates Heightmap and stats... @@ -554,87 +540,109 @@ namespace Automap /// Chunk metadata private void ProcessChunkBlocks(Vec2i key, IMapChunk mapChunk, ref ColumnMeta chunkMeta) { + int targetChunkY = mapChunk.YMax / chunkSize;//Surface ish... + byte chunkTally = 0; + + #if DEBUG + Logger.VerboseDebug("Start col @ X{0} Y{1} Z{2} !", key.X, targetChunkY, key.Y); + #endif + + chunkMeta.ResetMetadata(ClientAPI.World.BlockAccessor.MapSizeY); - int targetChunkY = mapChunk.YMax / chunkSize;//Surface ... - for (; targetChunkY > 0; targetChunkY--) + for (; targetChunkY > 0; targetChunkY--) { - WorldChunk chunkData = ClientAPI.World.BlockAccessor.GetChunk(key.X, targetChunkY, key.Y) as WorldChunk; + WorldChunk worldChunk = ClientAPI.World.BlockAccessor.GetChunk(key.X, targetChunkY, key.Y) as WorldChunk; - if (chunkData == null || chunkData.BlockEntities == null) + if (worldChunk == null || worldChunk.BlockEntities == null) { -#if DEBUG - Logger.VerboseDebug("Chunk null or empty X{0} Y{1} Z{2}", key.X, targetChunkY, key.Y); -#endif + #if DEBUG + Logger.VerboseDebug("WORLD chunk: null or empty X{0} Y{1} Z{2} !", key.X, targetChunkY, key.Y); + #endif nullChunkCount++; continue; } + if (worldChunk.IsPacked()) + { + Logger.VerboseDebug("WORLD chunk: Compressed: X{0} Y{1} Z{2}", key.X, targetChunkY, key.Y); + worldChunk.Unpack( );//RESEARCH: Thread Unsafe? + } + /*************** Chunk Entities Scanning *********************/ - if (chunkData.BlockEntities != null && chunkData.BlockEntities.Length > 0) + if (worldChunk.BlockEntities != null && worldChunk.BlockEntities.Count > 0) { -#if DEBUG - Logger.VerboseDebug("Surface@ {0} = BlockEntities: {1}", key, chunkData.BlockEntities.Length); -#endif + #if DEBUG + Logger.VerboseDebug("Scan pos.({0}) for BlockEntities# {1}", key, worldChunk.BlockEntities.Count); + #endif - foreach (var blockEnt in chunkData.BlockEntities) + foreach (var blockEnt in worldChunk.BlockEntities) { - if (blockEnt != null && blockEnt.Block != null && BlockID_Designators.ContainsKey(blockEnt.Block.BlockId)) + if (blockEnt.Value != null && blockEnt.Value.Block != null && BlockID_Designators.ContainsKey(blockEnt.Value.Block.BlockId)) { - var designator = BlockID_Designators[blockEnt.Block.BlockId]; - designator.SpecialAction(ClientAPI, POIs, blockEnt.Pos.Copy(), blockEnt.Block); + var designator = BlockID_Designators[blockEnt.Value.Block.BlockId]; + designator.SpecialAction(ClientAPI, POIs, blockEnt.Value.Pos.Copy(), blockEnt.Value.Block); } } } + /********************* Chunk/Column BLOCKs scanning ****************/ //Heightmap, Stats, block tally - chunkData.Unpack(); - - //int X_index, Y_index, Z_index; - - //Ensure ChunkData Metadata fields arn't null...due to being tossed out - //if (chunkMeta.HeightMap == null) { chunkMeta.HeightMap = new ushort[chunkSize, chunkSize]; } - //if (chunkMeta.RockRatio == null) { chunkMeta.RockRatio = new Dictionary(10); } - - //for (Y_index = 0; Y_index < chunkSize - 1; Y_index++) - //{ - // for (Z_index = 0; Z_index < chunkSize - 1; Z_index++) - // { - // for (X_index = 0; X_index < chunkSize - 1; X_index++) - // { - // /* Encode packed indicie - // (y * chunksize + z) * chunksize + x - // */ - // var indicie = Helpers.ChunkBlockIndicie16(X_index, Y_index, Z_index); - // int aBlockId = chunkData.Blocks[indicie]; - - // if (aBlockId == 0) - // {//Air - // chunkMeta.AirBlocks++; - // continue; - // } - - // if (RockIdCodes.ContainsKey(aBlockId)) - // { - // if (chunkMeta.RockRatio.ContainsKey(aBlockId)) - // chunkMeta.RockRatio[aBlockId]++; - // else - // chunkMeta.RockRatio.Add(aBlockId, 1); - // } - - // chunkMeta.NonAirBlocks++; - - // //Heightmap - // //if (chunkMeta.HeightMap[X_index, Z_index] == 0) - // //{ - - // // chunkMeta.HeightMap[X_index, Z_index] = (ushort) (Y_index + (targetChunkY * chunkSize)); - // //} - // } - // } - - //} + int X_index, Y_index, Z_index; + + //First Chance fail-safe; + if (worldChunk.Blocks == null || worldChunk.Blocks.Length <= 0) { + Logger.VerboseDebug("WORLD chunk; Missing block DATA⁈ X{0} Y{1} Z{2} ⁈", key.X, targetChunkY, key.Y); + nullChunkCount++; + continue; + } + + chunkMeta.ColumnPresense[targetChunkY] = true; + chunkTally++; + for (Y_index = 0; Y_index < chunkSize; Y_index++) + { + for (Z_index = 0; Z_index < chunkSize; Z_index++) + { + for (X_index = 0; X_index < chunkSize; X_index++) + { + var indicie = MapUtil.Index3d(X_index, Y_index, Z_index, chunkSize, chunkSize); + + //'Last' Chance fail-safe; + if (worldChunk.Blocks == null || worldChunk.Blocks.Length <= 0) { + Logger.VerboseDebug("Processing Block: Missing block DATA⁈ X{0} Y{1} Z{2} ⁈", X_index, Y_index, Z_index); + nullChunkCount++; + goto loop_bustout; ; + } + + int aBlockId = worldChunk.Blocks[indicie]; + + if (aBlockId == 0 || AiryIdCodes.ContainsKey(aBlockId)) {//Airy blocks,,, + chunkMeta.AirBlocks++; + continue; + } + + if (RockIdCodes.ContainsKey(aBlockId)) { + if (chunkMeta.RockRatio.ContainsKey(aBlockId)) + chunkMeta.RockRatio[aBlockId]++; + else + chunkMeta.RockRatio.Add(aBlockId, 1); + } + + chunkMeta.NonAirBlocks++; + + ushort localHeight = ( ushort )(Y_index + (targetChunkY * chunkSize)); + //Heightmap - Need to ignore Grass & Snow + if (localHeight > chunkMeta.HeightMap[X_index, Z_index]) + { + chunkMeta.HeightMap[X_index, Z_index] = localHeight; + if (localHeight > chunkMeta.YMax) chunkMeta.YMax = localHeight; + } + } + } + } + loop_bustout:; } + Logger.VerboseDebug("COLUMN X{0} Z{1}: {2}, processed.", key.X , key.Y, chunkTally + 1); } private void UpdateEntityMetadata() @@ -644,14 +652,14 @@ namespace Automap foreach (var loadedEntity in ClientAPI.World.LoadedEntities.ToArray()) { -#if DEBUG + #if DEBUG //Logger.VerboseDebug($"ENTITY: ({loadedEntity.Value.Code}) = #{loadedEntity.Value.EntityId} {loadedEntity.Value.State} {loadedEntity.Value.LocalPos} <<<<<<<<<<<<"); -#endif + #endif var dMatch = Entity_Designators.SingleOrDefault(se => se.Key.Equals(loadedEntity.Value.Code)); if (dMatch.Value != null) { - dMatch.Value.SpecialAction(ClientAPI, this.EOIs, loadedEntity.Value.LocalPos.AsBlockPos.Copy(), loadedEntity.Value); + dMatch.Value.SpecialAction(ClientAPI, this.EOIs, loadedEntity.Value.Pos.AsBlockPos.Copy(), loadedEntity.Value); } } @@ -664,7 +672,7 @@ namespace Automap var playerNodePoi = new PointOfInterest() { Name = "Note", - Location = ClientAPI.World.Player.Entity.LocalPos.AsBlockPos.Copy(), + Location = ClientAPI.World.Player.Entity.Pos.AsBlockPos.Copy(), Notes = notation, Timestamp = DateTime.UtcNow, };