]> git.lizzy.rs Git - dragonfireclient.git/blob - src/utility.h
All textures are are now searched first from the directory specified by the texture_p...
[dragonfireclient.git] / src / utility.h
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 #ifndef UTILITY_HEADER
21 #define UTILITY_HEADER
22
23 #include <iostream>
24 #include <fstream>
25 #include <string>
26 #include <sstream>
27 #include <vector>
28 #include <jthread.h>
29 #include <jmutex.h>
30 #include <jmutexautolock.h>
31
32 #include "common_irrlicht.h"
33 #include "debug.h"
34 #include "strfnd.h"
35 #include "exceptions.h"
36 #include "porting.h"
37
38 extern const v3s16 g_6dirs[6];
39
40 extern const v3s16 g_26dirs[26];
41
42 // 26th is (0,0,0)
43 extern const v3s16 g_27dirs[27];
44
45 inline void writeU64(u8 *data, u64 i)
46 {
47         data[0] = ((i>>56)&0xff);
48         data[1] = ((i>>48)&0xff);
49         data[2] = ((i>>40)&0xff);
50         data[3] = ((i>>32)&0xff);
51         data[4] = ((i>>24)&0xff);
52         data[5] = ((i>>16)&0xff);
53         data[6] = ((i>> 8)&0xff);
54         data[7] = ((i>> 0)&0xff);
55 }
56
57 inline void writeU32(u8 *data, u32 i)
58 {
59         data[0] = ((i>>24)&0xff);
60         data[1] = ((i>>16)&0xff);
61         data[2] = ((i>> 8)&0xff);
62         data[3] = ((i>> 0)&0xff);
63 }
64
65 inline void writeU16(u8 *data, u16 i)
66 {
67         data[0] = ((i>> 8)&0xff);
68         data[1] = ((i>> 0)&0xff);
69 }
70
71 inline void writeU8(u8 *data, u8 i)
72 {
73         data[0] = ((i>> 0)&0xff);
74 }
75
76 inline u64 readU64(u8 *data)
77 {
78         return ((u64)data[0]<<56) | ((u64)data[1]<<48)
79                 | ((u64)data[2]<<40) | ((u64)data[3]<<32)
80                 | ((u64)data[4]<<24) | ((u64)data[5]<<16)
81                 | ((u64)data[6]<<8) | ((u64)data[7]<<0);
82 }
83
84 inline u32 readU32(u8 *data)
85 {
86         return (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | (data[3]<<0);
87 }
88
89 inline u16 readU16(u8 *data)
90 {
91         return (data[0]<<8) | (data[1]<<0);
92 }
93
94 inline u8 readU8(u8 *data)
95 {
96         return (data[0]<<0);
97 }
98
99 inline void writeS32(u8 *data, s32 i){
100         writeU32(data, (u32)i);
101 }
102 inline s32 readS32(u8 *data){
103         return (s32)readU32(data);
104 }
105
106 inline void writeF1000(u8 *data, f32 i){
107         writeS32(data, i*1000);
108 }
109 inline f32 readF1000(u8 *data){
110         return (f32)readS32(data)/1000.;
111 }
112
113 inline void writeS16(u8 *data, s16 i){
114         writeU16(data, (u16)i);
115 }
116 inline s16 readS16(u8 *data){
117         return (s16)readU16(data);
118 }
119
120 inline void writeV3S32(u8 *data, v3s32 p)
121 {
122         writeS32(&data[0], p.X);
123         writeS32(&data[4], p.Y);
124         writeS32(&data[8], p.Z);
125 }
126 inline v3s32 readV3S32(u8 *data)
127 {
128         v3s32 p;
129         p.X = readS32(&data[0]);
130         p.Y = readS32(&data[4]);
131         p.Z = readS32(&data[8]);
132         return p;
133 }
134
135 inline void writeV3F1000(u8 *data, v3f p)
136 {
137         writeF1000(&data[0], p.X);
138         writeF1000(&data[4], p.Y);
139         writeF1000(&data[8], p.Z);
140 }
141 inline v3f readV3F1000(u8 *data)
142 {
143         v3f p;
144         p.X = (float)readF1000(&data[0]);
145         p.Y = (float)readF1000(&data[4]);
146         p.Z = (float)readF1000(&data[8]);
147         return p;
148 }
149
150 inline void writeV2S16(u8 *data, v2s16 p)
151 {
152         writeS16(&data[0], p.X);
153         writeS16(&data[2], p.Y);
154 }
155
156 inline v2s16 readV2S16(u8 *data)
157 {
158         v2s16 p;
159         p.X = readS16(&data[0]);
160         p.Y = readS16(&data[2]);
161         return p;
162 }
163
164 inline void writeV2S32(u8 *data, v2s32 p)
165 {
166         writeS32(&data[0], p.X);
167         writeS32(&data[2], p.Y);
168 }
169
170 inline v2s32 readV2S32(u8 *data)
171 {
172         v2s32 p;
173         p.X = readS32(&data[0]);
174         p.Y = readS32(&data[2]);
175         return p;
176 }
177
178 inline void writeV3S16(u8 *data, v3s16 p)
179 {
180         writeS16(&data[0], p.X);
181         writeS16(&data[2], p.Y);
182         writeS16(&data[4], p.Z);
183 }
184
185 inline v3s16 readV3S16(u8 *data)
186 {
187         v3s16 p;
188         p.X = readS16(&data[0]);
189         p.Y = readS16(&data[2]);
190         p.Z = readS16(&data[4]);
191         return p;
192 }
193
194 /*
195         The above stuff directly interfaced to iostream
196 */
197
198 inline void writeU8(std::ostream &os, u8 p)
199 {
200         char buf[1];
201         writeU8((u8*)buf, p);
202         os.write(buf, 1);
203 }
204 inline u8 readU8(std::istream &is)
205 {
206         char buf[1];
207         is.read(buf, 1);
208         return readU8((u8*)buf);
209 }
210
211 inline void writeU16(std::ostream &os, u16 p)
212 {
213         char buf[2];
214         writeU16((u8*)buf, p);
215         os.write(buf, 2);
216 }
217 inline u16 readU16(std::istream &is)
218 {
219         char buf[2];
220         is.read(buf, 2);
221         return readU16((u8*)buf);
222 }
223
224 inline void writeF1000(std::ostream &os, f32 p)
225 {
226         char buf[2];
227         writeF1000((u8*)buf, p);
228         os.write(buf, 2);
229 }
230 inline f32 readF1000(std::istream &is)
231 {
232         char buf[2];
233         is.read(buf, 2);
234         return readF1000((u8*)buf);
235 }
236
237 inline void writeV3F1000(std::ostream &os, v3f p)
238 {
239         char buf[12];
240         writeV3F1000((u8*)buf, p);
241         os.write(buf, 12);
242 }
243 inline v3f readV3F1000(std::istream &is)
244 {
245         char buf[12];
246         is.read(buf, 12);
247         return readV3F1000((u8*)buf);
248 }
249
250 /*
251         None of these are used at the moment
252 */
253
254 template <typename T>
255 class SharedPtr
256 {
257 public:
258         SharedPtr(T *t=NULL)
259         {
260                 refcount = new int;
261                 *refcount = 1;
262                 ptr = t;
263         }
264         SharedPtr(SharedPtr<T> &t)
265         {
266                 //*this = t;
267                 drop();
268                 refcount = t.refcount;
269                 (*refcount)++;
270                 ptr = t.ptr;
271         }
272         ~SharedPtr()
273         {
274                 drop();
275         }
276         SharedPtr<T> & operator=(T *t)
277         {
278                 drop();
279                 refcount = new int;
280                 *refcount = 1;
281                 ptr = t;
282                 return *this;
283         }
284         SharedPtr<T> & operator=(SharedPtr<T> &t)
285         {
286                 drop();
287                 refcount = t.refcount;
288                 (*refcount)++;
289                 ptr = t.ptr;
290                 return *this;
291         }
292         T* operator->()
293         {
294                 return ptr;
295         }
296         T & operator*()
297         {
298                 return *ptr;
299         }
300         bool operator!=(T *t)
301         {
302                 return ptr != t;
303         }
304         bool operator==(T *t)
305         {
306                 return ptr == t;
307         }
308         T & operator[](unsigned int i)
309         {
310                 return ptr[i];
311         }
312 private:
313         void drop()
314         {
315                 assert((*refcount) > 0);
316                 (*refcount)--;
317                 if(*refcount == 0)
318                 {
319                         delete refcount;
320                         if(ptr != NULL)
321                                 delete ptr;
322                 }
323         }
324         T *ptr;
325         int *refcount;
326 };
327
328 template <typename T>
329 class Buffer
330 {
331 public:
332         Buffer(unsigned int size)
333         {
334                 m_size = size;
335                 data = new T[size];
336         }
337         Buffer(const Buffer &buffer)
338         {
339                 m_size = buffer.m_size;
340                 data = new T[buffer.m_size];
341                 memcpy(data, buffer.data, buffer.m_size);
342         }
343         Buffer(T *t, unsigned int size)
344         {
345                 m_size = size;
346                 data = new T[size];
347                 memcpy(data, t, size);
348         }
349         ~Buffer()
350         {
351                 delete[] data;
352         }
353         T & operator[](unsigned int i) const
354         {
355                 return data[i];
356         }
357         T * operator*() const
358         {
359                 return data;
360         }
361         unsigned int getSize() const
362         {
363                 return m_size;
364         }
365 private:
366         T *data;
367         unsigned int m_size;
368 };
369
370 template <typename T>
371 class SharedBuffer
372 {
373 public:
374         SharedBuffer(unsigned int size)
375         {
376                 m_size = size;
377                 data = new T[size];
378                 refcount = new unsigned int;
379                 (*refcount) = 1;
380         }
381         SharedBuffer(const SharedBuffer &buffer)
382         {
383                 //std::cout<<"SharedBuffer(const SharedBuffer &buffer)"<<std::endl;
384                 m_size = buffer.m_size;
385                 data = buffer.data;
386                 refcount = buffer.refcount;
387                 (*refcount)++;
388         }
389         SharedBuffer & operator=(const SharedBuffer & buffer)
390         {
391                 //std::cout<<"SharedBuffer & operator=(const SharedBuffer & buffer)"<<std::endl;
392                 if(this == &buffer)
393                         return *this;
394                 drop();
395                 m_size = buffer.m_size;
396                 data = buffer.data;
397                 refcount = buffer.refcount;
398                 (*refcount)++;
399                 return *this;
400         }
401         /*
402                 Copies whole buffer
403         */
404         SharedBuffer(T *t, unsigned int size)
405         {
406                 m_size = size;
407                 data = new T[size];
408                 memcpy(data, t, size);
409                 refcount = new unsigned int;
410                 (*refcount) = 1;
411         }
412         /*
413                 Copies whole buffer
414         */
415         SharedBuffer(const Buffer<T> &buffer)
416         {
417                 m_size = buffer.m_size;
418                 data = new T[buffer.getSize()];
419                 memcpy(data, *buffer, buffer.getSize());
420                 refcount = new unsigned int;
421                 (*refcount) = 1;
422         }
423         ~SharedBuffer()
424         {
425                 drop();
426         }
427         T & operator[](unsigned int i) const
428         {
429                 return data[i];
430         }
431         T * operator*() const
432         {
433                 return data;
434         }
435         unsigned int getSize() const
436         {
437                 return m_size;
438         }
439 private:
440         void drop()
441         {
442                 assert((*refcount) > 0);
443                 (*refcount)--;
444                 if(*refcount == 0)
445                 {
446                         delete[] data;
447                         delete refcount;
448                 }
449         }
450         T *data;
451         unsigned int m_size;
452         unsigned int *refcount;
453 };
454
455 inline SharedBuffer<u8> SharedBufferFromString(const char *string)
456 {
457         SharedBuffer<u8> b((u8*)string, strlen(string)+1);
458         return b;
459 }
460
461 template<typename T>
462 class MutexedVariable
463 {
464 public:
465         MutexedVariable(T value):
466                 m_value(value)
467         {
468                 m_mutex.Init();
469         }
470
471         T get()
472         {
473                 JMutexAutoLock lock(m_mutex);
474                 return m_value;
475         }
476
477         void set(T value)
478         {
479                 JMutexAutoLock lock(m_mutex);
480                 m_value = value;
481         }
482         
483         // You'll want to grab this in a SharedPtr
484         JMutexAutoLock * getLock()
485         {
486                 return new JMutexAutoLock(m_mutex);
487         }
488         
489         // You pretty surely want to grab the lock when accessing this
490         T m_value;
491
492 private:
493         JMutex m_mutex;
494 };
495
496 /*
497         TimeTaker
498 */
499
500 class TimeTaker
501 {
502 public:
503         TimeTaker(const char *name, u32 *result=NULL);
504
505         ~TimeTaker()
506         {
507                 stop();
508         }
509
510         u32 stop(bool quiet=false);
511
512         u32 getTime();
513
514 private:
515         const char *m_name;
516         u32 m_time1;
517         bool m_running;
518         u32 *m_result;
519 };
520
521 // Calculates the borders of a "d-radius" cube
522 inline void getFacePositions(core::list<v3s16> &list, u16 d)
523 {
524         if(d == 0)
525         {
526                 list.push_back(v3s16(0,0,0));
527                 return;
528         }
529         if(d == 1)
530         {
531                 /*
532                         This is an optimized sequence of coordinates.
533                 */
534                 list.push_back(v3s16( 0, 1, 0)); // top
535                 list.push_back(v3s16( 0, 0, 1)); // back
536                 list.push_back(v3s16(-1, 0, 0)); // left
537                 list.push_back(v3s16( 1, 0, 0)); // right
538                 list.push_back(v3s16( 0, 0,-1)); // front
539                 list.push_back(v3s16( 0,-1, 0)); // bottom
540                 // 6
541                 list.push_back(v3s16(-1, 0, 1)); // back left
542                 list.push_back(v3s16( 1, 0, 1)); // back right
543                 list.push_back(v3s16(-1, 0,-1)); // front left
544                 list.push_back(v3s16( 1, 0,-1)); // front right
545                 list.push_back(v3s16(-1,-1, 0)); // bottom left
546                 list.push_back(v3s16( 1,-1, 0)); // bottom right
547                 list.push_back(v3s16( 0,-1, 1)); // bottom back
548                 list.push_back(v3s16( 0,-1,-1)); // bottom front
549                 list.push_back(v3s16(-1, 1, 0)); // top left
550                 list.push_back(v3s16( 1, 1, 0)); // top right
551                 list.push_back(v3s16( 0, 1, 1)); // top back
552                 list.push_back(v3s16( 0, 1,-1)); // top front
553                 // 18
554                 list.push_back(v3s16(-1, 1, 1)); // top back-left
555                 list.push_back(v3s16( 1, 1, 1)); // top back-right
556                 list.push_back(v3s16(-1, 1,-1)); // top front-left
557                 list.push_back(v3s16( 1, 1,-1)); // top front-right
558                 list.push_back(v3s16(-1,-1, 1)); // bottom back-left
559                 list.push_back(v3s16( 1,-1, 1)); // bottom back-right
560                 list.push_back(v3s16(-1,-1,-1)); // bottom front-left
561                 list.push_back(v3s16( 1,-1,-1)); // bottom front-right
562                 // 26
563                 return;
564         }
565
566         // Take blocks in all sides, starting from y=0 and going +-y
567         for(s16 y=0; y<=d-1; y++)
568         {
569                 // Left and right side, including borders
570                 for(s16 z=-d; z<=d; z++)
571                 {
572                         list.push_back(v3s16(d,y,z));
573                         list.push_back(v3s16(-d,y,z));
574                         if(y != 0)
575                         {
576                                 list.push_back(v3s16(d,-y,z));
577                                 list.push_back(v3s16(-d,-y,z));
578                         }
579                 }
580                 // Back and front side, excluding borders
581                 for(s16 x=-d+1; x<=d-1; x++)
582                 {
583                         list.push_back(v3s16(x,y,d));
584                         list.push_back(v3s16(x,y,-d));
585                         if(y != 0)
586                         {
587                                 list.push_back(v3s16(x,-y,d));
588                                 list.push_back(v3s16(x,-y,-d));
589                         }
590                 }
591         }
592
593         // Take the bottom and top face with borders
594         // -d<x<d, y=+-d, -d<z<d
595         for(s16 x=-d; x<=d; x++)
596         for(s16 z=-d; z<=d; z++)
597         {
598                 list.push_back(v3s16(x,-d,z));
599                 list.push_back(v3s16(x,d,z));
600         }
601 }
602
603 class IndentationRaiser
604 {
605 public:
606         IndentationRaiser(u16 *indentation)
607         {
608                 m_indentation = indentation;
609                 (*m_indentation)++;
610         }
611         ~IndentationRaiser()
612         {
613                 (*m_indentation)--;
614         }
615 private:
616         u16 *m_indentation;
617 };
618
619 inline s16 getContainerPos(s16 p, s16 d)
620 {
621         return (p>=0 ? p : p-d+1) / d;
622 }
623
624 inline v2s16 getContainerPos(v2s16 p, s16 d)
625 {
626         return v2s16(
627                 getContainerPos(p.X, d),
628                 getContainerPos(p.Y, d)
629         );
630 }
631
632 inline v3s16 getContainerPos(v3s16 p, s16 d)
633 {
634         return v3s16(
635                 getContainerPos(p.X, d),
636                 getContainerPos(p.Y, d),
637                 getContainerPos(p.Z, d)
638         );
639 }
640
641 inline v2s16 getContainerPos(v2s16 p, v2s16 d)
642 {
643         return v2s16(
644                 getContainerPos(p.X, d.X),
645                 getContainerPos(p.Y, d.Y)
646         );
647 }
648
649 inline v3s16 getContainerPos(v3s16 p, v3s16 d)
650 {
651         return v3s16(
652                 getContainerPos(p.X, d.X),
653                 getContainerPos(p.Y, d.Y),
654                 getContainerPos(p.Z, d.Z)
655         );
656 }
657
658 inline bool isInArea(v3s16 p, s16 d)
659 {
660         return (
661                 p.X >= 0 && p.X < d &&
662                 p.Y >= 0 && p.Y < d &&
663                 p.Z >= 0 && p.Z < d
664         );
665 }
666
667 inline bool isInArea(v2s16 p, s16 d)
668 {
669         return (
670                 p.X >= 0 && p.X < d &&
671                 p.Y >= 0 && p.Y < d
672         );
673 }
674
675 inline bool isInArea(v3s16 p, v3s16 d)
676 {
677         return (
678                 p.X >= 0 && p.X < d.X &&
679                 p.Y >= 0 && p.Y < d.Y &&
680                 p.Z >= 0 && p.Z < d.Z
681         );
682 }
683
684 inline s16 rangelim(s16 i, s16 max)
685 {
686         if(i < 0)
687                 return 0;
688         if(i > max)
689                 return max;
690         return i;
691 }
692
693 #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
694
695 inline v3s16 arealim(v3s16 p, s16 d)
696 {
697         if(p.X < 0)
698                 p.X = 0;
699         if(p.Y < 0)
700                 p.Y = 0;
701         if(p.Z < 0)
702                 p.Z = 0;
703         if(p.X > d-1)
704                 p.X = d-1;
705         if(p.Y > d-1)
706                 p.Y = d-1;
707         if(p.Z > d-1)
708                 p.Z = d-1;
709         return p;
710 }
711
712 inline std::wstring narrow_to_wide(const std::string& mbs)
713 {
714         size_t wcl = mbs.size();
715         Buffer<wchar_t> wcs(wcl+1);
716         size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
717         if(l == (size_t)(-1))
718                 return L"<invalid multibyte string>";
719         wcs[l] = 0;
720         return *wcs;
721 }
722
723 inline std::string wide_to_narrow(const std::wstring& wcs)
724 {
725         size_t mbl = wcs.size()*4;
726         SharedBuffer<char> mbs(mbl+1);
727         size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
728         if(l == (size_t)(-1))
729                 mbs[0] = 0;
730         else
731                 mbs[l] = 0;
732         return *mbs;
733 }
734
735 // Split a string using the given delimiter. Returns a vector containing
736 // the component parts.
737 inline std::vector<std::wstring> str_split(const std::wstring &str, wchar_t delimiter)
738 {
739         std::vector<std::wstring> parts;
740         std::wstringstream sstr(str);
741         std::wstring part;
742         while(std::getline(sstr, part, delimiter))
743                 parts.push_back(part);
744         return parts;
745 }
746
747
748 /*
749         See test.cpp for example cases.
750         wraps degrees to the range of -360...360
751         NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
752 */
753 inline float wrapDegrees(float f)
754 {
755         // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
756         // This results in
757         // 10, 720, -1, -361
758         int i = floor(f);
759         // 0, 2, 0, -1
760         int l = i / 360;
761         // NOTE: This would be used for wrapping to 0...360
762         // 0, 2, -1, -2
763         /*if(i < 0)
764                 l -= 1;*/
765         // 0, 720, 0, -360
766         int k = l * 360;
767         // 10, 0.5, -0.5, -0.5
768         f -= float(k);
769         return f;
770 }
771
772 inline std::string lowercase(const std::string &s)
773 {
774         std::string s2;
775         for(size_t i=0; i<s.size(); i++)
776         {
777                 char c = s[i];
778                 if(c >= 'A' && c <= 'Z')
779                         c -= 'A' - 'a';
780                 s2 += c;
781         }
782         return s2;
783 }
784
785 inline bool is_yes(const std::string &s)
786 {
787         std::string s2 = lowercase(trim(s));
788         if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
789                 return true;
790         return false;
791 }
792
793 inline s32 stoi(const std::string &s, s32 min, s32 max)
794 {
795         s32 i = atoi(s.c_str());
796         if(i < min)
797                 i = min;
798         if(i > max)
799                 i = max;
800         return i;
801 }
802
803
804 // MSVC2010 includes it's own versions of these
805 #if !defined(_MSC_VER) || _MSC_VER < 1600
806
807 inline s32 stoi(std::string s)
808 {
809         return atoi(s.c_str());
810 }
811
812 inline s32 stoi(std::wstring s)
813 {
814         return atoi(wide_to_narrow(s).c_str());
815 }
816
817 inline float stof(std::string s)
818 {
819         float f;
820         std::istringstream ss(s);
821         ss>>f;
822         return f;
823 }
824
825 #endif
826
827 inline std::string itos(s32 i)
828 {
829         std::ostringstream o;
830         o<<i;
831         return o.str();
832 }
833
834 inline std::string ftos(float f)
835 {
836         std::ostringstream o;
837         o<<f;
838         return o.str();
839 }
840
841 inline void str_replace(std::string & str, std::string const & pattern,
842                 std::string const & replacement)
843 {
844         std::string::size_type start = str.find(pattern, 0);
845         while(start != str.npos)
846         {
847                 str.replace(start, pattern.size(), replacement);
848                 start = str.find(pattern, start+replacement.size());
849         }
850 }
851
852 inline void str_replace_char(std::string & str, char from, char to)
853 {
854         for(unsigned int i=0; i<str.size(); i++)
855         {
856                 if(str[i] == from)
857                         str[i] = to;
858         }
859 }
860
861 /*
862         A base class for simple background thread implementation
863 */
864
865 class SimpleThread : public JThread
866 {
867         bool run;
868         JMutex run_mutex;
869
870 public:
871
872         SimpleThread():
873                 JThread(),
874                 run(true)
875         {
876                 run_mutex.Init();
877         }
878
879         virtual ~SimpleThread()
880         {}
881
882         virtual void * Thread() = 0;
883
884         bool getRun()
885         {
886                 JMutexAutoLock lock(run_mutex);
887                 return run;
888         }
889         void setRun(bool a_run)
890         {
891                 JMutexAutoLock lock(run_mutex);
892                 run = a_run;
893         }
894
895         void stop()
896         {
897                 setRun(false);
898                 while(IsRunning())
899                         sleep_ms(100);
900         }
901 };
902
903 /*
904         Config stuff
905 */
906
907 enum ValueType
908 {
909         VALUETYPE_STRING,
910         VALUETYPE_FLAG // Doesn't take any arguments
911 };
912
913 struct ValueSpec
914 {
915         ValueSpec(ValueType a_type, const char *a_help=NULL)
916         {
917                 type = a_type;
918                 help = a_help;
919         }
920         ValueType type;
921         const char *help;
922 };
923
924 class Settings
925 {
926 public:
927         Settings()
928         {
929                 m_mutex.Init();
930         }
931
932         void writeLines(std::ostream &os)
933         {
934                 JMutexAutoLock lock(m_mutex);
935                 
936                 for(core::map<std::string, std::string>::Iterator
937                                 i = m_settings.getIterator();
938                                 i.atEnd() == false; i++)
939                 {
940                         std::string name = i.getNode()->getKey();
941                         std::string value = i.getNode()->getValue();
942                         os<<name<<" = "<<value<<"\n";
943                 }
944         }
945
946         bool parseConfigLine(const std::string &line)
947         {
948                 JMutexAutoLock lock(m_mutex);
949                 
950                 std::string trimmedline = trim(line);
951                 
952                 // Ignore comments
953                 if(trimmedline[0] == '#')
954                         return true;
955
956                 //dstream<<"trimmedline=\""<<trimmedline<<"\""<<std::endl;
957
958                 Strfnd sf(trim(line));
959
960                 std::string name = sf.next("=");
961                 name = trim(name);
962
963                 if(name == "")
964                         return true;
965                 
966                 std::string value = sf.next("\n");
967                 value = trim(value);
968
969                 /*dstream<<"Config name=\""<<name<<"\" value=\""
970                                 <<value<<"\""<<std::endl;*/
971                 
972                 m_settings[name] = value;
973                 
974                 return true;
975         }
976
977         // Returns false on EOF
978         bool parseConfigObject(std::istream &is)
979         {
980                 if(is.eof())
981                         return false;
982                 
983                 /*
984                         NOTE: This function might be expanded to allow multi-line
985                               settings.
986                 */
987                 std::string line;
988                 std::getline(is, line);
989                 //dstream<<"got line: \""<<line<<"\""<<std::endl;
990
991                 return parseConfigLine(line);
992         }
993
994         /*
995                 Read configuration file
996
997                 Returns true on success
998         */
999         bool readConfigFile(const char *filename)
1000         {
1001                 std::ifstream is(filename);
1002                 if(is.good() == false)
1003                 {
1004                         dstream<<"Error opening configuration file \""
1005                                         <<filename<<"\""<<std::endl;
1006                         return false;
1007                 }
1008
1009                 dstream<<"Parsing configuration file: \""
1010                                 <<filename<<"\""<<std::endl;
1011                                 
1012                 while(parseConfigObject(is));
1013                 
1014                 return true;
1015         }
1016
1017         /*
1018                 Reads a configuration object from stream (usually a single line)
1019                 and adds it to dst.
1020                 
1021                 Preserves comments and empty lines.
1022
1023                 Settings that were added to dst are also added to updated.
1024                 key of updated is setting name, value of updated is dummy.
1025
1026                 Returns false on EOF
1027         */
1028         bool getUpdatedConfigObject(std::istream &is,
1029                         core::list<std::string> &dst,
1030                         core::map<std::string, bool> &updated)
1031         {
1032                 JMutexAutoLock lock(m_mutex);
1033                 
1034                 if(is.eof())
1035                         return false;
1036                 
1037                 // NOTE: This function will be expanded to allow multi-line settings
1038                 std::string line;
1039                 std::getline(is, line);
1040
1041                 std::string trimmedline = trim(line);
1042
1043                 std::string line_end = "";
1044                 if(is.eof() == false)
1045                         line_end = "\n";
1046                 
1047                 // Ignore comments
1048                 if(trimmedline[0] == '#')
1049                 {
1050                         dst.push_back(line+line_end);
1051                         return true;
1052                 }
1053
1054                 Strfnd sf(trim(line));
1055
1056                 std::string name = sf.next("=");
1057                 name = trim(name);
1058
1059                 if(name == "")
1060                 {
1061                         dst.push_back(line+line_end);
1062                         return true;
1063                 }
1064                 
1065                 std::string value = sf.next("\n");
1066                 value = trim(value);
1067                 
1068                 if(m_settings.find(name))
1069                 {
1070                         std::string newvalue = m_settings[name];
1071                         
1072                         if(newvalue != value)
1073                         {
1074                                 dstream<<"Changing value of \""<<name<<"\" = \""
1075                                                 <<value<<"\" -> \""<<newvalue<<"\""
1076                                                 <<std::endl;
1077                         }
1078
1079                         dst.push_back(name + " = " + newvalue + line_end);
1080
1081                         updated[name] = true;
1082                 }
1083                 
1084                 return true;
1085         }
1086
1087         /*
1088                 Updates configuration file
1089
1090                 Returns true on success
1091         */
1092         bool updateConfigFile(const char *filename)
1093         {
1094                 dstream<<"Updating configuration file: \""
1095                                 <<filename<<"\""<<std::endl;
1096                 
1097                 core::list<std::string> objects;
1098                 core::map<std::string, bool> updated;
1099                 
1100                 // Read and modify stuff
1101                 {
1102                         std::ifstream is(filename);
1103                         if(is.good() == false)
1104                         {
1105                                 dstream<<"INFO: updateConfigFile():"
1106                                                 " Error opening configuration file"
1107                                                 " for reading: \""
1108                                                 <<filename<<"\""<<std::endl;
1109                         }
1110                         else
1111                         {
1112                                 while(getUpdatedConfigObject(is, objects, updated));
1113                         }
1114                 }
1115                 
1116                 JMutexAutoLock lock(m_mutex);
1117                 
1118                 // Write stuff back
1119                 {
1120                         std::ofstream os(filename);
1121                         if(os.good() == false)
1122                         {
1123                                 dstream<<"Error opening configuration file"
1124                                                 " for writing: \""
1125                                                 <<filename<<"\""<<std::endl;
1126                                 return false;
1127                         }
1128                         
1129                         /*
1130                                 Write updated stuff
1131                         */
1132                         for(core::list<std::string>::Iterator
1133                                         i = objects.begin();
1134                                         i != objects.end(); i++)
1135                         {
1136                                 os<<(*i);
1137                         }
1138
1139                         /*
1140                                 Write stuff that was not already in the file
1141                         */
1142                         for(core::map<std::string, std::string>::Iterator
1143                                         i = m_settings.getIterator();
1144                                         i.atEnd() == false; i++)
1145                         {
1146                                 if(updated.find(i.getNode()->getKey()))
1147                                         continue;
1148                                 std::string name = i.getNode()->getKey();
1149                                 std::string value = i.getNode()->getValue();
1150                                 dstream<<"Adding \""<<name<<"\" = \""<<value<<"\""
1151                                                 <<std::endl;
1152                                 os<<name<<" = "<<value<<"\n";
1153                         }
1154                 }
1155                 
1156                 return true;
1157         }
1158
1159         /*
1160                 NOTE: Types of allowed_options are ignored
1161
1162                 returns true on success
1163         */
1164         bool parseCommandLine(int argc, char *argv[],
1165                         core::map<std::string, ValueSpec> &allowed_options)
1166         {
1167                 int i=1;
1168                 for(;;)
1169                 {
1170                         if(i >= argc)
1171                                 break;
1172                         std::string argname = argv[i];
1173                         if(argname.substr(0, 2) != "--")
1174                         {
1175                                 dstream<<"Invalid command-line parameter \""
1176                                                 <<argname<<"\": --<option> expected."<<std::endl;
1177                                 return false;
1178                         }
1179                         i++;
1180
1181                         std::string name = argname.substr(2);
1182
1183                         core::map<std::string, ValueSpec>::Node *n;
1184                         n = allowed_options.find(name);
1185                         if(n == NULL)
1186                         {
1187                                 dstream<<"Unknown command-line parameter \""
1188                                                 <<argname<<"\""<<std::endl;
1189                                 return false;
1190                         }
1191
1192                         ValueType type = n->getValue().type;
1193
1194                         std::string value = "";
1195                         
1196                         if(type == VALUETYPE_FLAG)
1197                         {
1198                                 value = "true";
1199                         }
1200                         else
1201                         {
1202                                 if(i >= argc)
1203                                 {
1204                                         dstream<<"Invalid command-line parameter \""
1205                                                         <<name<<"\": missing value"<<std::endl;
1206                                         return false;
1207                                 }
1208                                 value = argv[i];
1209                                 i++;
1210                         }
1211                         
1212
1213                         dstream<<"Valid command-line parameter: \""
1214                                         <<name<<"\" = \""<<value<<"\""
1215                                         <<std::endl;
1216                         set(name, value);
1217                 }
1218
1219                 return true;
1220         }
1221
1222         void set(std::string name, std::string value)
1223         {
1224                 JMutexAutoLock lock(m_mutex);
1225                 
1226                 m_settings[name] = value;
1227         }
1228
1229         void setDefault(std::string name, std::string value)
1230         {
1231                 JMutexAutoLock lock(m_mutex);
1232                 
1233                 m_defaults[name] = value;
1234         }
1235
1236         bool exists(std::string name)
1237         {
1238                 JMutexAutoLock lock(m_mutex);
1239                 
1240                 return (m_settings.find(name) || m_defaults.find(name));
1241         }
1242
1243         std::string get(std::string name)
1244         {
1245                 JMutexAutoLock lock(m_mutex);
1246                 
1247                 core::map<std::string, std::string>::Node *n;
1248                 n = m_settings.find(name);
1249                 if(n == NULL)
1250                 {
1251                         n = m_defaults.find(name);
1252                         if(n == NULL)
1253                         {
1254                                 dstream<<"INFO: Settings: Setting not found: \""
1255                                                 <<name<<"\""<<std::endl;
1256                                 throw SettingNotFoundException("Setting not found");
1257                         }
1258                 }
1259
1260                 return n->getValue();
1261         }
1262
1263         bool getBool(std::string name)
1264         {
1265                 return is_yes(get(name));
1266         }
1267         
1268         bool getFlag(std::string name)
1269         {
1270                 try
1271                 {
1272                         return getBool(name);
1273                 }
1274                 catch(SettingNotFoundException &e)
1275                 {
1276                         return false;
1277                 }
1278         }
1279
1280         // Asks if empty
1281         bool getBoolAsk(std::string name, std::string question, bool def)
1282         {
1283                 // If it is in settings
1284                 if(exists(name))
1285                         return getBool(name);
1286                 
1287                 std::string s;
1288                 char templine[10];
1289                 std::cout<<question<<" [y/N]: ";
1290                 std::cin.getline(templine, 10);
1291                 s = templine;
1292
1293                 if(s == "")
1294                         return def;
1295
1296                 return is_yes(s);
1297         }
1298
1299         float getFloat(std::string name)
1300         {
1301                 return stof(get(name));
1302         }
1303
1304         u16 getU16(std::string name)
1305         {
1306                 return stoi(get(name), 0, 65535);
1307         }
1308
1309         u16 getU16Ask(std::string name, std::string question, u16 def)
1310         {
1311                 // If it is in settings
1312                 if(exists(name))
1313                         return getU16(name);
1314                 
1315                 std::string s;
1316                 char templine[10];
1317                 std::cout<<question<<" ["<<def<<"]: ";
1318                 std::cin.getline(templine, 10);
1319                 s = templine;
1320
1321                 if(s == "")
1322                         return def;
1323
1324                 return stoi(s, 0, 65535);
1325         }
1326
1327         s16 getS16(std::string name)
1328         {
1329                 return stoi(get(name), -32768, 32767);
1330         }
1331
1332         s32 getS32(std::string name)
1333         {
1334                 return stoi(get(name));
1335         }
1336
1337         v3f getV3F(std::string name)
1338         {
1339                 v3f value;
1340                 Strfnd f(get(name));
1341                 f.next("(");
1342                 value.X = stof(f.next(","));
1343                 value.Y = stof(f.next(","));
1344                 value.Z = stof(f.next(")"));
1345                 return value;
1346         }
1347
1348         u64 getU64(std::string name)
1349         {
1350                 u64 value = 0;
1351                 std::string s = get(name);
1352                 std::istringstream ss(s);
1353                 ss>>value;
1354                 return value;
1355         }
1356
1357         void setBool(std::string name, bool value)
1358         {
1359                 if(value)
1360                         set(name, "true");
1361                 else
1362                         set(name, "false");
1363         }
1364
1365         void setS32(std::string name, s32 value)
1366         {
1367                 set(name, itos(value));
1368         }
1369
1370         void setFloat(std::string name, float value)
1371         {
1372                 set(name, ftos(value));
1373         }
1374
1375         void setV3F(std::string name, v3f value)
1376         {
1377                 std::ostringstream os;
1378                 os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
1379                 set(name, os.str());
1380         }
1381
1382         void setU64(std::string name, u64 value)
1383         {
1384                 std::ostringstream os;
1385                 os<<value;
1386                 set(name, os.str());
1387         }
1388
1389         void clear()
1390         {
1391                 JMutexAutoLock lock(m_mutex);
1392                 
1393                 m_settings.clear();
1394                 m_defaults.clear();
1395         }
1396
1397         Settings & operator+=(Settings &other)
1398         {
1399                 JMutexAutoLock lock(m_mutex);
1400                 JMutexAutoLock lock2(other.m_mutex);
1401                 
1402                 if(&other == this)
1403                         return *this;
1404
1405                 for(core::map<std::string, std::string>::Iterator
1406                                 i = other.m_settings.getIterator();
1407                                 i.atEnd() == false; i++)
1408                 {
1409                         m_settings.insert(i.getNode()->getKey(),
1410                                         i.getNode()->getValue());
1411                 }
1412                 
1413                 for(core::map<std::string, std::string>::Iterator
1414                                 i = other.m_defaults.getIterator();
1415                                 i.atEnd() == false; i++)
1416                 {
1417                         m_defaults.insert(i.getNode()->getKey(),
1418                                         i.getNode()->getValue());
1419                 }
1420
1421         }
1422
1423         Settings & operator=(Settings &other)
1424         {
1425                 JMutexAutoLock lock(m_mutex);
1426                 JMutexAutoLock lock2(other.m_mutex);
1427                 
1428                 if(&other == this)
1429                         return *this;
1430
1431                 clear();
1432                 (*this) += other;
1433                 
1434                 return *this;
1435         }
1436
1437 private:
1438         core::map<std::string, std::string> m_settings;
1439         core::map<std::string, std::string> m_defaults;
1440         // All methods that access m_settings/m_defaults directly should lock this.
1441         JMutex m_mutex;
1442 };
1443
1444 /*
1445         FIFO queue (well, actually a FILO also)
1446 */
1447 template<typename T>
1448 class Queue
1449 {
1450 public:
1451         void push_back(T t)
1452         {
1453                 m_list.push_back(t);
1454         }
1455         
1456         T pop_front()
1457         {
1458                 if(m_list.size() == 0)
1459                         throw ItemNotFoundException("Queue: queue is empty");
1460
1461                 typename core::list<T>::Iterator begin = m_list.begin();
1462                 T t = *begin;
1463                 m_list.erase(begin);
1464                 return t;
1465         }
1466         T pop_back()
1467         {
1468                 if(m_list.size() == 0)
1469                         throw ItemNotFoundException("Queue: queue is empty");
1470
1471                 typename core::list<T>::Iterator last = m_list.getLast();
1472                 T t = *last;
1473                 m_list.erase(last);
1474                 return t;
1475         }
1476
1477         u32 size()
1478         {
1479                 return m_list.size();
1480         }
1481
1482 protected:
1483         core::list<T> m_list;
1484 };
1485
1486 /*
1487         Thread-safe FIFO queue (well, actually a FILO also)
1488 */
1489
1490 template<typename T>
1491 class MutexedQueue
1492 {
1493 public:
1494         MutexedQueue()
1495         {
1496                 m_mutex.Init();
1497         }
1498         u32 size()
1499         {
1500                 JMutexAutoLock lock(m_mutex);
1501                 return m_list.size();
1502         }
1503         void push_back(T t)
1504         {
1505                 JMutexAutoLock lock(m_mutex);
1506                 m_list.push_back(t);
1507         }
1508         T pop_front(u32 wait_time_max_ms=0)
1509         {
1510                 u32 wait_time_ms = 0;
1511
1512                 for(;;)
1513                 {
1514                         {
1515                                 JMutexAutoLock lock(m_mutex);
1516
1517                                 if(m_list.size() > 0)
1518                                 {
1519                                         typename core::list<T>::Iterator begin = m_list.begin();
1520                                         T t = *begin;
1521                                         m_list.erase(begin);
1522                                         return t;
1523                                 }
1524
1525                                 if(wait_time_ms >= wait_time_max_ms)
1526                                         throw ItemNotFoundException("MutexedQueue: queue is empty");
1527                         }
1528
1529                         // Wait a while before trying again
1530                         sleep_ms(10);
1531                         wait_time_ms += 10;
1532                 }
1533         }
1534         T pop_back(u32 wait_time_max_ms=0)
1535         {
1536                 u32 wait_time_ms = 0;
1537
1538                 for(;;)
1539                 {
1540                         {
1541                                 JMutexAutoLock lock(m_mutex);
1542
1543                                 if(m_list.size() > 0)
1544                                 {
1545                                         typename core::list<T>::Iterator last = m_list.getLast();
1546                                         T t = *last;
1547                                         m_list.erase(last);
1548                                         return t;
1549                                 }
1550
1551                                 if(wait_time_ms >= wait_time_max_ms)
1552                                         throw ItemNotFoundException("MutexedQueue: queue is empty");
1553                         }
1554
1555                         // Wait a while before trying again
1556                         sleep_ms(10);
1557                         wait_time_ms += 10;
1558                 }
1559         }
1560
1561         JMutex & getMutex()
1562         {
1563                 return m_mutex;
1564         }
1565
1566         core::list<T> & getList()
1567         {
1568                 return m_list;
1569         }
1570
1571 protected:
1572         JMutex m_mutex;
1573         core::list<T> m_list;
1574 };
1575
1576 /*
1577         A single worker thread - multiple client threads queue framework.
1578 */
1579
1580 template<typename Caller, typename Data>
1581 class CallerInfo
1582 {
1583 public:
1584         Caller caller;
1585         Data data;
1586 };
1587
1588 template<typename Key, typename T, typename Caller, typename CallerData>
1589 class GetResult
1590 {
1591 public:
1592         Key key;
1593         T item;
1594         core::list<CallerInfo<Caller, CallerData> > callers;
1595 };
1596
1597 template<typename Key, typename T, typename Caller, typename CallerData>
1598 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1599 {
1600 };
1601
1602 template<typename Key, typename T, typename Caller, typename CallerData>
1603 class GetRequest
1604 {
1605 public:
1606         GetRequest()
1607         {
1608                 dest = NULL;
1609         }
1610         GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1611         {
1612                 dest = a_dest;
1613         }
1614         GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1615                         Key a_key)
1616         {
1617                 dest = a_dest;
1618                 key = a_key;
1619         }
1620         ~GetRequest()
1621         {
1622         }
1623         
1624         Key key;
1625         ResultQueue<Key, T, Caller, CallerData> *dest;
1626         core::list<CallerInfo<Caller, CallerData> > callers;
1627 };
1628
1629 template<typename Key, typename T, typename Caller, typename CallerData>
1630 class RequestQueue
1631 {
1632 public:
1633         u32 size()
1634         {
1635                 return m_queue.size();
1636         }
1637
1638         void add(Key key, Caller caller, CallerData callerdata,
1639                         ResultQueue<Key, T, Caller, CallerData> *dest)
1640         {
1641                 JMutexAutoLock lock(m_queue.getMutex());
1642                 
1643                 /*
1644                         If the caller is already on the list, only update CallerData
1645                 */
1646                 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1647                                 i = m_queue.getList().begin();
1648                                 i != m_queue.getList().end(); i++)
1649                 {
1650                         GetRequest<Key, T, Caller, CallerData> &request = *i;
1651
1652                         if(request.key == key)
1653                         {
1654                                 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1655                                                 i = request.callers.begin();
1656                                                 i != request.callers.end(); i++)
1657                                 {
1658                                         CallerInfo<Caller, CallerData> &ca = *i;
1659                                         if(ca.caller == caller)
1660                                         {
1661                                                 ca.data = callerdata;
1662                                                 return;
1663                                         }
1664                                 }
1665                                 CallerInfo<Caller, CallerData> ca;
1666                                 ca.caller = caller;
1667                                 ca.data = callerdata;
1668                                 request.callers.push_back(ca);
1669                                 return;
1670                         }
1671                 }
1672
1673                 /*
1674                         Else add a new request to the queue
1675                 */
1676
1677                 GetRequest<Key, T, Caller, CallerData> request;
1678                 request.key = key;
1679                 CallerInfo<Caller, CallerData> ca;
1680                 ca.caller = caller;
1681                 ca.data = callerdata;
1682                 request.callers.push_back(ca);
1683                 request.dest = dest;
1684                 
1685                 m_queue.getList().push_back(request);
1686         }
1687
1688         GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1689         {
1690                 return m_queue.pop_front(wait_if_empty);
1691         }
1692
1693 private:
1694         MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1695 };
1696
1697 /*
1698         Pseudo-random (VC++ rand() sucks)
1699 */
1700 int myrand(void);
1701 void mysrand(unsigned seed);
1702 #define MYRAND_MAX 32767
1703
1704 inline int myrand_range(int min, int max)
1705 {
1706         if(min > max)
1707         {
1708                 assert(0);
1709                 return max;
1710         }
1711         return (myrand()%(max-min+1))+min;
1712 }
1713
1714 /*
1715         Miscellaneous functions
1716 */
1717
1718 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
1719                 f32 *distance_ptr=NULL);
1720
1721 /*
1722         Queue with unique values with fast checking of value existence
1723 */
1724
1725 template<typename Value>
1726 class UniqueQueue
1727 {
1728 public:
1729         
1730         /*
1731                 Does nothing if value is already queued.
1732                 Return value:
1733                         true: value added
1734                         false: value already exists
1735         */
1736         bool push_back(Value value)
1737         {
1738                 // Check if already exists
1739                 if(m_map.find(value) != NULL)
1740                         return false;
1741
1742                 // Add
1743                 m_map.insert(value, 0);
1744                 m_list.push_back(value);
1745                 
1746                 return true;
1747         }
1748
1749         Value pop_front()
1750         {
1751                 typename core::list<Value>::Iterator i = m_list.begin();
1752                 Value value = *i;
1753                 m_map.remove(value);
1754                 m_list.erase(i);
1755                 return value;
1756         }
1757
1758         u32 size()
1759         {
1760                 assert(m_list.size() == m_map.size());
1761                 return m_list.size();
1762         }
1763
1764 private:
1765         core::map<Value, u8> m_map;
1766         core::list<Value> m_list;
1767 };
1768
1769 #if 1
1770 template<typename Key, typename Value>
1771 class MutexedMap
1772 {
1773 public:
1774         MutexedMap()
1775         {
1776                 m_mutex.Init();
1777                 assert(m_mutex.IsInitialized());
1778         }
1779         
1780         void set(const Key &name, const Value &value)
1781         {
1782                 JMutexAutoLock lock(m_mutex);
1783
1784                 m_values[name] = value;
1785         }
1786         
1787         bool get(const Key &name, Value *result)
1788         {
1789                 JMutexAutoLock lock(m_mutex);
1790
1791                 typename core::map<Key, Value>::Node *n;
1792                 n = m_values.find(name);
1793
1794                 if(n == NULL)
1795                         return false;
1796                 
1797                 if(result != NULL)
1798                         *result = n->getValue();
1799                         
1800                 return true;
1801         }
1802
1803 private:
1804         core::map<Key, Value> m_values;
1805         JMutex m_mutex;
1806 };
1807 #endif
1808
1809 /*
1810         Generates ids for comparable values.
1811         Id=0 is reserved for "no value".
1812
1813         Is fast at:
1814         - Returning value by id (very fast)
1815         - Returning id by value
1816         - Generating a new id for a value
1817
1818         Is not able to:
1819         - Remove an id/value pair (is possible to implement but slow)
1820 */
1821 template<typename T>
1822 class MutexedIdGenerator
1823 {
1824 public:
1825         MutexedIdGenerator()
1826         {
1827                 m_mutex.Init();
1828                 assert(m_mutex.IsInitialized());
1829         }
1830         
1831         // Returns true if found
1832         bool getValue(u32 id, T &value)
1833         {
1834                 if(id == 0)
1835                         return false;
1836                 JMutexAutoLock lock(m_mutex);
1837                 if(m_id_to_value.size() < id)
1838                         return false;
1839                 value = m_id_to_value[id-1];
1840                 return true;
1841         }
1842         
1843         // If id exists for value, returns the id.
1844         // Otherwise generates an id for the value.
1845         u32 getId(const T &value)
1846         {
1847                 JMutexAutoLock lock(m_mutex);
1848                 typename core::map<T, u32>::Node *n;
1849                 n = m_value_to_id.find(value);
1850                 if(n != NULL)
1851                         return n->getValue();
1852                 m_id_to_value.push_back(value);
1853                 u32 new_id = m_id_to_value.size();
1854                 m_value_to_id.insert(value, new_id);
1855                 return new_id;
1856         }
1857
1858 private:
1859         JMutex m_mutex;
1860         // Values are stored here at id-1 position (id 1 = [0])
1861         core::array<T> m_id_to_value;
1862         core::map<T, u32> m_value_to_id;
1863 };
1864
1865 /*
1866         Checks if a string contains only supplied characters
1867 */
1868 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1869 {
1870         for(u32 i=0; i<s.size(); i++)
1871         {
1872                 bool confirmed = false;
1873                 for(u32 j=0; j<allowed_chars.size(); j++)
1874                 {
1875                         if(s[i] == allowed_chars[j])
1876                         {
1877                                 confirmed = true;
1878                                 break;
1879                         }
1880                 }
1881                 if(confirmed == false)
1882                         return false;
1883         }
1884         return true;
1885 }
1886
1887 /*
1888         Forcefully wraps string into rows using \n
1889         (no word wrap, used for showing paths in gui)
1890 */
1891 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1892 {
1893         std::string to;
1894         for(u32 i=0; i<from.size(); i++)
1895         {
1896                 if(i != 0 && i%rowlen == 0)
1897                         to += '\n';
1898                 to += from[i];
1899         }
1900         return to;
1901 }
1902
1903 /*
1904         Some helper stuff
1905 */
1906 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1907 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1908
1909 /*
1910         Returns integer position of node in given floating point position
1911 */
1912 inline v3s16 floatToInt(v3f p, f32 d)
1913 {
1914         v3s16 p2(
1915                 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1916                 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1917                 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1918         return p2;
1919 }
1920
1921 /*
1922         Returns floating point position of node in given integer position
1923 */
1924 inline v3f intToFloat(v3s16 p, f32 d)
1925 {
1926         v3f p2(
1927                 (f32)p.X * d,
1928                 (f32)p.Y * d,
1929                 (f32)p.Z * d
1930         );
1931         return p2;
1932 }
1933
1934 /*
1935         More serialization stuff
1936 */
1937
1938 // Creates a string with the length as the first two bytes
1939 inline std::string serializeString(const std::string &plain)
1940 {
1941         //assert(plain.size() <= 65535);
1942         if(plain.size() > 65535)
1943                 throw SerializationError("String too long for serializeString");
1944         char buf[2];
1945         writeU16((u8*)&buf[0], plain.size());
1946         std::string s;
1947         s.append(buf, 2);
1948         s.append(plain);
1949         return s;
1950 }
1951
1952 /*// Reads a string with the length as the first two bytes
1953 inline std::string deSerializeString(const std::string encoded)
1954 {
1955         u16 s_size = readU16((u8*)&encoded.c_str()[0]);
1956         if(s_size > encoded.length() - 2)
1957                 return "";
1958         std::string s;
1959         s.reserve(s_size);
1960         s.append(&encoded.c_str()[2], s_size);
1961         return s;
1962 }*/
1963
1964 // Reads a string with the length as the first two bytes
1965 inline std::string deSerializeString(std::istream &is)
1966 {
1967         char buf[2];
1968         is.read(buf, 2);
1969         if(is.gcount() != 2)
1970                 throw SerializationError("deSerializeString: size not read");
1971         u16 s_size = readU16((u8*)buf);
1972         if(s_size == 0)
1973                 return "";
1974         Buffer<char> buf2(s_size);
1975         is.read(&buf2[0], s_size);
1976         std::string s;
1977         s.reserve(s_size);
1978         s.append(&buf2[0], s_size);
1979         return s;
1980 }
1981
1982 // Creates a string with the length as the first four bytes
1983 inline std::string serializeLongString(const std::string &plain)
1984 {
1985         char buf[4];
1986         writeU32((u8*)&buf[0], plain.size());
1987         std::string s;
1988         s.append(buf, 4);
1989         s.append(plain);
1990         return s;
1991 }
1992
1993 /*// Reads a string with the length as the first four bytes
1994 inline std::string deSerializeLongString(const std::string encoded)
1995 {
1996         u32 s_size = readU32((u8*)&encoded.c_str()[0]);
1997         if(s_size > encoded.length() - 4)
1998                 return "";
1999         std::string s;
2000         s.reserve(s_size);
2001         s.append(&encoded.c_str()[4], s_size);
2002         return s;
2003 }*/
2004
2005 // Reads a string with the length as the first four bytes
2006 inline std::string deSerializeLongString(std::istream &is)
2007 {
2008         char buf[4];
2009         is.read(buf, 4);
2010         if(is.gcount() != 4)
2011                 throw SerializationError("deSerializeLongString: size not read");
2012         u32 s_size = readU32((u8*)buf);
2013         if(s_size == 0)
2014                 return "";
2015         Buffer<char> buf2(s_size);
2016         is.read(&buf2[0], s_size);
2017         std::string s;
2018         s.reserve(s_size);
2019         s.append(&buf2[0], s_size);
2020         return s;
2021 }
2022
2023 //
2024
2025 inline u32 time_to_daynight_ratio(u32 time_of_day)
2026 {
2027         const s32 daylength = 16;
2028         const s32 nightlength = 6;
2029         const s32 daytimelength = 8;
2030         s32 d = daylength;
2031         s32 t = (((time_of_day)%24000)/(24000/d));
2032         if(t < nightlength/2 || t >= d - nightlength/2)
2033                 //return 300;
2034                 return 350;
2035         else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
2036                 return 1000;
2037         else
2038                 return 750;
2039 }
2040
2041 // Random helper. Usually d=BS
2042 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
2043 {
2044         return core::aabbox3d<f32>(
2045                 (float)p.X * d - 0.5*d,
2046                 (float)p.Y * d - 0.5*d,
2047                 (float)p.Z * d - 0.5*d,
2048                 (float)p.X * d + 0.5*d,
2049                 (float)p.Y * d + 0.5*d,
2050                 (float)p.Z * d + 0.5*d
2051         );
2052 }
2053         
2054 class IntervalLimiter
2055 {
2056 public:
2057         IntervalLimiter():
2058                 m_accumulator(0)
2059         {
2060         }
2061         /*
2062                 dtime: time from last call to this method
2063                 wanted_interval: interval wanted
2064                 return value:
2065                         true: action should be skipped
2066                         false: action should be done
2067         */
2068         bool step(float dtime, float wanted_interval)
2069         {
2070                 m_accumulator += dtime;
2071                 if(m_accumulator < wanted_interval)
2072                         return false;
2073                 m_accumulator -= wanted_interval;
2074                 return true;
2075         }
2076 protected:
2077         float m_accumulator;
2078 };
2079
2080
2081 #endif
2082