OSDN Git Service

Fixes for some post *.4 issues
[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                 public static ushort RainHeight2DMap(this IMapChunk mapChunk, int x, int y, int chunkSize = 32)
98                 {
99                         //int num = posZ % this.chunksize * this.chunksize + posX % this.chunksize;
100                         int index = (y % chunkSize) * chunkSize + (x % chunkSize);
101                         return mapChunk.RainHeightMap[index];
102                 }
103
104
105         /// <summary>
106         /// Find a BLOCK partial path match: BlockID
107         /// </summary>
108         /// <returns>Matching finds</returns>
109         /// <param name="assetName">Asset name.</param>
110         public static Dictionary<int, string> ArbitrarytBlockIdHunter(this ICoreAPI CoreApi, AssetLocation assetName, EnumBlockMaterial? material = null)
111         {
112             Dictionary<int, string> arbBlockIDTable = new Dictionary<int, string>();
113             uint emptyCount = 0;
114
115             if (CoreApi.World.Blocks != null)
116             {
117
118 #if DEBUG
119                 //CoreApi.World.Logger.VerboseDebug(" World Blocks [Count: {0}]", CoreApi.World.Blocks.Count);
120 #endif
121                 //If Brute force won't work; use GROOT FORCE!
122                 //var theBlock = ClientApi.World.BlockAccessor.GetBlock(0);
123
124                 if (!material.HasValue)
125                 {
126                     foreach (Block blk in CoreApi.World.Blocks)
127                     {
128                         if (blk.IsMissing || blk.Id == 0 || blk.BlockId == 0)
129                         {
130                             emptyCount++;
131                         }
132                         else if (blk.Code != null && blk.Code.BeginsWith(assetName.Domain, assetName.Path))
133                         {
134 #if DEBUG
135                             //CoreApi.World.Logger.VerboseDebug("Block: [{0} ({1})] =  #{2}", blk.Code.Path, blk.BlockMaterial, blk.BlockId);
136 #endif
137
138                             arbBlockIDTable.Add(blk.BlockId, blk.Code.Path);
139                         }
140                     }
141                 }
142                 else
143                 {
144                     foreach (Block blk in CoreApi.World.Blocks)
145                     {
146                         if (blk.IsMissing || blk.Id == 0 || blk.BlockId == 0)
147                         {
148                             emptyCount++;
149                         }
150                         else if (blk.Code != null && material.Value == blk.BlockMaterial && blk.Code.BeginsWith(assetName.Domain, assetName.Path))
151                         {
152 #if DEBUG
153                             //CoreApi.World.Logger.VerboseDebug("Block: [{0} ({1})] =  #{2}", blk.Code.Path, blk.BlockMaterial, blk.BlockId);
154 #endif
155
156                             arbBlockIDTable.Add(blk.BlockId, blk.Code.Path);
157                         }
158                     }
159                 }
160
161 #if DEBUG
162                 //CoreApi.World.Logger.VerboseDebug("Block gaps: {0}", emptyCount);
163 #endif
164             }
165
166             return arbBlockIDTable;
167         }
168
169                 public static Mod Self(this ICoreClientAPI ownApi)
170                 {
171                 AutomapMod ownMod = ownApi.ModLoader.GetModSystem<AutomapMod>( );
172                 return ownMod.Mod;
173                 }
174
175
176                 public static bool EndsWith(this AssetLocation asset, string domain, string endPath)
177                 {
178                 return asset.Domain.Equals(domain,StringComparison.InvariantCultureIgnoreCase) && asset.Path.EndsWith(endPath, StringComparison.InvariantCultureIgnoreCase);
179                 }
180     }
181 }
182