utility.h: Change Buffer's interface to be more compatible with SharedBuffer's interf...
[oweals/minetest.git] / src / utility.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 /*
21 (c) 2010 Perttu Ahola <celeron55@gmail.com>
22 */
23
24 #include "utility.h"
25 #include "gettime.h"
26 #include "sha1.h"
27 #include "base64.h"
28 #include "log.h"
29
30 TimeTaker::TimeTaker(const char *name, u32 *result)
31 {
32         m_name = name;
33         m_result = result;
34         m_running = true;
35         m_time1 = getTimeMs();
36 }
37
38 u32 TimeTaker::stop(bool quiet)
39 {
40         if(m_running)
41         {
42                 u32 time2 = getTimeMs();
43                 u32 dtime = time2 - m_time1;
44                 if(m_result != NULL)
45                 {
46                         (*m_result) += dtime;
47                 }
48                 else
49                 {
50                         if(quiet == false)
51                                 infostream<<m_name<<" took "<<dtime<<"ms"<<std::endl;
52                 }
53                 m_running = false;
54                 return dtime;
55         }
56         return 0;
57 }
58
59 u32 TimeTaker::getTime()
60 {
61         u32 time2 = getTimeMs();
62         u32 dtime = time2 - m_time1;
63         return dtime;
64 }
65
66 const v3s16 g_6dirs[6] =
67 {
68         // +right, +top, +back
69         v3s16( 0, 0, 1), // back
70         v3s16( 0, 1, 0), // top
71         v3s16( 1, 0, 0), // right
72         v3s16( 0, 0,-1), // front
73         v3s16( 0,-1, 0), // bottom
74         v3s16(-1, 0, 0) // left
75 };
76
77 const v3s16 g_26dirs[26] =
78 {
79         // +right, +top, +back
80         v3s16( 0, 0, 1), // back
81         v3s16( 0, 1, 0), // top
82         v3s16( 1, 0, 0), // right
83         v3s16( 0, 0,-1), // front
84         v3s16( 0,-1, 0), // bottom
85         v3s16(-1, 0, 0), // left
86         // 6
87         v3s16(-1, 1, 0), // top left
88         v3s16( 1, 1, 0), // top right
89         v3s16( 0, 1, 1), // top back
90         v3s16( 0, 1,-1), // top front
91         v3s16(-1, 0, 1), // back left
92         v3s16( 1, 0, 1), // back right
93         v3s16(-1, 0,-1), // front left
94         v3s16( 1, 0,-1), // front right
95         v3s16(-1,-1, 0), // bottom left
96         v3s16( 1,-1, 0), // bottom right
97         v3s16( 0,-1, 1), // bottom back
98         v3s16( 0,-1,-1), // bottom front
99         // 18
100         v3s16(-1, 1, 1), // top back-left
101         v3s16( 1, 1, 1), // top back-right
102         v3s16(-1, 1,-1), // top front-left
103         v3s16( 1, 1,-1), // top front-right
104         v3s16(-1,-1, 1), // bottom back-left
105         v3s16( 1,-1, 1), // bottom back-right
106         v3s16(-1,-1,-1), // bottom front-left
107         v3s16( 1,-1,-1), // bottom front-right
108         // 26
109 };
110
111 const v3s16 g_27dirs[27] =
112 {
113         // +right, +top, +back
114         v3s16( 0, 0, 1), // back
115         v3s16( 0, 1, 0), // top
116         v3s16( 1, 0, 0), // right
117         v3s16( 0, 0,-1), // front
118         v3s16( 0,-1, 0), // bottom
119         v3s16(-1, 0, 0), // left
120         // 6
121         v3s16(-1, 1, 0), // top left
122         v3s16( 1, 1, 0), // top right
123         v3s16( 0, 1, 1), // top back
124         v3s16( 0, 1,-1), // top front
125         v3s16(-1, 0, 1), // back left
126         v3s16( 1, 0, 1), // back right
127         v3s16(-1, 0,-1), // front left
128         v3s16( 1, 0,-1), // front right
129         v3s16(-1,-1, 0), // bottom left
130         v3s16( 1,-1, 0), // bottom right
131         v3s16( 0,-1, 1), // bottom back
132         v3s16( 0,-1,-1), // bottom front
133         // 18
134         v3s16(-1, 1, 1), // top back-left
135         v3s16( 1, 1, 1), // top back-right
136         v3s16(-1, 1,-1), // top front-left
137         v3s16( 1, 1,-1), // top front-right
138         v3s16(-1,-1, 1), // bottom back-left
139         v3s16( 1,-1, 1), // bottom back-right
140         v3s16(-1,-1,-1), // bottom front-left
141         v3s16( 1,-1,-1), // bottom front-right
142         // 26
143         v3s16(0,0,0),
144 };
145
146 static unsigned long next = 1;
147
148 /* RAND_MAX assumed to be 32767 */
149 int myrand(void)
150 {
151    next = next * 1103515245 + 12345;
152    return((unsigned)(next/65536) % 32768);
153 }
154
155 void mysrand(unsigned seed)
156 {
157    next = seed;
158 }
159
160 int myrand_range(int min, int max)
161 {
162         if(max-min > MYRAND_MAX)
163         {
164                 errorstream<<"WARNING: myrand_range: max-min > MYRAND_MAX"<<std::endl;
165                 assert(0);
166         }
167         if(min > max)
168         {
169                 assert(0);
170                 return max;
171         }
172         return (myrand()%(max-min+1))+min;
173 }
174
175 #ifndef SERVER
176 // Sets the color of all vertices in the mesh
177 void setMeshVerticesColor(scene::IMesh* mesh, video::SColor& color)
178 {
179         if(mesh == NULL)
180                 return;
181         
182         u16 mc = mesh->getMeshBufferCount();
183         for(u16 j=0; j<mc; j++)
184         {
185                 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
186                 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
187                 u16 vc = buf->getVertexCount();
188                 for(u16 i=0; i<vc; i++)
189                 {
190                         vertices[i].Color = color;
191                 }
192         }
193 }
194 #endif
195
196 /*
197         blockpos: position of block in block coordinates
198         camera_pos: position of camera in nodes
199         camera_dir: an unit vector pointing to camera direction
200         range: viewing range
201 */
202 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
203                 f32 camera_fov, f32 range, f32 *distance_ptr)
204 {
205         v3s16 blockpos_nodes = blockpos_b * MAP_BLOCKSIZE;
206         
207         // Block center position
208         v3f blockpos(
209                         ((float)blockpos_nodes.X + MAP_BLOCKSIZE/2) * BS,
210                         ((float)blockpos_nodes.Y + MAP_BLOCKSIZE/2) * BS,
211                         ((float)blockpos_nodes.Z + MAP_BLOCKSIZE/2) * BS
212         );
213
214         // Block position relative to camera
215         v3f blockpos_relative = blockpos - camera_pos;
216
217         // Distance in camera direction (+=front, -=back)
218         f32 dforward = blockpos_relative.dotProduct(camera_dir);
219
220         // Total distance
221         f32 d = blockpos_relative.getLength();
222
223         if(distance_ptr)
224                 *distance_ptr = d;
225         
226         // If block is very close, it is always in sight
227         if(d < 1.44*1.44*MAP_BLOCKSIZE*BS/2)
228                 return true;
229
230         // If block is far away, it's not in sight
231         if(d > range * BS)
232                 return false;
233
234         // Maximum radius of a block
235         f32 block_max_radius = 0.5*1.44*1.44*MAP_BLOCKSIZE*BS;
236         
237         // If block is (nearly) touching the camera, don't
238         // bother validating further (that is, render it anyway)
239         if(d < block_max_radius)
240                 return true;
241         
242         // Cosine of the angle between the camera direction
243         // and the block direction (camera_dir is an unit vector)
244         f32 cosangle = dforward / d;
245         
246         // Compensate for the size of the block
247         // (as the block has to be shown even if it's a bit off FOV)
248         // This is an estimate, plus an arbitary factor
249         cosangle += block_max_radius / d * 0.5;
250
251         // If block is not in the field of view, skip it
252         if(cosangle < cos(camera_fov / 2))
253                 return false;
254
255         return true;
256 }
257
258 // Get an sha-1 hash of the player's name combined with
259 // the password entered. That's what the server uses as
260 // their password. (Exception : if the password field is
261 // blank, we send a blank password - this is for backwards
262 // compatibility with password-less players).
263 std::string translatePassword(std::string playername, std::wstring password)
264 {
265         if(password.length() == 0)
266                 return "";
267
268         std::string slt = playername + wide_to_narrow(password);
269         SHA1 sha1;
270         sha1.addBytes(slt.c_str(), slt.length());
271         unsigned char *digest = sha1.getDigest();
272         std::string pwd = base64_encode(digest, 20);
273         free(digest);
274         return pwd;
275 }
276
277
278