using System;
+using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
-using System.IO;
using System.Collections.ObjectModel;
-using System.Text;
+
using Vintagestory.API.MathTools;
using Vintagestory.API.Common;
using ProtoBuf;
+
namespace Automap
{
[ProtoContract(ImplicitFields = ImplicitFields.None)]
[ProtoMember(13)]
private ushort[] _flattened_HeightMap;
- public ColumnMeta(Vec2i loc, ICoreClientAPI clientAPI, byte chunkSize = 32)
+
+ /// <summary>
+ /// Column Presense Bitmap
+ /// </summary>
+ [ProtoIgnore]
+ public BitArray ColumnPresense;
+
+ public ColumnMeta(Vec2i loc, ICoreClientAPI clientAPI, byte chunkSize = 32, int maxChunkHeight = 16)
{
Location = loc;
PrettyLocation = loc.PrettyCoords(clientAPI);
ChunkSize = chunkSize;
HeightMap = new ushort[ChunkSize, ChunkSize];
_flattened_HeightMap = null;
+ ColumnPresense = new BitArray(maxChunkHeight, false);//TODO: get real chunk height MAX
}
internal void UpdateFieldsFrom(ClimateCondition climate, IMapChunk mapChunk, TimeSpan chunkAge)
public virtual ILogger Logger { get; protected set; }
public virtual Dictionary<int, BlockDesignator> BlockID_Designators { get; set; }
public virtual bool SeasonalColors { get; }
- //private PngWriter pngWriter;
+ public virtual PngWriter PngWriter { get; set;}
protected AChunkRenderer(ICoreClientAPI clientAPI, ILogger logger, bool useSeasonColor = true)
{
}
- public abstract void GenerateChunkPngShard(Vec2i chunkPos, IMapChunk mapChunk, ColumnMeta metaData, PngWriter pngWriter, out uint pixelCount);
+ public abstract void GenerateChunkPngShard(Vec2i chunkPos, IMapChunk mapChunk, ColumnMeta metaData, out uint pixelCount);
public virtual PngWriter SetupPngImage(Vec2i coord, string path, string chunkPath, ref ColumnMeta metadata)
{
string filename = $"{coord.X}_{coord.Y}.png";
filename = Path.Combine(path, chunkPath, filename);
- PngWriter pngWriter = FileHelper.CreatePngWriter(filename, imageInf, true);
- PngMetadata meta = pngWriter.GetMetadata( );
+ this.PngWriter = FileHelper.CreatePngWriter(filename, imageInf, true);
+ PngMetadata meta = this.PngWriter.GetMetadata( );
meta.SetTimeNow( );
meta.SetText("Chunk_X", coord.X.ToString("D"));
meta.SetText("Chunk_Y", coord.Y.ToString("D"));
meta.SetText("PxSz", "1");
//Setup specialized meta-data PNG chunks here...
- PngMetadataChunk pngChunkMeta = new PngMetadataChunk(pngWriter.ImgInfo) {
+ PngMetadataChunk pngChunkMeta = new PngMetadataChunk(this.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;
+ this.PngWriter.GetChunksList( ).Queue(pngChunkMeta);
+ this.PngWriter.CompLevel = 5;// 9 is the maximum compression but thats too high for the small benefit it gives
+ this.PngWriter.CompressionStrategy = Hjg.Pngcs.Zlib.EDeflateCompressStrategy.Huffman;
- return pngWriter;
+ return this.PngWriter;
}
- protected virtual void ExtractBlockColor(BlockPos tmpPos, Block block, float slopeBoost,out int red, out int green, out int blue )
+ protected virtual void ExtractBlockColor(BlockPos tmpPos, Block block, float slopeBoost, out int red, out int green, out int blue)
{
int avgCol, rndCol, col, packedFormat;
}
else {
col = block.GetColorWithoutTint(ClientAPI, tmpPos);
- //How to set as Eternal-Summer???
- //col = ClientAPI.World.ApplyColorMapOnRgba(block.ClimateColorMapForMap, block.SeasonColorMapForMap, col, tmpPos.X, tmpPos.Y, tmpPos.Z);
-
- /*
+ //How to set as Eternal-Summer...perhaps if block is plant, dirt...
+ if (block.BlockMaterial == EnumBlockMaterial.Leaves ||
+ block.BlockMaterial == EnumBlockMaterial.Plant ||
+ block.BlockMaterial == EnumBlockMaterial.Soil
+ ) {
+ col = ClientAPI.World.ApplyColorMapOnRgba(block.ClimateColorMapForMap, block.SeasonColorMapForMap, col, tmpPos.X, tmpPos.Y, tmpPos.Z);
int greenAmp = ColorUtil.ColorG(127);
- col = ColorUtil.ColorOverlay(col, greenAmp, 0.125f);
- */
- packedFormat = ColorUtil.ColorMultiply3Clamped(col, slopeBoost);
+ col = ColorUtil.ColorOverlay(col, greenAmp, 0.25f);
+ }
+ packedFormat = ColorUtil.ColorMultiply3Clamped(col, slopeBoost);
red = ColorUtil.ColorB(packedFormat);
green = ColorUtil.ColorG(packedFormat);
blue = ColorUtil.ColorR(packedFormat);
}
+
}
}
}
}
- public override void GenerateChunkPngShard(Vec2i chunkPos, IMapChunk mc, ColumnMeta metaData, PngWriter pngWriter, out uint pixelCount)
+ public override void GenerateChunkPngShard(Vec2i chunkPos, IMapChunk mc, ColumnMeta metaData, out uint pixelCount)
{
pixelCount = 0;
BlockPos tmpPos = new BlockPos();
}
//pre-create PNG line slices...
- ImageLine[] lines = Enumerable.Repeat(new object(), chunkSize).Select(l => new ImageLine(pngWriter.ImgInfo)).ToArray();
+ ImageLine[] lines = Enumerable.Repeat(new object(), chunkSize).Select(l => new ImageLine(this.PngWriter.ImgInfo)).ToArray();
ushort[] allMapYs = mc.RainHeightMap;
for (int posIndex = 0; posIndex < (chunkSize * chunkSize); posIndex++)
{
pixelCount++;
}
- for (int row = 0; row < pngWriter.ImgInfo.Rows; row++)
+ for (int row = 0; row < this.PngWriter.ImgInfo.Rows; row++)
{
- pngWriter.WriteRow(lines[row], row);
+ this.PngWriter.WriteRow(lines[row], row);
}
- pngWriter.End();
+ this.PngWriter.End();
}
private float GetSlope(int x, int y, ushort[] heightMap)
}
- public override void GenerateChunkPngShard(Vec2i chunkPos, IMapChunk mc, ColumnMeta metaData, PngWriter pngWriter, out uint pixelCount)
+ public override void GenerateChunkPngShard(Vec2i chunkPos, IMapChunk mc, ColumnMeta metaData, out uint pixelCount)
{
pixelCount = 0;
BlockPos tmpPos = new BlockPos();
};
//pre-create PNG line slices...
- ImageLine[] lines = Enumerable.Repeat(new object(), chunkSize).Select(l => new ImageLine(pngWriter.ImgInfo)).ToArray();
+ ImageLine[] lines = Enumerable.Repeat(new object(), chunkSize).Select(l => new ImageLine(this.PngWriter.ImgInfo)).ToArray();
for (int posIndex = 0; posIndex < (chunkSize * chunkSize); posIndex++)
{
pixelCount++;
}
- for (int row = 0; row < pngWriter.ImgInfo.Rows; row++)
+ for (int row = 0; row < this.PngWriter.ImgInfo.Rows; row++)
{
- pngWriter.WriteRow(lines[row], row);
+ this.PngWriter.WriteRow(lines[row], row);
}
- pngWriter.End();
+ this.PngWriter.End();
}
}
}
using System.Threading;
using Hjg.Pngcs;
-using Hjg.Pngcs.Chunks;
using ProtoBuf;
}
ProcessChunkBlocks(mostActiveCol.Key, mapChunk, ref chunkMeta);
- PngWriter pngWriter = ChunkRenderer.SetupPngImage(mostActiveCol.Key, path, _chunkPath, 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)
{
private ColumnMeta CreateColumnMetadata(KeyValuePair<Vec2i, uint> 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);
int targetChunkY = mapChunk.YMax / chunkSize;//Surface ...
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;
}
+ worldChunk.Unpack( );//RESEARCH: Thread Unsafe?
+
/*************** Chunk Entities Scanning *********************/
- if (chunkData.BlockEntities != null && chunkData.BlockEntities.Count > 0)
+ if (worldChunk.BlockEntities != null && worldChunk.BlockEntities.Count > 0)
{
-#if DEBUG
- Logger.VerboseDebug("Surface@ {0} = BlockEntities: {1}", key, chunkData.BlockEntities.Count);
-#endif
+ #if DEBUG
+ Logger.VerboseDebug("Surface@ {0} = BlockEntities: {1}", key, worldChunk.BlockEntities.Count);
+ #endif
- foreach (var blockEnt in chunkData.BlockEntities)
+ foreach (var blockEnt in worldChunk.BlockEntities)
{
if (blockEnt.Value != null && blockEnt.Value.Block != null && BlockID_Designators.ContainsKey(blockEnt.Value.Block.BlockId))
{
}
}
}
+
+ chunkMeta.ColumnPresense[targetChunkY] = true;
+
/********************* Chunk/Column BLOCKs scanning ****************/
//Heightmap, Stats, block tally
- chunkData.Unpack();
- //int X_index, Y_index, Z_index;
+ 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<int, uint>(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));
- // //}
- // }
- // }
-
- //}
+ if (chunkMeta.HeightMap == null) { chunkMeta.HeightMap = new ushort[chunkSize, chunkSize]; }
+ if (chunkMeta.RockRatio == null) { chunkMeta.RockRatio = new Dictionary<int, uint>(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 = worldChunk.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));
+ }
+ }
+ }
+
+ }
}
}
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)
{
"type": "code",
"name": "Automap",
- "description" : "Automap; Generates a static HTML map dynamically, with Points of Interest!",
+ "description" : "Automap; Generates a static HTML5 map dynamically, with P.O.I. Tracking & more.",
"authors": ["Melchior","VeryGoodDog"],
"contributors":["VeryGoodDog"],
- "version": "0.1.4",
+ "version": "0.1.5",
"side":"Client",
"dependencies": {
- "game": "1.13.0-pre.5"
+ "game": "1.13.4"
},
"website": "http://nowebsite.nope"
}
\ No newline at end of file