OSDN Git Service

Adjusted notes GUI, POI/EOI JSON metadata added
[automap/automap.git] / Automap / Helpers.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Drawing;
4 using System.Linq;
5
6 using Hjg.Pngcs.Chunks;
7
8 using Vintagestory.API.Client;
9 using Vintagestory.API.Common;
10 using Vintagestory.API.MathTools;
11
12 namespace Automap
13 {
14         public static class Helpers
15         {
16                 static Helpers( )
17                 {
18                         //Called once - thus it can only be in a static constructor.
19                         PngChunk.FactoryRegister(PngMetadataChunk.ID, typeof(PngMetadataChunk));
20                 }
21                 
22                 /// <summary>
23                 /// Hue, Saturation Value colorspace
24                 /// </summary>
25                 /// <returns>The color equiv.</returns>
26                 /// <param name="hue">0 - 360 for hue.</param>
27                 /// <param name="saturation"> 0 - 1 for saturation or value..</param>
28                 /// <param name="value"> 0 - 1 for saturation or value..</param>
29                 public static Color FromHSV(double hue, double saturation, double value)
30                 {
31                         int hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6;
32                         double f = hue / 60 - Math.Floor(hue / 60);
33
34                         value = value * 255;
35                         int v = Convert.ToInt32(value);
36                         int p = Convert.ToInt32(value * (1 - saturation));
37                         int q = Convert.ToInt32(value * (1 - f * saturation));
38                         int t = Convert.ToInt32(value * (1 - (1 - f) * saturation));
39
40                         if (hi == 0)
41                                 return Color.FromArgb(255, v, t, p);
42                         else if (hi == 1)
43                                 return Color.FromArgb(255, q, v, p);
44                         else if (hi == 2)
45                                 return Color.FromArgb(255, p, v, t);
46                         else if (hi == 3)
47                                 return Color.FromArgb(255, p, q, v);
48                         else if (hi == 4)
49                                 return Color.FromArgb(255, t, p, v);
50                         else
51                                 return Color.FromArgb(255, v, p, q);
52                 }
53
54                 public static string PrettyCoords(this BlockPos location, ICoreClientAPI ClientApi)
55                 {
56                         var start = ClientApi.World.DefaultSpawnPosition.AsBlockPos;
57
58                         return string.Format("X{0}, Y{1}, Z{2}", location.X - start.X, location.Y, location.Z - start.Z );
59                 }
60
61                 /// <summary>
62                 /// Chunk location to User display coordinate system
63                 /// </summary>
64                 /// <returns>Friendly string</returns>
65                 /// <param name="location">Chunk Coords.</param>
66                 public static string PrettyCoords(this Vec2i location, ICoreClientAPI ClientApi)
67                 {
68                 var start = ClientApi.World.DefaultSpawnPosition.AsBlockPos;
69                 var chunkSize = ClientApi.World.BlockAccessor.ChunkSize;
70
71                 return string.Format("X{0}, Z{1}", (location.X*chunkSize) - start.X, (location.Y*chunkSize) - start.Z);
72                 }
73
74                 public static BlockPos AverageHighestPos(List<BlockPos> positions)
75                 {
76                         int x = 0, y = 0, z = 0, length = positions.Count;
77                         foreach (BlockPos pos in positions)
78                         {
79                                 x += pos.X;
80                                 y = Math.Max(y, pos.Y);//Mutant Y-axis, take "HIGHEST"
81                                 z += pos.Z;
82                         }
83                         return new BlockPos(x/ length, y, z / length);
84                 }
85
86                 public static BlockPos PickRepresentativePosition(List<BlockPos> positions)
87                 {
88                         var averagePos = AverageHighestPos( positions );
89                         if ( positions.Any( pos => pos.X == averagePos.X && pos.Y == averagePos.Y && pos.Z == averagePos.Z ) ) {
90                                 return averagePos;//lucky ~ center was it!
91                         }
92
93                         //Otherwise...pick one
94                         var whichever = positions.Last(poz => poz.Y == averagePos.Y);
95
96                         return whichever;
97                 }
98
99
100
101                 /// <summary>
102                 /// Find a BLOCK partial path match: BlockID
103                 /// </summary>
104                 /// <returns>Matching finds</returns>
105                 /// <param name="assetName">Asset name.</param>
106                 public static Dictionary<int, string> ArbitrarytBlockIdHunter(this ICoreAPI CoreApi ,AssetLocation assetName, EnumBlockMaterial? material = null)
107                 {
108                         Dictionary<int, string> arbBlockIDTable = new Dictionary<int, string>( );
109                         uint emptyCount = 0;
110
111                         if (CoreApi.World.Blocks != null) {
112
113                                 #if DEBUG
114                                 CoreApi.World.Logger.VerboseDebug(" World Blocks [Count: {0}]", CoreApi.World.Blocks.Count);
115                                 #endif
116                                 //If Brute force won't work; use GROOT FORCE!
117                                 //var theBlock = ClientApi.World.BlockAccessor.GetBlock(0);
118
119                                 if (!material.HasValue) {
120                                         foreach (Block blk in CoreApi.World.Blocks) {
121                                                 if (blk.IsMissing || blk.Id == 0 || blk.BlockId == 0) {
122                                                         emptyCount++;
123                                                 } else if (blk.Code != null && blk.Code.BeginsWith(assetName.Domain, assetName.Path)) {
124                                                         #if DEBUG
125                                                         //CoreApi.World.Logger.VerboseDebug("Block: [{0} ({1})] =  #{2}", blk.Code.Path, blk.BlockMaterial, blk.BlockId);
126                                                         #endif
127
128                                                         arbBlockIDTable.Add(blk.BlockId, blk.Code.Path);
129                                                 }
130                                         }
131                                 } else {
132                                         foreach (Block blk in CoreApi.World.Blocks) {
133                                                 if (blk.IsMissing || blk.Id == 0 || blk.BlockId == 0) {
134                                                         emptyCount++;
135                                                 } else if (blk.Code != null && material.Value == blk.BlockMaterial && blk.Code.BeginsWith(assetName.Domain, assetName.Path)) {
136                                                         #if DEBUG
137                                                         //CoreApi.World.Logger.VerboseDebug("Block: [{0} ({1})] =  #{2}", blk.Code.Path, blk.BlockMaterial, blk.BlockId);
138                                                         #endif
139
140                                                         arbBlockIDTable.Add(blk.BlockId, blk.Code.Path);
141                                                 }
142                                         }
143                                 }
144
145                                 #if DEBUG
146                                 CoreApi.World.Logger.VerboseDebug("Block gaps: {0}", emptyCount);
147                                 #endif
148                         }
149
150                         return arbBlockIDTable;
151                 }
152
153
154
155                 /// <summary>
156                 /// Chunk local index. Not block position!
157                 /// </summary>
158                 /// <remarks>Clamps to 5 bit ranges automagically</remarks>
159                 public static int ChunkBlockIndicie16(int X_index, int Y_index, int Z_index)
160                 {                       
161                         return ((Y_index & 31) * 32 + (Z_index & 31)) * 32 + (X_index & 31);
162                 }
163
164                 /// <summary>
165                 /// Chunk index converted from block position (in world)
166                 /// </summary>
167                 /// <returns>The block indicie.</returns>
168                 /// <param name="blockPos">Block position.</param>
169                 /// <remarks>Clamps to 5 bit ranges automagically</remarks>
170                 public static int ChunkBlockIndicie16(BlockPos blockPos)
171                 {
172                         //Chunk masked
173                         return ((blockPos.Y & 31) * 32 + (blockPos.Z & 31)) * 32 + (blockPos.X & 31);
174                 }
175         }
176 }
177