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