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