]> git.lizzy.rs Git - dragonfireclient.git/blob - src/utility.h
19946354c1eb6fcb280dde7cd12776e310832bf5
[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[12];
219         is.read(buf, 12);
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[12];
232         is.read(buf, 12);
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 IrrlichtWrapper;
500
501 class TimeTaker
502 {
503 public:
504         TimeTaker(const char *name, u32 *result=NULL);
505
506         ~TimeTaker()
507         {
508                 stop();
509         }
510
511         u32 stop(bool quiet=false);
512
513         u32 getTime();
514
515 private:
516         const char *m_name;
517         u32 m_time1;
518         bool m_running;
519         u32 *m_result;
520 };
521
522 // Calculates the borders of a "d-radius" cube
523 inline void getFacePositions(core::list<v3s16> &list, u16 d)
524 {
525         if(d == 0)
526         {
527                 list.push_back(v3s16(0,0,0));
528                 return;
529         }
530         if(d == 1)
531         {
532                 /*
533                         This is an optimized sequence of coordinates.
534                 */
535                 list.push_back(v3s16( 0, 1, 0)); // top
536                 list.push_back(v3s16( 0, 0, 1)); // back
537                 list.push_back(v3s16(-1, 0, 0)); // left
538                 list.push_back(v3s16( 1, 0, 0)); // right
539                 list.push_back(v3s16( 0, 0,-1)); // front
540                 list.push_back(v3s16( 0,-1, 0)); // bottom
541                 // 6
542                 list.push_back(v3s16(-1, 0, 1)); // back left
543                 list.push_back(v3s16( 1, 0, 1)); // back right
544                 list.push_back(v3s16(-1, 0,-1)); // front left
545                 list.push_back(v3s16( 1, 0,-1)); // front right
546                 list.push_back(v3s16(-1,-1, 0)); // bottom left
547                 list.push_back(v3s16( 1,-1, 0)); // bottom right
548                 list.push_back(v3s16( 0,-1, 1)); // bottom back
549                 list.push_back(v3s16( 0,-1,-1)); // bottom front
550                 list.push_back(v3s16(-1, 1, 0)); // top left
551                 list.push_back(v3s16( 1, 1, 0)); // top right
552                 list.push_back(v3s16( 0, 1, 1)); // top back
553                 list.push_back(v3s16( 0, 1,-1)); // top front
554                 // 18
555                 list.push_back(v3s16(-1, 1, 1)); // top back-left
556                 list.push_back(v3s16( 1, 1, 1)); // top back-right
557                 list.push_back(v3s16(-1, 1,-1)); // top front-left
558                 list.push_back(v3s16( 1, 1,-1)); // top front-right
559                 list.push_back(v3s16(-1,-1, 1)); // bottom back-left
560                 list.push_back(v3s16( 1,-1, 1)); // bottom back-right
561                 list.push_back(v3s16(-1,-1,-1)); // bottom front-left
562                 list.push_back(v3s16( 1,-1,-1)); // bottom front-right
563                 // 26
564                 return;
565         }
566
567         // Take blocks in all sides, starting from y=0 and going +-y
568         for(s16 y=0; y<=d-1; y++)
569         {
570                 // Left and right side, including borders
571                 for(s16 z=-d; z<=d; z++)
572                 {
573                         list.push_back(v3s16(d,y,z));
574                         list.push_back(v3s16(-d,y,z));
575                         if(y != 0)
576                         {
577                                 list.push_back(v3s16(d,-y,z));
578                                 list.push_back(v3s16(-d,-y,z));
579                         }
580                 }
581                 // Back and front side, excluding borders
582                 for(s16 x=-d+1; x<=d-1; x++)
583                 {
584                         list.push_back(v3s16(x,y,d));
585                         list.push_back(v3s16(x,y,-d));
586                         if(y != 0)
587                         {
588                                 list.push_back(v3s16(x,-y,d));
589                                 list.push_back(v3s16(x,-y,-d));
590                         }
591                 }
592         }
593
594         // Take the bottom and top face with borders
595         // -d<x<d, y=+-d, -d<z<d
596         for(s16 x=-d; x<=d; x++)
597         for(s16 z=-d; z<=d; z++)
598         {
599                 list.push_back(v3s16(x,-d,z));
600                 list.push_back(v3s16(x,d,z));
601         }
602 }
603
604 class IndentationRaiser
605 {
606 public:
607         IndentationRaiser(u16 *indentation)
608         {
609                 m_indentation = indentation;
610                 (*m_indentation)++;
611         }
612         ~IndentationRaiser()
613         {
614                 (*m_indentation)--;
615         }
616 private:
617         u16 *m_indentation;
618 };
619
620 inline s16 getContainerPos(s16 p, s16 d)
621 {
622         return (p>=0 ? p : p-d+1) / d;
623 }
624
625 inline v2s16 getContainerPos(v2s16 p, s16 d)
626 {
627         return v2s16(
628                 getContainerPos(p.X, d),
629                 getContainerPos(p.Y, d)
630         );
631 }
632
633 inline v3s16 getContainerPos(v3s16 p, s16 d)
634 {
635         return v3s16(
636                 getContainerPos(p.X, d),
637                 getContainerPos(p.Y, d),
638                 getContainerPos(p.Z, d)
639         );
640 }
641
642 inline v2s16 getContainerPos(v2s16 p, v2s16 d)
643 {
644         return v2s16(
645                 getContainerPos(p.X, d.X),
646                 getContainerPos(p.Y, d.Y)
647         );
648 }
649
650 inline v3s16 getContainerPos(v3s16 p, v3s16 d)
651 {
652         return v3s16(
653                 getContainerPos(p.X, d.X),
654                 getContainerPos(p.Y, d.Y),
655                 getContainerPos(p.Z, d.Z)
656         );
657 }
658
659 inline bool isInArea(v3s16 p, s16 d)
660 {
661         return (
662                 p.X >= 0 && p.X < d &&
663                 p.Y >= 0 && p.Y < d &&
664                 p.Z >= 0 && p.Z < d
665         );
666 }
667
668 inline bool isInArea(v2s16 p, s16 d)
669 {
670         return (
671                 p.X >= 0 && p.X < d &&
672                 p.Y >= 0 && p.Y < d
673         );
674 }
675
676 inline bool isInArea(v3s16 p, v3s16 d)
677 {
678         return (
679                 p.X >= 0 && p.X < d.X &&
680                 p.Y >= 0 && p.Y < d.Y &&
681                 p.Z >= 0 && p.Z < d.Z
682         );
683 }
684
685 inline s16 rangelim(s16 i, s16 max)
686 {
687         if(i < 0)
688                 return 0;
689         if(i > max)
690                 return max;
691         return i;
692 }
693
694 #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
695
696 inline v3s16 arealim(v3s16 p, s16 d)
697 {
698         if(p.X < 0)
699                 p.X = 0;
700         if(p.Y < 0)
701                 p.Y = 0;
702         if(p.Z < 0)
703                 p.Z = 0;
704         if(p.X > d-1)
705                 p.X = d-1;
706         if(p.Y > d-1)
707                 p.Y = d-1;
708         if(p.Z > d-1)
709                 p.Z = d-1;
710         return p;
711 }
712
713 inline std::wstring narrow_to_wide(const std::string& mbs)
714 {
715         size_t wcl = mbs.size();
716         Buffer<wchar_t> wcs(wcl+1);
717         size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
718         if(l == (size_t)(-1))
719                 return L"<invalid multibyte string>";
720         wcs[l] = 0;
721         return *wcs;
722 }
723
724 inline std::string wide_to_narrow(const std::wstring& wcs)
725 {
726         size_t mbl = wcs.size()*4;
727         SharedBuffer<char> mbs(mbl+1);
728         size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
729         if(l == (size_t)(-1))
730                 mbs[0] = 0;
731         else
732                 mbs[l] = 0;
733         return *mbs;
734 }
735
736 /*
737         See test.cpp for example cases.
738         wraps degrees to the range of -360...360
739         NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
740 */
741 inline float wrapDegrees(float f)
742 {
743         // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
744         // This results in
745         // 10, 720, -1, -361
746         int i = floor(f);
747         // 0, 2, 0, -1
748         int l = i / 360;
749         // NOTE: This would be used for wrapping to 0...360
750         // 0, 2, -1, -2
751         /*if(i < 0)
752                 l -= 1;*/
753         // 0, 720, 0, -360
754         int k = l * 360;
755         // 10, 0.5, -0.5, -0.5
756         f -= float(k);
757         return f;
758 }
759
760 inline std::string lowercase(const std::string &s)
761 {
762         std::string s2;
763         for(size_t i=0; i<s.size(); i++)
764         {
765                 char c = s[i];
766                 if(c >= 'A' && c <= 'Z')
767                         c -= 'A' - 'a';
768                 s2 += c;
769         }
770         return s2;
771 }
772
773 inline bool is_yes(const std::string &s)
774 {
775         std::string s2 = lowercase(trim(s));
776         if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
777                 return true;
778         return false;
779 }
780
781 inline s32 stoi(const std::string &s, s32 min, s32 max)
782 {
783         s32 i = atoi(s.c_str());
784         if(i < min)
785                 i = min;
786         if(i > max)
787                 i = max;
788         return i;
789 }
790
791 inline s32 stoi(std::string s)
792 {
793         return atoi(s.c_str());
794 }
795
796 inline float stof(std::string s)
797 {
798         float f;
799         std::istringstream ss(s);
800         ss>>f;
801         return f;
802 }
803
804 inline std::string itos(s32 i)
805 {
806         std::ostringstream o;
807         o<<i;
808         return o.str();
809 }
810
811 inline std::string ftos(float f)
812 {
813         std::ostringstream o;
814         o<<f;
815         return o.str();
816 }
817
818 inline void str_replace(std::string & str, std::string const & pattern,
819                 std::string const & replacement)
820 {
821         std::string::size_type start = str.find(pattern, 0);
822         while(start != str.npos)
823         {
824                 str.replace(start, pattern.size(), replacement);
825                 start = str.find(pattern, start+replacement.size());
826         }
827 }
828
829 inline void str_replace_char(std::string & str, char from, char to)
830 {
831         for(unsigned int i=0; i<str.size(); i++)
832         {
833                 if(str[i] == from)
834                         str[i] = to;
835         }
836 }
837
838 /*
839         A base class for simple background thread implementation
840 */
841
842 class SimpleThread : public JThread
843 {
844         bool run;
845         JMutex run_mutex;
846
847 public:
848
849         SimpleThread():
850                 JThread(),
851                 run(true)
852         {
853                 run_mutex.Init();
854         }
855
856         virtual ~SimpleThread()
857         {}
858
859         virtual void * Thread() = 0;
860
861         bool getRun()
862         {
863                 JMutexAutoLock lock(run_mutex);
864                 return run;
865         }
866         void setRun(bool a_run)
867         {
868                 JMutexAutoLock lock(run_mutex);
869                 run = a_run;
870         }
871
872         void stop()
873         {
874                 setRun(false);
875                 while(IsRunning())
876                         sleep_ms(100);
877         }
878 };
879
880 /*
881         Config stuff
882 */
883
884 enum ValueType
885 {
886         VALUETYPE_STRING,
887         VALUETYPE_FLAG // Doesn't take any arguments
888 };
889
890 struct ValueSpec
891 {
892         ValueSpec(ValueType a_type, const char *a_help=NULL)
893         {
894                 type = a_type;
895                 help = a_help;
896         }
897         ValueType type;
898         const char *help;
899 };
900
901 class Settings
902 {
903 public:
904         Settings()
905         {
906                 m_mutex.Init();
907         }
908
909         void writeLines(std::ostream &os)
910         {
911                 JMutexAutoLock lock(m_mutex);
912                 
913                 for(core::map<std::string, std::string>::Iterator
914                                 i = m_settings.getIterator();
915                                 i.atEnd() == false; i++)
916                 {
917                         std::string name = i.getNode()->getKey();
918                         std::string value = i.getNode()->getValue();
919                         os<<name<<" = "<<value<<"\n";
920                 }
921         }
922
923         bool parseConfigLine(const std::string &line)
924         {
925                 JMutexAutoLock lock(m_mutex);
926                 
927                 std::string trimmedline = trim(line);
928                 
929                 // Ignore comments
930                 if(trimmedline[0] == '#')
931                         return true;
932
933                 //dstream<<"trimmedline=\""<<trimmedline<<"\""<<std::endl;
934
935                 Strfnd sf(trim(line));
936
937                 std::string name = sf.next("=");
938                 name = trim(name);
939
940                 if(name == "")
941                         return true;
942                 
943                 std::string value = sf.next("\n");
944                 value = trim(value);
945
946                 /*dstream<<"Config name=\""<<name<<"\" value=\""
947                                 <<value<<"\""<<std::endl;*/
948                 
949                 m_settings[name] = value;
950                 
951                 return true;
952         }
953
954         // Returns false on EOF
955         bool parseConfigObject(std::istream &is)
956         {
957                 if(is.eof())
958                         return false;
959                 
960                 /*
961                         NOTE: This function might be expanded to allow multi-line
962                               settings.
963                 */
964                 std::string line;
965                 std::getline(is, line);
966                 //dstream<<"got line: \""<<line<<"\""<<std::endl;
967
968                 return parseConfigLine(line);
969         }
970
971         /*
972                 Read configuration file
973
974                 Returns true on success
975         */
976         bool readConfigFile(const char *filename)
977         {
978                 std::ifstream is(filename);
979                 if(is.good() == false)
980                 {
981                         dstream<<"Error opening configuration file \""
982                                         <<filename<<"\""<<std::endl;
983                         return false;
984                 }
985
986                 dstream<<"Parsing configuration file: \""
987                                 <<filename<<"\""<<std::endl;
988                                 
989                 while(parseConfigObject(is));
990                 
991                 return true;
992         }
993
994         /*
995                 Reads a configuration object from stream (usually a single line)
996                 and adds it to dst.
997                 
998                 Preserves comments and empty lines.
999
1000                 Settings that were added to dst are also added to updated.
1001                 key of updated is setting name, value of updated is dummy.
1002
1003                 Returns false on EOF
1004         */
1005         bool getUpdatedConfigObject(std::istream &is,
1006                         core::list<std::string> &dst,
1007                         core::map<std::string, bool> &updated)
1008         {
1009                 JMutexAutoLock lock(m_mutex);
1010                 
1011                 if(is.eof())
1012                         return false;
1013                 
1014                 // NOTE: This function will be expanded to allow multi-line settings
1015                 std::string line;
1016                 std::getline(is, line);
1017
1018                 std::string trimmedline = trim(line);
1019
1020                 std::string line_end = "";
1021                 if(is.eof() == false)
1022                         line_end = "\n";
1023                 
1024                 // Ignore comments
1025                 if(trimmedline[0] == '#')
1026                 {
1027                         dst.push_back(line+line_end);
1028                         return true;
1029                 }
1030
1031                 Strfnd sf(trim(line));
1032
1033                 std::string name = sf.next("=");
1034                 name = trim(name);
1035
1036                 if(name == "")
1037                 {
1038                         dst.push_back(line+line_end);
1039                         return true;
1040                 }
1041                 
1042                 std::string value = sf.next("\n");
1043                 value = trim(value);
1044                 
1045                 if(m_settings.find(name))
1046                 {
1047                         std::string newvalue = m_settings[name];
1048                         
1049                         if(newvalue != value)
1050                         {
1051                                 dstream<<"Changing value of \""<<name<<"\" = \""
1052                                                 <<value<<"\" -> \""<<newvalue<<"\""
1053                                                 <<std::endl;
1054                         }
1055
1056                         dst.push_back(name + " = " + newvalue + line_end);
1057
1058                         updated[name] = true;
1059                 }
1060                 
1061                 return true;
1062         }
1063
1064         /*
1065                 Updates configuration file
1066
1067                 Returns true on success
1068         */
1069         bool updateConfigFile(const char *filename)
1070         {
1071                 dstream<<"Updating configuration file: \""
1072                                 <<filename<<"\""<<std::endl;
1073                 
1074                 core::list<std::string> objects;
1075                 core::map<std::string, bool> updated;
1076                 
1077                 // Read and modify stuff
1078                 {
1079                         std::ifstream is(filename);
1080                         if(is.good() == false)
1081                         {
1082                                 dstream<<"INFO: updateConfigFile():"
1083                                                 " Error opening configuration file"
1084                                                 " for reading: \""
1085                                                 <<filename<<"\""<<std::endl;
1086                         }
1087                         else
1088                         {
1089                                 while(getUpdatedConfigObject(is, objects, updated));
1090                         }
1091                 }
1092                 
1093                 JMutexAutoLock lock(m_mutex);
1094                 
1095                 // Write stuff back
1096                 {
1097                         std::ofstream os(filename);
1098                         if(os.good() == false)
1099                         {
1100                                 dstream<<"Error opening configuration file"
1101                                                 " for writing: \""
1102                                                 <<filename<<"\""<<std::endl;
1103                                 return false;
1104                         }
1105                         
1106                         /*
1107                                 Write updated stuff
1108                         */
1109                         for(core::list<std::string>::Iterator
1110                                         i = objects.begin();
1111                                         i != objects.end(); i++)
1112                         {
1113                                 os<<(*i);
1114                         }
1115
1116                         /*
1117                                 Write stuff that was not already in the file
1118                         */
1119                         for(core::map<std::string, std::string>::Iterator
1120                                         i = m_settings.getIterator();
1121                                         i.atEnd() == false; i++)
1122                         {
1123                                 if(updated.find(i.getNode()->getKey()))
1124                                         continue;
1125                                 std::string name = i.getNode()->getKey();
1126                                 std::string value = i.getNode()->getValue();
1127                                 dstream<<"Adding \""<<name<<"\" = \""<<value<<"\""
1128                                                 <<std::endl;
1129                                 os<<name<<" = "<<value<<"\n";
1130                         }
1131                 }
1132                 
1133                 return true;
1134         }
1135
1136         /*
1137                 NOTE: Types of allowed_options are ignored
1138
1139                 returns true on success
1140         */
1141         bool parseCommandLine(int argc, char *argv[],
1142                         core::map<std::string, ValueSpec> &allowed_options)
1143         {
1144                 int i=1;
1145                 for(;;)
1146                 {
1147                         if(i >= argc)
1148                                 break;
1149                         std::string argname = argv[i];
1150                         if(argname.substr(0, 2) != "--")
1151                         {
1152                                 dstream<<"Invalid command-line parameter \""
1153                                                 <<argname<<"\": --<option> expected."<<std::endl;
1154                                 return false;
1155                         }
1156                         i++;
1157
1158                         std::string name = argname.substr(2);
1159
1160                         core::map<std::string, ValueSpec>::Node *n;
1161                         n = allowed_options.find(name);
1162                         if(n == NULL)
1163                         {
1164                                 dstream<<"Unknown command-line parameter \""
1165                                                 <<argname<<"\""<<std::endl;
1166                                 return false;
1167                         }
1168
1169                         ValueType type = n->getValue().type;
1170
1171                         std::string value = "";
1172                         
1173                         if(type == VALUETYPE_FLAG)
1174                         {
1175                                 value = "true";
1176                         }
1177                         else
1178                         {
1179                                 if(i >= argc)
1180                                 {
1181                                         dstream<<"Invalid command-line parameter \""
1182                                                         <<name<<"\": missing value"<<std::endl;
1183                                         return false;
1184                                 }
1185                                 value = argv[i];
1186                                 i++;
1187                         }
1188                         
1189
1190                         dstream<<"Valid command-line parameter: \""
1191                                         <<name<<"\" = \""<<value<<"\""
1192                                         <<std::endl;
1193                         set(name, value);
1194                 }
1195
1196                 return true;
1197         }
1198
1199         void set(std::string name, std::string value)
1200         {
1201                 JMutexAutoLock lock(m_mutex);
1202                 
1203                 m_settings[name] = value;
1204         }
1205
1206         void setDefault(std::string name, std::string value)
1207         {
1208                 JMutexAutoLock lock(m_mutex);
1209                 
1210                 m_defaults[name] = value;
1211         }
1212
1213         bool exists(std::string name)
1214         {
1215                 JMutexAutoLock lock(m_mutex);
1216                 
1217                 return (m_settings.find(name) || m_defaults.find(name));
1218         }
1219
1220         std::string get(std::string name)
1221         {
1222                 JMutexAutoLock lock(m_mutex);
1223                 
1224                 core::map<std::string, std::string>::Node *n;
1225                 n = m_settings.find(name);
1226                 if(n == NULL)
1227                 {
1228                         n = m_defaults.find(name);
1229                         if(n == NULL)
1230                         {
1231                                 dstream<<"INFO: Settings: Setting not found: \""
1232                                                 <<name<<"\""<<std::endl;
1233                                 throw SettingNotFoundException("Setting not found");
1234                         }
1235                 }
1236
1237                 return n->getValue();
1238         }
1239
1240         bool getBool(std::string name)
1241         {
1242                 return is_yes(get(name));
1243         }
1244         
1245         bool getFlag(std::string name)
1246         {
1247                 try
1248                 {
1249                         return getBool(name);
1250                 }
1251                 catch(SettingNotFoundException &e)
1252                 {
1253                         return false;
1254                 }
1255         }
1256
1257         // Asks if empty
1258         bool getBoolAsk(std::string name, std::string question, bool def)
1259         {
1260                 // If it is in settings
1261                 if(exists(name))
1262                         return getBool(name);
1263                 
1264                 std::string s;
1265                 char templine[10];
1266                 std::cout<<question<<" [y/N]: ";
1267                 std::cin.getline(templine, 10);
1268                 s = templine;
1269
1270                 if(s == "")
1271                         return def;
1272
1273                 return is_yes(s);
1274         }
1275
1276         float getFloat(std::string name)
1277         {
1278                 return stof(get(name));
1279         }
1280
1281         u16 getU16(std::string name)
1282         {
1283                 return stoi(get(name), 0, 65535);
1284         }
1285
1286         u16 getU16Ask(std::string name, std::string question, u16 def)
1287         {
1288                 // If it is in settings
1289                 if(exists(name))
1290                         return getU16(name);
1291                 
1292                 std::string s;
1293                 char templine[10];
1294                 std::cout<<question<<" ["<<def<<"]: ";
1295                 std::cin.getline(templine, 10);
1296                 s = templine;
1297
1298                 if(s == "")
1299                         return def;
1300
1301                 return stoi(s, 0, 65535);
1302         }
1303
1304         s16 getS16(std::string name)
1305         {
1306                 return stoi(get(name), -32768, 32767);
1307         }
1308
1309         s32 getS32(std::string name)
1310         {
1311                 return stoi(get(name));
1312         }
1313
1314         v3f getV3F(std::string name)
1315         {
1316                 v3f value;
1317                 Strfnd f(get(name));
1318                 f.next("(");
1319                 value.X = stof(f.next(","));
1320                 value.Y = stof(f.next(","));
1321                 value.Z = stof(f.next(")"));
1322                 return value;
1323         }
1324
1325         u64 getU64(std::string name)
1326         {
1327                 u64 value = 0;
1328                 std::string s = get(name);
1329                 std::istringstream ss(s);
1330                 ss>>value;
1331                 return value;
1332         }
1333
1334         void setS32(std::string name, s32 value)
1335         {
1336                 set(name, itos(value));
1337         }
1338
1339         void setFloat(std::string name, float value)
1340         {
1341                 set(name, ftos(value));
1342         }
1343
1344         void setV3F(std::string name, v3f value)
1345         {
1346                 std::ostringstream os;
1347                 os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
1348                 set(name, os.str());
1349         }
1350
1351         void setU64(std::string name, u64 value)
1352         {
1353                 std::ostringstream os;
1354                 os<<value;
1355                 set(name, os.str());
1356         }
1357
1358         void clear()
1359         {
1360                 JMutexAutoLock lock(m_mutex);
1361                 
1362                 m_settings.clear();
1363                 m_defaults.clear();
1364         }
1365
1366         Settings & operator+=(Settings &other)
1367         {
1368                 JMutexAutoLock lock(m_mutex);
1369                 JMutexAutoLock lock2(other.m_mutex);
1370                 
1371                 if(&other == this)
1372                         return *this;
1373
1374                 for(core::map<std::string, std::string>::Iterator
1375                                 i = other.m_settings.getIterator();
1376                                 i.atEnd() == false; i++)
1377                 {
1378                         m_settings.insert(i.getNode()->getKey(),
1379                                         i.getNode()->getValue());
1380                 }
1381                 
1382                 for(core::map<std::string, std::string>::Iterator
1383                                 i = other.m_defaults.getIterator();
1384                                 i.atEnd() == false; i++)
1385                 {
1386                         m_defaults.insert(i.getNode()->getKey(),
1387                                         i.getNode()->getValue());
1388                 }
1389
1390         }
1391
1392         Settings & operator=(Settings &other)
1393         {
1394                 JMutexAutoLock lock(m_mutex);
1395                 JMutexAutoLock lock2(other.m_mutex);
1396                 
1397                 if(&other == this)
1398                         return *this;
1399
1400                 clear();
1401                 (*this) += other;
1402                 
1403                 return *this;
1404         }
1405
1406 private:
1407         core::map<std::string, std::string> m_settings;
1408         core::map<std::string, std::string> m_defaults;
1409         // All methods that access m_settings/m_defaults directly should lock this.
1410         JMutex m_mutex;
1411 };
1412
1413 /*
1414         FIFO queue (well, actually a FILO also)
1415 */
1416 template<typename T>
1417 class Queue
1418 {
1419 public:
1420         void push_back(T t)
1421         {
1422                 m_list.push_back(t);
1423         }
1424         
1425         T pop_front()
1426         {
1427                 if(m_list.size() == 0)
1428                         throw ItemNotFoundException("Queue: queue is empty");
1429
1430                 typename core::list<T>::Iterator begin = m_list.begin();
1431                 T t = *begin;
1432                 m_list.erase(begin);
1433                 return t;
1434         }
1435         T pop_back()
1436         {
1437                 if(m_list.size() == 0)
1438                         throw ItemNotFoundException("Queue: queue is empty");
1439
1440                 typename core::list<T>::Iterator last = m_list.getLast();
1441                 T t = *last;
1442                 m_list.erase(last);
1443                 return t;
1444         }
1445
1446         u32 size()
1447         {
1448                 return m_list.size();
1449         }
1450
1451 protected:
1452         core::list<T> m_list;
1453 };
1454
1455 /*
1456         Thread-safe FIFO queue (well, actually a FILO also)
1457 */
1458
1459 template<typename T>
1460 class MutexedQueue
1461 {
1462 public:
1463         MutexedQueue()
1464         {
1465                 m_mutex.Init();
1466         }
1467         u32 size()
1468         {
1469                 JMutexAutoLock lock(m_mutex);
1470                 return m_list.size();
1471         }
1472         void push_back(T t)
1473         {
1474                 JMutexAutoLock lock(m_mutex);
1475                 m_list.push_back(t);
1476         }
1477         T pop_front(u32 wait_time_max_ms=0)
1478         {
1479                 u32 wait_time_ms = 0;
1480
1481                 for(;;)
1482                 {
1483                         {
1484                                 JMutexAutoLock lock(m_mutex);
1485
1486                                 if(m_list.size() > 0)
1487                                 {
1488                                         typename core::list<T>::Iterator begin = m_list.begin();
1489                                         T t = *begin;
1490                                         m_list.erase(begin);
1491                                         return t;
1492                                 }
1493
1494                                 if(wait_time_ms >= wait_time_max_ms)
1495                                         throw ItemNotFoundException("MutexedQueue: queue is empty");
1496                         }
1497
1498                         // Wait a while before trying again
1499                         sleep_ms(10);
1500                         wait_time_ms += 10;
1501                 }
1502         }
1503         T pop_back(u32 wait_time_max_ms=0)
1504         {
1505                 u32 wait_time_ms = 0;
1506
1507                 for(;;)
1508                 {
1509                         {
1510                                 JMutexAutoLock lock(m_mutex);
1511
1512                                 if(m_list.size() > 0)
1513                                 {
1514                                         typename core::list<T>::Iterator last = m_list.getLast();
1515                                         T t = *last;
1516                                         m_list.erase(last);
1517                                         return t;
1518                                 }
1519
1520                                 if(wait_time_ms >= wait_time_max_ms)
1521                                         throw ItemNotFoundException("MutexedQueue: queue is empty");
1522                         }
1523
1524                         // Wait a while before trying again
1525                         sleep_ms(10);
1526                         wait_time_ms += 10;
1527                 }
1528         }
1529
1530         JMutex & getMutex()
1531         {
1532                 return m_mutex;
1533         }
1534
1535         core::list<T> & getList()
1536         {
1537                 return m_list;
1538         }
1539
1540 protected:
1541         JMutex m_mutex;
1542         core::list<T> m_list;
1543 };
1544
1545 /*
1546         A single worker thread - multiple client threads queue framework.
1547 */
1548
1549 template<typename Caller, typename Data>
1550 class CallerInfo
1551 {
1552 public:
1553         Caller caller;
1554         Data data;
1555 };
1556
1557 template<typename Key, typename T, typename Caller, typename CallerData>
1558 class GetResult
1559 {
1560 public:
1561         Key key;
1562         T item;
1563         core::list<CallerInfo<Caller, CallerData> > callers;
1564 };
1565
1566 template<typename Key, typename T, typename Caller, typename CallerData>
1567 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1568 {
1569 };
1570
1571 template<typename Key, typename T, typename Caller, typename CallerData>
1572 class GetRequest
1573 {
1574 public:
1575         GetRequest()
1576         {
1577                 dest = NULL;
1578         }
1579         GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1580         {
1581                 dest = a_dest;
1582         }
1583         GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1584                         Key a_key)
1585         {
1586                 dest = a_dest;
1587                 key = a_key;
1588         }
1589         ~GetRequest()
1590         {
1591         }
1592         
1593         Key key;
1594         ResultQueue<Key, T, Caller, CallerData> *dest;
1595         core::list<CallerInfo<Caller, CallerData> > callers;
1596 };
1597
1598 template<typename Key, typename T, typename Caller, typename CallerData>
1599 class RequestQueue
1600 {
1601 public:
1602         u32 size()
1603         {
1604                 return m_queue.size();
1605         }
1606
1607         void add(Key key, Caller caller, CallerData callerdata,
1608                         ResultQueue<Key, T, Caller, CallerData> *dest)
1609         {
1610                 JMutexAutoLock lock(m_queue.getMutex());
1611                 
1612                 /*
1613                         If the caller is already on the list, only update CallerData
1614                 */
1615                 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1616                                 i = m_queue.getList().begin();
1617                                 i != m_queue.getList().end(); i++)
1618                 {
1619                         GetRequest<Key, T, Caller, CallerData> &request = *i;
1620
1621                         if(request.key == key)
1622                         {
1623                                 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1624                                                 i = request.callers.begin();
1625                                                 i != request.callers.end(); i++)
1626                                 {
1627                                         CallerInfo<Caller, CallerData> &ca = *i;
1628                                         if(ca.caller == caller)
1629                                         {
1630                                                 ca.data = callerdata;
1631                                                 return;
1632                                         }
1633                                 }
1634                                 CallerInfo<Caller, CallerData> ca;
1635                                 ca.caller = caller;
1636                                 ca.data = callerdata;
1637                                 request.callers.push_back(ca);
1638                                 return;
1639                         }
1640                 }
1641
1642                 /*
1643                         Else add a new request to the queue
1644                 */
1645
1646                 GetRequest<Key, T, Caller, CallerData> request;
1647                 request.key = key;
1648                 CallerInfo<Caller, CallerData> ca;
1649                 ca.caller = caller;
1650                 ca.data = callerdata;
1651                 request.callers.push_back(ca);
1652                 request.dest = dest;
1653                 
1654                 m_queue.getList().push_back(request);
1655         }
1656
1657         GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1658         {
1659                 return m_queue.pop_front(wait_if_empty);
1660         }
1661
1662 private:
1663         MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1664 };
1665
1666 /*
1667         Pseudo-random (VC++ rand() sucks)
1668 */
1669 int myrand(void);
1670 void mysrand(unsigned seed);
1671 #define MYRAND_MAX 32767
1672
1673 inline int myrand_range(int min, int max)
1674 {
1675         if(min > max)
1676         {
1677                 assert(0);
1678                 return max;
1679         }
1680         return (myrand()%(max-min+1))+min;
1681 }
1682
1683 /*
1684         Miscellaneous functions
1685 */
1686
1687 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
1688                 f32 *distance_ptr=NULL);
1689
1690 /*
1691         Queue with unique values with fast checking of value existence
1692 */
1693
1694 template<typename Value>
1695 class UniqueQueue
1696 {
1697 public:
1698         
1699         /*
1700                 Does nothing if value is already queued.
1701                 Return value:
1702                         true: value added
1703                         false: value already exists
1704         */
1705         bool push_back(Value value)
1706         {
1707                 // Check if already exists
1708                 if(m_map.find(value) != NULL)
1709                         return false;
1710
1711                 // Add
1712                 m_map.insert(value, 0);
1713                 m_list.push_back(value);
1714                 
1715                 return true;
1716         }
1717
1718         Value pop_front()
1719         {
1720                 typename core::list<Value>::Iterator i = m_list.begin();
1721                 Value value = *i;
1722                 m_map.remove(value);
1723                 m_list.erase(i);
1724                 return value;
1725         }
1726
1727         u32 size()
1728         {
1729                 assert(m_list.size() == m_map.size());
1730                 return m_list.size();
1731         }
1732
1733 private:
1734         core::map<Value, u8> m_map;
1735         core::list<Value> m_list;
1736 };
1737
1738 #if 0
1739 template<typename Key, typename Value>
1740 class MutexedCache
1741 {
1742 public:
1743         MutexedCache()
1744         {
1745                 m_mutex.Init();
1746                 assert(m_mutex.IsInitialized());
1747         }
1748         
1749         void set(const Key &name, const Value &value)
1750         {
1751                 JMutexAutoLock lock(m_mutex);
1752
1753                 m_values[name] = value;
1754         }
1755         
1756         bool get(const Key &name, Value *result)
1757         {
1758                 JMutexAutoLock lock(m_mutex);
1759
1760                 typename core::map<Key, Value>::Node *n;
1761                 n = m_values.find(name);
1762
1763                 if(n == NULL)
1764                         return false;
1765
1766                 *result = n->getValue();
1767                 return true;
1768         }
1769
1770 private:
1771         core::map<Key, Value> m_values;
1772         JMutex m_mutex;
1773 };
1774 #endif
1775
1776 /*
1777         Generates ids for comparable values.
1778         Id=0 is reserved for "no value".
1779
1780         Is fast at:
1781         - Returning value by id (very fast)
1782         - Returning id by value
1783         - Generating a new id for a value
1784
1785         Is not able to:
1786         - Remove an id/value pair (is possible to implement but slow)
1787 */
1788 template<typename T>
1789 class MutexedIdGenerator
1790 {
1791 public:
1792         MutexedIdGenerator()
1793         {
1794                 m_mutex.Init();
1795                 assert(m_mutex.IsInitialized());
1796         }
1797         
1798         // Returns true if found
1799         bool getValue(u32 id, T &value)
1800         {
1801                 if(id == 0)
1802                         return false;
1803                 JMutexAutoLock lock(m_mutex);
1804                 if(m_id_to_value.size() < id)
1805                         return false;
1806                 value = m_id_to_value[id-1];
1807                 return true;
1808         }
1809         
1810         // If id exists for value, returns the id.
1811         // Otherwise generates an id for the value.
1812         u32 getId(const T &value)
1813         {
1814                 JMutexAutoLock lock(m_mutex);
1815                 typename core::map<T, u32>::Node *n;
1816                 n = m_value_to_id.find(value);
1817                 if(n != NULL)
1818                         return n->getValue();
1819                 m_id_to_value.push_back(value);
1820                 u32 new_id = m_id_to_value.size();
1821                 m_value_to_id.insert(value, new_id);
1822                 return new_id;
1823         }
1824
1825 private:
1826         JMutex m_mutex;
1827         // Values are stored here at id-1 position (id 1 = [0])
1828         core::array<T> m_id_to_value;
1829         core::map<T, u32> m_value_to_id;
1830 };
1831
1832 /*
1833         Checks if a string contains only supplied characters
1834 */
1835 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1836 {
1837         for(u32 i=0; i<s.size(); i++)
1838         {
1839                 bool confirmed = false;
1840                 for(u32 j=0; j<allowed_chars.size(); j++)
1841                 {
1842                         if(s[i] == allowed_chars[j])
1843                         {
1844                                 confirmed = true;
1845                                 break;
1846                         }
1847                 }
1848                 if(confirmed == false)
1849                         return false;
1850         }
1851         return true;
1852 }
1853
1854 /*
1855         Forcefully wraps string into rows using \n
1856         (no word wrap, used for showing paths in gui)
1857 */
1858 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1859 {
1860         std::string to;
1861         for(u32 i=0; i<from.size(); i++)
1862         {
1863                 if(i != 0 && i%rowlen == 0)
1864                         to += '\n';
1865                 to += from[i];
1866         }
1867         return to;
1868 }
1869
1870 /*
1871         Some helper stuff
1872 */
1873 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1874 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1875
1876 /*
1877         Returns integer position of node in given floating point position
1878 */
1879 inline v3s16 floatToInt(v3f p, f32 d)
1880 {
1881         v3s16 p2(
1882                 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1883                 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1884                 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1885         return p2;
1886 }
1887
1888 /*
1889         Returns floating point position of node in given integer position
1890 */
1891 inline v3f intToFloat(v3s16 p, f32 d)
1892 {
1893         v3f p2(
1894                 (f32)p.X * d,
1895                 (f32)p.Y * d,
1896                 (f32)p.Z * d
1897         );
1898         return p2;
1899 }
1900
1901 /*
1902         More serialization stuff
1903 */
1904
1905 // Creates a string with the length as the first two bytes
1906 inline std::string serializeString(const std::string plain)
1907 {
1908         assert(plain.size() <= 65535);
1909         char buf[2];
1910         writeU16((u8*)&buf[0], plain.size());
1911         std::string s;
1912         s.append(buf, 2);
1913         s.append(plain);
1914         return s;
1915 }
1916
1917 /*// Reads a string with the length as the first two bytes
1918 inline std::string deSerializeString(const std::string encoded)
1919 {
1920         u16 s_size = readU16((u8*)&encoded.c_str()[0]);
1921         if(s_size > encoded.length() - 2)
1922                 return "";
1923         std::string s;
1924         s.reserve(s_size);
1925         s.append(&encoded.c_str()[2], s_size);
1926         return s;
1927 }*/
1928
1929 // Reads a string with the length as the first two bytes
1930 inline std::string deSerializeString(std::istream &is)
1931 {
1932         char buf[2];
1933         is.read(buf, 2);
1934         if(is.gcount() != 2)
1935                 throw SerializationError("deSerializeString: size not read");
1936         u16 s_size = readU16((u8*)buf);
1937         if(s_size == 0)
1938                 return "";
1939         Buffer<char> buf2(s_size);
1940         is.read(&buf2[0], s_size);
1941         std::string s;
1942         s.reserve(s_size);
1943         s.append(&buf2[0], s_size);
1944         return s;
1945 }
1946
1947 // Creates a string with the length as the first four bytes
1948 inline std::string serializeLongString(const std::string plain)
1949 {
1950         char buf[4];
1951         writeU32((u8*)&buf[0], plain.size());
1952         std::string s;
1953         s.append(buf, 4);
1954         s.append(plain);
1955         return s;
1956 }
1957
1958 /*// Reads a string with the length as the first four bytes
1959 inline std::string deSerializeLongString(const std::string encoded)
1960 {
1961         u32 s_size = readU32((u8*)&encoded.c_str()[0]);
1962         if(s_size > encoded.length() - 4)
1963                 return "";
1964         std::string s;
1965         s.reserve(s_size);
1966         s.append(&encoded.c_str()[4], s_size);
1967         return s;
1968 }*/
1969
1970 // Reads a string with the length as the first four bytes
1971 inline std::string deSerializeLongString(std::istream &is)
1972 {
1973         char buf[4];
1974         is.read(buf, 4);
1975         if(is.gcount() != 4)
1976                 throw SerializationError("deSerializeLongString: size not read");
1977         u32 s_size = readU32((u8*)buf);
1978         if(s_size == 0)
1979                 return "";
1980         Buffer<char> buf2(s_size);
1981         is.read(&buf2[0], s_size);
1982         std::string s;
1983         s.reserve(s_size);
1984         s.append(&buf2[0], s_size);
1985         return s;
1986 }
1987
1988 //
1989
1990 inline u32 time_to_daynight_ratio(u32 time_of_day)
1991 {
1992         const s32 daylength = 16;
1993         const s32 nightlength = 6;
1994         const s32 daytimelength = 8;
1995         s32 d = daylength;
1996         s32 t = (((time_of_day)%24000)/(24000/d));
1997         if(t < nightlength/2 || t >= d - nightlength/2)
1998                 return 300;
1999         else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
2000                 return 1000;
2001         else
2002                 return 750;
2003 }
2004
2005 // Random helper. Usually d=BS
2006 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
2007 {
2008         return core::aabbox3d<f32>(
2009                 (float)p.X * d - 0.5*d,
2010                 (float)p.Y * d - 0.5*d,
2011                 (float)p.Z * d - 0.5*d,
2012                 (float)p.X * d + 0.5*d,
2013                 (float)p.Y * d + 0.5*d,
2014                 (float)p.Z * d + 0.5*d
2015         );
2016 }
2017         
2018 class IntervalLimiter
2019 {
2020 public:
2021         IntervalLimiter():
2022                 m_accumulator(0)
2023         {
2024         }
2025         /*
2026                 dtime: time from last call to this method
2027                 wanted_interval: interval wanted
2028                 return value:
2029                         true: action should be skipped
2030                         false: action should be done
2031         */
2032         bool step(float dtime, float wanted_interval)
2033         {
2034                 m_accumulator += dtime;
2035                 if(m_accumulator < wanted_interval)
2036                 {
2037                         dtime = 0;
2038                         return true;
2039                 }
2040                 m_accumulator -= wanted_interval;
2041                 return false;
2042         }
2043 protected:
2044         float m_accumulator;
2045 };
2046
2047
2048 #endif
2049