<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\" />
<Folder Include="Designators\" />
<Folder Include="Libs\" />
<Folder Include="Subsystems\" />
+ <Folder Include="Renderers\" />
</ItemGroup>
<ItemGroup>
<None Include="modinfo.json">
using System.Linq;
using Vintagestory.API.MathTools;
+using Vintagestory.API.Common;
using ProtoBuf;
+
namespace Automap
{
[ProtoContract]
[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;
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;
+
}
}
--- /dev/null
+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;
+ }
+ }
+}
+
--- /dev/null
+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);
+ }
+}
+
--- /dev/null
+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( );
+ }
+ }
+}
+
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";
internal uint updatedChunksTotal;
internal Vec2i startChunkColumn;
-
+ private readonly int chunkSize;
private string path;
private IAsset stylesFile;
{
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);
}
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);
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) {
}
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;
}
}
-
-
-
private void Prefill_POI_Designators( )
{
this.POIs = new PointsOfInterest( );
//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)
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");
- 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;
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);
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
"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"