using System;
-using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
+using Hjg.Pngcs.Chunks;
+
using Vintagestory.API.Client;
using Vintagestory.API.Common;
using Vintagestory.API.MathTools;
namespace Automap
{
- public static class Helpers
- {
-
- /// <summary>
- /// Hue, Saturation Value colorspace
- /// </summary>
- /// <returns>The color equiv.</returns>
- /// <param name="hue">0 - 360 for hue.</param>
- /// <param name="saturation"> 0 - 1 for saturation or value..</param>
- /// <param name="value"> 0 - 1 for saturation or value..</param>
- public static Color FromHSV(double hue, double saturation, double value)
- {
- int hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6;
- double f = hue / 60 - Math.Floor(hue / 60);
-
- value = value * 255;
- int v = Convert.ToInt32(value);
- int p = Convert.ToInt32(value * (1 - saturation));
- int q = Convert.ToInt32(value * (1 - f * saturation));
- int t = Convert.ToInt32(value * (1 - (1 - f) * saturation));
-
- if (hi == 0)
- return Color.FromArgb(255, v, t, p);
- else if (hi == 1)
- return Color.FromArgb(255, q, v, p);
- else if (hi == 2)
- return Color.FromArgb(255, p, v, t);
- else if (hi == 3)
- return Color.FromArgb(255, p, q, v);
- else if (hi == 4)
- return Color.FromArgb(255, t, p, v);
- else
- return Color.FromArgb(255, v, p, q);
- }
-
- public static string PrettyCoords(this BlockPos location, ICoreClientAPI ClientApi)
+ public static class Helpers
+ {
+ static Helpers()
+ {
+ //Called once - thus it can only be in a static constructor.
+ PngChunk.FactoryRegister(PngMetadataChunk.ID, typeof(PngMetadataChunk));
+ }
+
+ /// <summary>
+ /// Hue, Saturation Value colorspace
+ /// </summary>
+ /// <returns>The color equiv.</returns>
+ /// <param name="hue">0 - 360 for hue.</param>
+ /// <param name="saturation"> 0 - 1 for saturation or value..</param>
+ /// <param name="value"> 0 - 1 for saturation or value..</param>
+ public static Color FromHSV(double hue, double saturation, double value)
+ {
+ int hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6;
+ double f = hue / 60 - Math.Floor(hue / 60);
+
+ value *= 255;
+ int v = Convert.ToInt32(value);
+ int p = Convert.ToInt32(value * (1 - saturation));
+ int q = Convert.ToInt32(value * (1 - f * saturation));
+ int t = Convert.ToInt32(value * (1 - (1 - f) * saturation));
+
+ switch (hi)
+ {
+ case 0: return Color.FromArgb(255, v, t, p);
+ case 1: return Color.FromArgb(255, q, v, p);
+ case 2: return Color.FromArgb(255, p, v, t);
+ case 3: return Color.FromArgb(255, p, q, v);
+ case 4: return Color.FromArgb(255, t, p, v);
+ default: return Color.FromArgb(255, v, p, q);
+ };
+ }
+
+ public static string PrettyCoords(this BlockPos location, ICoreClientAPI ClientApi)
+ {
+ var start = ClientApi.World.DefaultSpawnPosition.AsBlockPos;
+
+ return string.Format("X{0}, Y{1}, Z{2}", location.X - start.X, location.Y, location.Z - start.Z);
+ }
+
+ /// <summary>
+ /// Chunk location to User display coordinate system
+ /// </summary>
+ /// <returns>Friendly string</returns>
+ /// <param name="location">Chunk Coords.</param>
+ public static string PrettyCoords(this Vec2i location, ICoreClientAPI ClientApi)
+ {
+ var start = ClientApi.World.DefaultSpawnPosition.AsBlockPos;
+ var chunkSize = ClientApi.World.BlockAccessor.ChunkSize;
+
+ return string.Format("X{0}, Z{1}", (location.X * chunkSize) - start.X, (location.Y * chunkSize) - start.Z);
+ }
+
+ public static BlockPos AverageHighestPos(List<BlockPos> positions)
+ {
+ int x = 0, y = 0, z = 0, length = positions.Count;
+ foreach (BlockPos pos in positions)
+ {
+ x += pos.X;
+ y = Math.Max(y, pos.Y);//Mutant Y-axis, take "HIGHEST"
+ z += pos.Z;
+ }
+ return new BlockPos(x / length, y, z / length);
+ }
+
+ public static BlockPos PickRepresentativePosition(List<BlockPos> positions)
+ {
+ var averagePos = AverageHighestPos(positions);
+ if (positions.Any(pos => pos.X == averagePos.X && pos.Y == averagePos.Y && pos.Z == averagePos.Z))
+ {
+ return averagePos;//lucky ~ center was it!
+ }
+
+ //Otherwise...pick one
+ var whichever = positions.Last(poz => poz.Y == averagePos.Y);
+
+ return whichever;
+ }
+
+ public static ushort RainHeight2DMap(this IMapChunk mapChunk, int x, int y, int chunkSize = 32)
{
- var start = ClientApi.World.DefaultSpawnPosition.AsBlockPos;
-
- return string.Format("X{0}, Y{1}, Z{2}", location.X - start.X, location.Y, location.Z - start.Z );
+ int index = y % chunkSize * chunkSize + x % chunkSize;
+ return mapChunk.RainHeightMap[index];
}
- public static BlockPos AverageHighestPos(List<BlockPos> positions)
- {
- int x = 0, y = 0, z = 0, length = positions.Count;
- foreach (BlockPos pos in positions)
- {
- x += pos.X;
- y = Math.Max(y, pos.Y);//Mutant Y-axis, take "HIGHEST"
- z += pos.Z;
- }
- return new BlockPos(x/ length, y, z / length);
- }
-
- public static BlockPos PickRepresentativePosition(List<BlockPos> positions)
- {
- var averagePos = AverageHighestPos( positions );
- if ( positions.Any( pos => pos.X == averagePos.X && pos.Y == averagePos.Y && pos.Z == averagePos.Z ) ) {
- return averagePos;//lucky ~ center was it!
- }
-
- //Otherwise...pick one
- var whichever = positions.Last(poz => poz.Y == averagePos.Y);
-
- return whichever;
- }
-
-
-
- /// <summary>
- /// Find a BLOCK partial path match: BlockID
- /// </summary>
- /// <returns>Matching finds</returns>
- /// <param name="assetName">Asset name.</param>
- public static Dictionary<int, string> ArbitrarytBlockIdHunter(this ICoreAPI CoreApi ,AssetLocation assetName, EnumBlockMaterial? material = null)
- {
- Dictionary<int, string> arbBlockIDTable = new Dictionary<int, string>( );
- uint emptyCount = 0;
-
- if (CoreApi.World.Blocks != null) {
-
- #if DEBUG
- CoreApi.World.Logger.VerboseDebug(" World Blocks [Count: {0}]", CoreApi.World.Blocks.Count);
- #endif
- //If Brute force won't work; use GROOT FORCE!
- //var theBlock = ClientApi.World.BlockAccessor.GetBlock(0);
-
- if (!material.HasValue) {
- foreach (Block blk in CoreApi.World.Blocks) {
- if (blk.IsMissing || blk.Id == 0 || blk.BlockId == 0) {
- emptyCount++;
- } else if (blk.Code != null && blk.Code.BeginsWith(assetName.Domain, assetName.Path)) {
- #if DEBUG
- //CoreApi.World.Logger.VerboseDebug("Block: [{0} ({1})] = #{2}", blk.Code.Path, blk.BlockMaterial, blk.BlockId);
- #endif
-
- arbBlockIDTable.Add(blk.BlockId, blk.Code.Path);
- }
- }
- } else {
- foreach (Block blk in CoreApi.World.Blocks) {
- if (blk.IsMissing || blk.Id == 0 || blk.BlockId == 0) {
- emptyCount++;
- } else if (blk.Code != null && material.Value == blk.BlockMaterial && blk.Code.BeginsWith(assetName.Domain, assetName.Path)) {
- #if DEBUG
- //CoreApi.World.Logger.VerboseDebug("Block: [{0} ({1})] = #{2}", blk.Code.Path, blk.BlockMaterial, blk.BlockId);
- #endif
-
- arbBlockIDTable.Add(blk.BlockId, blk.Code.Path);
- }
- }
- }
-
- #if DEBUG
- CoreApi.World.Logger.VerboseDebug("Block gaps: {0}", emptyCount);
- #endif
- }
-
- return arbBlockIDTable;
- }
-
-
-
- /// <summary>
- /// Chunk local index. Not block position!
- /// </summary>
- /// <remarks>Clamps to 5 bit ranges automagically</remarks>
- public static int ChunkBlockIndicie16(int X_index, int Y_index, int Z_index)
- {
- return ((Y_index & 31) * 32 + (Z_index & 31)) * 32 + (X_index & 31);
- }
- /// <summary>
- /// Chunk index converted from block position (in world)
- /// </summary>
- /// <returns>The block indicie.</returns>
- /// <param name="blockPos">Block position.</param>
- /// <remarks>Clamps to 5 bit ranges automagically</remarks>
- public static int ChunkBlockIndicie16(BlockPos blockPos)
+ /// <summary>
+ /// Find a BLOCK partial path match: BlockID
+ /// </summary>
+ /// <returns>Matching finds</returns>
+ /// <param name="assetName">Asset name.</param>
+ public static Dictionary<int, string> ArbitrarytBlockIdHunter(this ICoreAPI CoreApi, AssetLocation assetName, EnumBlockMaterial? material = null)
+ {
+ Dictionary<int, string> arbBlockIDTable = new Dictionary<int, string>();
+ uint emptyCount = 0;
+
+ if (CoreApi.World.Blocks != null)
+ {
+
+#if DEBUG
+ CoreApi.World.Logger.VerboseDebug(" World Blocks [Count: {0}]", CoreApi.World.Blocks.Count);
+#endif
+ //If Brute force won't work; use GROOT FORCE!
+ //var theBlock = ClientApi.World.BlockAccessor.GetBlock(0);
+
+ if (!material.HasValue)
+ {
+ foreach (Block blk in CoreApi.World.Blocks)
+ {
+ if (blk.IsMissing || blk.Id == 0 || blk.BlockId == 0)
+ {
+ emptyCount++;
+ }
+ else if (blk.Code != null && blk.Code.BeginsWith(assetName.Domain, assetName.Path))
+ {
+#if DEBUG
+ //CoreApi.World.Logger.VerboseDebug("Block: [{0} ({1})] = #{2}", blk.Code.Path, blk.BlockMaterial, blk.BlockId);
+#endif
+
+ arbBlockIDTable.Add(blk.BlockId, blk.Code.Path);
+ }
+ }
+ }
+ else
+ {
+ foreach (Block blk in CoreApi.World.Blocks)
+ {
+ if (blk.IsMissing || blk.Id == 0 || blk.BlockId == 0)
+ {
+ emptyCount++;
+ }
+ else if (blk.Code != null && material.Value == blk.BlockMaterial && blk.Code.BeginsWith(assetName.Domain, assetName.Path))
+ {
+#if DEBUG
+ //CoreApi.World.Logger.VerboseDebug("Block: [{0} ({1})] = #{2}", blk.Code.Path, blk.BlockMaterial, blk.BlockId);
+#endif
+
+ arbBlockIDTable.Add(blk.BlockId, blk.Code.Path);
+ }
+ }
+ }
+
+#if DEBUG
+ CoreApi.World.Logger.VerboseDebug("Block gaps: {0}", emptyCount);
+#endif
+ }
+
+ return arbBlockIDTable;
+ }
+
+ public static Mod Self(this ICoreClientAPI ownApi)
{
- //Chunk masked
- return ((blockPos.Y & 31) * 32 + (blockPos.Z & 31)) * 32 + (blockPos.X & 31);
+ AutomapMod ownMod = ownApi.ModLoader.GetModSystem<AutomapMod>( );
+ return ownMod.Mod;
}
- }
+
+ }
}