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