using Vintagestory.API.Client;
using Vintagestory.API.Common;
using Vintagestory.API.MathTools;
+using Vintagestory.Common;
namespace Automap
{
public class StandardRenderer : AChunkRenderer
{
-
-
/// <summary>
/// Renders shards similar to the Default VS version, plus P.O.I. markings.
/// <param name="logger">Logger.</param>
public StandardRenderer(ICoreClientAPI clientAPI, ILogger logger, bool seasonalColor) : base(clientAPI, logger, seasonalColor)
{
-
+
}
public override void GenerateChunkPngShard(Vec2i chunkPos, IMapChunk mc, ColumnMeta metaData, out uint pixelCount)
{
- pixelCount = 0;
- BlockPos tmpPos = new BlockPos();
- Vec2i localpos = new Vec2i();
+ pixelCount = 0;
+ BlockPos tmpPos = new BlockPos( );
+ Vec2i localpos = new Vec2i( );
- var chunksColumn = new IWorldChunk[ClientAPI.World.BlockAccessor.MapSizeY / 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!
+ //pre-create PNG line slices...
+ ImageLine[ ] lines = Enumerable.Repeat(new object( ), chunkSize).Select(l => new ImageLine(this.PngWriter.ImgInfo)).ToArray( );
- 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?
- }
+ int topChunkY = metaData.YMax / chunkSize;
- // Prefetch map chunks, in pattern
- IMapChunk[] mapChunks = new IMapChunk[]
- {
+ for (int chunkY = 0; chunkY <= topChunkY; chunkY++)
+ {
+ chunksColumn[chunkY] = ClientAPI.World.BlockAccessor.GetChunk(chunkPos.X, chunkY, chunkPos.Y);
+ WorldChunk ownChunk = chunksColumn[chunkY] as WorldChunk;
+ if (ownChunk != null)
+ {
+ if (ownChunk.IsPacked( )) ownChunk.Unpack( );//Gah - probably done already by chunk processor
+ }
+ else
+ {
+ Logger.Warning("CHUNK A.W.O.L. : X{0} Y{1} Z{2} - Missing slice FOR COLUMN", chunkPos.X, chunkY, chunkPos.Y);
+ //return;
+ }
+ }
+
+ // 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(this.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 slopeBoost = 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;
+ for (int pixelIndex = 0; pixelIndex < (chunkSize * chunkSize); pixelIndex++) {
+ MapUtil.PosInt2d(pixelIndex, chunkSize, localpos);
+ int localX = localpos.X;
+ int localZ = localpos.Y;
+ ushort localY = metaData.HeightMap[localX, localZ];//mc.RainHeightMap[posIndex];//NOPE NOPE NOPE, RAINMAP IS CRAP. USE IT NOT!
- 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];
- }
- }
+ int localChunkY = localY / chunkSize;
+ if (localChunkY >= (chunksColumn.Length)) continue;//Out of range!
+ if (chunksColumn[localChunkY] == null) continue;//BIG Gaps!
- topX = GameMath.Mod(topX, chunkSize);
- leftZ = GameMath.Mod(leftZ, chunkSize);
+ float slopeBoost = 1;
+ int leftTop, rightTop, leftBot;
- 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]);
+ IMapChunk leftTopMapChunk = mc;
+ IMapChunk rightTopMapChunk = mc;
+ IMapChunk leftBotMapChunk = mc;
- float slopeness = (leftTop + rightTop + leftBot);
+ int topX = localX - 1;
+ int botX = localX;
+ int leftZ = localZ - 1;
+ int rightZ = localZ;
- if (slopeness > 0) slopeBoost = 1.2f;
- if (slopeness < 0) slopeBoost = 0.8f;
+ 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];
+ }
+ }
- slopeBoost -= 0.15f; //Slope boost value
+ topX = GameMath.Mod(topX, chunkSize);
+ leftZ = GameMath.Mod(leftZ, chunkSize);
- if (chunksColumn[localChunkY] == null)
- {
+ leftTop = leftTopMapChunk == null ? 0 : Math.Sign(localY - leftTopMapChunk.RainHeightMap[leftZ * chunkSize + topX]);
+ rightTop = rightTopMapChunk == null ? 0 : Math.Sign(localY - rightTopMapChunk.RainHeightMap[rightZ * chunkSize + topX]);
+ leftBot = leftBotMapChunk == null ? 0 : Math.Sign(localY - leftBotMapChunk.RainHeightMap[leftZ * chunkSize + botX]);
- continue;
- }
+ float slopeness = (leftTop + rightTop + leftBot);
- chunksColumn[localChunkY].Unpack();
- int blockId = chunksColumn[localChunkY].Blocks[MapUtil.Index3d(localpos.X, mapY % chunkSize, localpos.Y, chunkSize, chunkSize)];
+ if (slopeness > 0) slopeBoost = 1.2f;
+ if (slopeness < 0) slopeBoost = 0.8f;
- Block block = ClientAPI.World.Blocks[blockId];
+ slopeBoost -= 0.15f; //Slope boost value
- tmpPos.Set(chunkSize * chunkPos.X + localpos.X, mapY, chunkSize * chunkPos.Y + localpos.Y);
+ int blockId = chunksColumn[localChunkY].Blocks[MapUtil.Index3d(localX, (localY % chunkSize), localZ, chunkSize, chunkSize)];
- int red, green, blue;
+ Block block = ClientAPI.World.Blocks[blockId];
- ExtractBlockColor(tmpPos, block, slopeBoost, out red, out green, out blue);
+ tmpPos.Set(chunkSize * chunkPos.X + localpos.X, localY, chunkSize * chunkPos.Y + localpos.Y);
- //============ POI Population =================
- if (BlockID_Designators.ContainsKey(blockId))
- {
- var desig = BlockID_Designators[blockId];
-
- if (desig.Enabled)
- {
- red = desig.OverwriteColor.R;
- green = desig.OverwriteColor.G;
- blue = desig.OverwriteColor.B;
- }
- }
+ int red = 0, green = 0, blue = 0;
- ImageLineHelper.SetPixel(lines[localZ], localX, red, green, blue);
+ ExtractBlockColor(tmpPos, block, slopeBoost, out red, out green, out blue);
- //chunkImage.SetPixel(localX, localZ, pixelColor);
- pixelCount++;
- }
+ //============ POI Population =================
+ if (BlockID_Designators.ContainsKey(blockId)) {
+ var desig = BlockID_Designators[blockId];
- for (int row = 0; row < this.PngWriter.ImgInfo.Rows; row++)
+ if (desig.Enabled)
{
- this.PngWriter.WriteRow(lines[row], row);
+ red = desig.OverwriteColor.R;
+ green = desig.OverwriteColor.G;
+ blue = desig.OverwriteColor.B;
}
+ }
- this.PngWriter.End();
+ ImageLineHelper.SetPixel(lines[localZ], localX, red, green, blue);
+ pixelCount++;
+ }
+
+ for (int row = 0; row < this.PngWriter.ImgInfo.Rows; row++) {
+ this.PngWriter.WriteRow(lines[row], row);
}
- }
-}
+ this.PngWriter.End( );
+ }
+ }
+}
\ No newline at end of file
{
columnCounter.TryRemove(mostActiveCol.Key, out ejectedItem);
#if DEBUG
- Logger.VerboseDebug("Un-painted chun shard: ({0}) ", mostActiveCol.Key);
+ Logger.VerboseDebug("Un-painted chunk shard: ({0}) ", mostActiveCol.Key);
#endif
}
}
- //Cleanup persisted Metadata...
+ //Cleanup in-memory Metadata...
chunkTopMetadata.ClearMetadata();
}
/// <param name="chunkMeta">Chunk metadata</param>
private void ProcessChunkBlocks(Vec2i key, IMapChunk mapChunk, ref ColumnMeta chunkMeta)
{
+ int targetChunkY = mapChunk.YMax / chunkSize;//Surface ish...
+ byte chunkTally = 0;
- int targetChunkY = mapChunk.YMax / chunkSize;//Surface ...
- for (; targetChunkY > 0; targetChunkY--)
+ #if DEBUG
+ Logger.VerboseDebug("Start col @ X{0} Y{1} Z{2} !", key.X, targetChunkY, key.Y);
+ #endif
+
+ chunkMeta.ResetMetadata(ClientAPI.World.BlockAccessor.MapSizeY);
+
+ for (; targetChunkY > 0; targetChunkY--)
{
WorldChunk worldChunk = ClientAPI.World.BlockAccessor.GetChunk(key.X, targetChunkY, key.Y) as WorldChunk;
}
}
- //NOTE: Temporary; remove - replace later
- if (chunkMeta.ColumnPresense == null) { chunkMeta.ColumnPresense = new BitArray((ClientAPI.World.BlockAccessor.MapSizeY / chunkSize), false); }
- chunkMeta.ColumnPresense[targetChunkY] = true;
-
/********************* Chunk/Column BLOCKs scanning ****************/
//Heightmap, Stats, block tally
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); }
-
//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;
}
- for (Y_index = 0; Y_index < chunkSize - 1; Y_index++)
+ chunkMeta.ColumnPresense[targetChunkY] = true;
+ chunkTally++;
+ for (Y_index = 0; Y_index < chunkSize; Y_index++)
{
- for (Z_index = 0; Z_index < chunkSize - 1; Z_index++)
+ for (Z_index = 0; Z_index < chunkSize; Z_index++)
{
- for (X_index = 0; X_index < chunkSize - 1; X_index++)
+ for (X_index = 0; X_index < chunkSize; X_index++)
{
- /* Encode packed indicie
- (y * chunksize + z) * chunksize + x
- */
- var indicie = Helpers.ChunkBlockIndicie16(X_index, Y_index, Z_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);
- goto loop_bustout;;
+ nullChunkCount++;
+ goto loop_bustout; ;
}
-
+
int aBlockId = worldChunk.Blocks[indicie];
- if (aBlockId == 0)
- {//Air
- chunkMeta.AirBlocks++;
- continue;
+ 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);
+ 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));
- }
+ 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()