OSDN Git Service

47033791c91cb3b5757f2d8b029d9acc214f0511
[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 *= 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                         switch (hi) 
41             {
42                                 case 0: return Color.FromArgb(255, v, t, p);
43                                 case 1: return Color.FromArgb(255, q, v, p);
44                                 case 2: return Color.FromArgb(255, p, v, t);
45                                 case 3: return Color.FromArgb(255, p, q, v);
46                                 case 4: return Color.FromArgb(255, t, p, v);
47                                 default: return Color.FromArgb(255, v, p, q);
48             };
49         }
50
51         public static string PrettyCoords(this BlockPos location, ICoreClientAPI ClientApi)
52         {
53             var start = ClientApi.World.DefaultSpawnPosition.AsBlockPos;
54
55             return string.Format("X{0}, Y{1}, Z{2}", location.X - start.X, location.Y, location.Z - start.Z);
56         }
57
58         /// <summary>
59         /// Chunk location to User display coordinate system
60         /// </summary>
61         /// <returns>Friendly string</returns>
62         /// <param name="location">Chunk Coords.</param>
63         public static string PrettyCoords(this Vec2i location, ICoreClientAPI ClientApi)
64         {
65             var start = ClientApi.World.DefaultSpawnPosition.AsBlockPos;
66             var chunkSize = ClientApi.World.BlockAccessor.ChunkSize;
67
68             return string.Format("X{0}, Z{1}", (location.X * chunkSize) - start.X, (location.Y * chunkSize) - start.Z);
69         }
70
71         public static BlockPos AverageHighestPos(List<BlockPos> positions)
72         {
73             int x = 0, y = 0, z = 0, length = positions.Count;
74             foreach (BlockPos pos in positions)
75             {
76                 x += pos.X;
77                 y = Math.Max(y, pos.Y);//Mutant Y-axis, take "HIGHEST"
78                 z += pos.Z;
79             }
80             return new BlockPos(x / length, y, z / length);
81         }
82
83         public static BlockPos PickRepresentativePosition(List<BlockPos> positions)
84         {
85             var averagePos = AverageHighestPos(positions);
86             if (positions.Any(pos => pos.X == averagePos.X && pos.Y == averagePos.Y && pos.Z == averagePos.Z))
87             {
88                 return averagePos;//lucky ~ center was it!
89             }
90
91             //Otherwise...pick one
92             var whichever = positions.Last(poz => poz.Y == averagePos.Y);
93
94             return whichever;
95         }
96
97
98
99         /// <summary>
100         /// Find a BLOCK partial path match: BlockID
101         /// </summary>
102         /// <returns>Matching finds</returns>
103         /// <param name="assetName">Asset name.</param>
104         public static Dictionary<int, string> ArbitrarytBlockIdHunter(this ICoreAPI CoreApi, AssetLocation assetName, EnumBlockMaterial? material = null)
105         {
106             Dictionary<int, string> arbBlockIDTable = new Dictionary<int, string>();
107             uint emptyCount = 0;
108
109             if (CoreApi.World.Blocks != null)
110             {
111
112 #if DEBUG
113                 CoreApi.World.Logger.VerboseDebug(" World Blocks [Count: {0}]", CoreApi.World.Blocks.Count);
114 #endif
115                 //If Brute force won't work; use GROOT FORCE!
116                 //var theBlock = ClientApi.World.BlockAccessor.GetBlock(0);
117
118                 if (!material.HasValue)
119                 {
120                     foreach (Block blk in CoreApi.World.Blocks)
121                     {
122                         if (blk.IsMissing || blk.Id == 0 || blk.BlockId == 0)
123                         {
124                             emptyCount++;
125                         }
126                         else if (blk.Code != null && blk.Code.BeginsWith(assetName.Domain, assetName.Path))
127                         {
128 #if DEBUG
129                             //CoreApi.World.Logger.VerboseDebug("Block: [{0} ({1})] =  #{2}", blk.Code.Path, blk.BlockMaterial, blk.BlockId);
130 #endif
131
132                             arbBlockIDTable.Add(blk.BlockId, blk.Code.Path);
133                         }
134                     }
135                 }
136                 else
137                 {
138                     foreach (Block blk in CoreApi.World.Blocks)
139                     {
140                         if (blk.IsMissing || blk.Id == 0 || blk.BlockId == 0)
141                         {
142                             emptyCount++;
143                         }
144                         else if (blk.Code != null && material.Value == blk.BlockMaterial && blk.Code.BeginsWith(assetName.Domain, assetName.Path))
145                         {
146 #if DEBUG
147                             //CoreApi.World.Logger.VerboseDebug("Block: [{0} ({1})] =  #{2}", blk.Code.Path, blk.BlockMaterial, blk.BlockId);
148 #endif
149
150                             arbBlockIDTable.Add(blk.BlockId, blk.Code.Path);
151                         }
152                     }
153                 }
154
155 #if DEBUG
156                 CoreApi.World.Logger.VerboseDebug("Block gaps: {0}", emptyCount);
157 #endif
158             }
159
160             return arbBlockIDTable;
161         }
162
163
164
165         /// <summary>
166         /// Chunk local index. Not block position!
167         /// </summary>
168         /// <remarks>Clamps to 5 bit ranges automagically</remarks>
169         public static int ChunkBlockIndicie16(int X_index, int Y_index, int Z_index)
170         {
171             return ((Y_index & 31) * 32 + (Z_index & 31)) * 32 + (X_index & 31);
172         }
173
174         /// <summary>
175         /// Chunk index converted from block position (in world)
176         /// </summary>
177         /// <returns>The block indicie.</returns>
178         /// <param name="blockPos">Block position.</param>
179         /// <remarks>Clamps to 5 bit ranges automagically</remarks>
180         public static int ChunkBlockIndicie16(BlockPos blockPos)
181         {
182             //Chunk masked
183             return ((blockPos.Y & 31) * 32 + (blockPos.Z & 31)) * 32 + (blockPos.X & 31);
184         }
185     }
186 }
187