If a user doesn't have build rights, don't allow them to move items to and from their...
[oweals/minetest.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[4];
240         writeF1000((u8*)buf, p);
241         os.write(buf, 4);
242 }
243 inline f32 readF1000(std::istream &is)
244 {
245         char buf[4];
246         is.read(buf, 4);
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 set(std::string name, const char *value)
1265         {
1266                 JMutexAutoLock lock(m_mutex);
1267
1268                 m_settings[name] = value;
1269         }
1270
1271
1272         void setDefault(std::string name, std::string value)
1273         {
1274                 JMutexAutoLock lock(m_mutex);
1275                 
1276                 m_defaults[name] = value;
1277         }
1278
1279         bool exists(std::string name)
1280         {
1281                 JMutexAutoLock lock(m_mutex);
1282                 
1283                 return (m_settings.find(name) || m_defaults.find(name));
1284         }
1285
1286         std::string get(std::string name)
1287         {
1288                 JMutexAutoLock lock(m_mutex);
1289                 
1290                 core::map<std::string, std::string>::Node *n;
1291                 n = m_settings.find(name);
1292                 if(n == NULL)
1293                 {
1294                         n = m_defaults.find(name);
1295                         if(n == NULL)
1296                         {
1297                                 dstream<<"INFO: Settings: Setting not found: \""
1298                                                 <<name<<"\""<<std::endl;
1299                                 throw SettingNotFoundException("Setting not found");
1300                         }
1301                 }
1302
1303                 return n->getValue();
1304         }
1305
1306         bool getBool(std::string name)
1307         {
1308                 return is_yes(get(name));
1309         }
1310         
1311         bool getFlag(std::string name)
1312         {
1313                 try
1314                 {
1315                         return getBool(name);
1316                 }
1317                 catch(SettingNotFoundException &e)
1318                 {
1319                         return false;
1320                 }
1321         }
1322
1323         // Asks if empty
1324         bool getBoolAsk(std::string name, std::string question, bool def)
1325         {
1326                 // If it is in settings
1327                 if(exists(name))
1328                         return getBool(name);
1329                 
1330                 std::string s;
1331                 char templine[10];
1332                 std::cout<<question<<" [y/N]: ";
1333                 std::cin.getline(templine, 10);
1334                 s = templine;
1335
1336                 if(s == "")
1337                         return def;
1338
1339                 return is_yes(s);
1340         }
1341
1342         float getFloat(std::string name)
1343         {
1344                 return stof(get(name));
1345         }
1346
1347         u16 getU16(std::string name)
1348         {
1349                 return stoi(get(name), 0, 65535);
1350         }
1351
1352         u16 getU16Ask(std::string name, std::string question, u16 def)
1353         {
1354                 // If it is in settings
1355                 if(exists(name))
1356                         return getU16(name);
1357                 
1358                 std::string s;
1359                 char templine[10];
1360                 std::cout<<question<<" ["<<def<<"]: ";
1361                 std::cin.getline(templine, 10);
1362                 s = templine;
1363
1364                 if(s == "")
1365                         return def;
1366
1367                 return stoi(s, 0, 65535);
1368         }
1369
1370         s16 getS16(std::string name)
1371         {
1372                 return stoi(get(name), -32768, 32767);
1373         }
1374
1375         s32 getS32(std::string name)
1376         {
1377                 return stoi(get(name));
1378         }
1379
1380         v3f getV3F(std::string name)
1381         {
1382                 v3f value;
1383                 Strfnd f(get(name));
1384                 f.next("(");
1385                 value.X = stof(f.next(","));
1386                 value.Y = stof(f.next(","));
1387                 value.Z = stof(f.next(")"));
1388                 return value;
1389         }
1390
1391         u64 getU64(std::string name)
1392         {
1393                 u64 value = 0;
1394                 std::string s = get(name);
1395                 std::istringstream ss(s);
1396                 ss>>value;
1397                 return value;
1398         }
1399
1400         void setBool(std::string name, bool value)
1401         {
1402                 if(value)
1403                         set(name, "true");
1404                 else
1405                         set(name, "false");
1406         }
1407
1408         void setS32(std::string name, s32 value)
1409         {
1410                 set(name, itos(value));
1411         }
1412
1413         void setFloat(std::string name, float value)
1414         {
1415                 set(name, ftos(value));
1416         }
1417
1418         void setV3F(std::string name, v3f value)
1419         {
1420                 std::ostringstream os;
1421                 os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
1422                 set(name, os.str());
1423         }
1424
1425         void setU64(std::string name, u64 value)
1426         {
1427                 std::ostringstream os;
1428                 os<<value;
1429                 set(name, os.str());
1430         }
1431
1432         void clear()
1433         {
1434                 JMutexAutoLock lock(m_mutex);
1435                 
1436                 m_settings.clear();
1437                 m_defaults.clear();
1438         }
1439
1440         Settings & operator+=(Settings &other)
1441         {
1442                 JMutexAutoLock lock(m_mutex);
1443                 JMutexAutoLock lock2(other.m_mutex);
1444                 
1445                 if(&other == this)
1446                         return *this;
1447
1448                 for(core::map<std::string, std::string>::Iterator
1449                                 i = other.m_settings.getIterator();
1450                                 i.atEnd() == false; i++)
1451                 {
1452                         m_settings.insert(i.getNode()->getKey(),
1453                                         i.getNode()->getValue());
1454                 }
1455                 
1456                 for(core::map<std::string, std::string>::Iterator
1457                                 i = other.m_defaults.getIterator();
1458                                 i.atEnd() == false; i++)
1459                 {
1460                         m_defaults.insert(i.getNode()->getKey(),
1461                                         i.getNode()->getValue());
1462                 }
1463
1464                 return *this;
1465
1466         }
1467
1468         Settings & operator=(Settings &other)
1469         {
1470                 JMutexAutoLock lock(m_mutex);
1471                 JMutexAutoLock lock2(other.m_mutex);
1472                 
1473                 if(&other == this)
1474                         return *this;
1475
1476                 clear();
1477                 (*this) += other;
1478                 
1479                 return *this;
1480         }
1481
1482 private:
1483         core::map<std::string, std::string> m_settings;
1484         core::map<std::string, std::string> m_defaults;
1485         // All methods that access m_settings/m_defaults directly should lock this.
1486         JMutex m_mutex;
1487 };
1488
1489 /*
1490         FIFO queue (well, actually a FILO also)
1491 */
1492 template<typename T>
1493 class Queue
1494 {
1495 public:
1496         void push_back(T t)
1497         {
1498                 m_list.push_back(t);
1499         }
1500         
1501         T pop_front()
1502         {
1503                 if(m_list.size() == 0)
1504                         throw ItemNotFoundException("Queue: queue is empty");
1505
1506                 typename core::list<T>::Iterator begin = m_list.begin();
1507                 T t = *begin;
1508                 m_list.erase(begin);
1509                 return t;
1510         }
1511         T pop_back()
1512         {
1513                 if(m_list.size() == 0)
1514                         throw ItemNotFoundException("Queue: queue is empty");
1515
1516                 typename core::list<T>::Iterator last = m_list.getLast();
1517                 T t = *last;
1518                 m_list.erase(last);
1519                 return t;
1520         }
1521
1522         u32 size()
1523         {
1524                 return m_list.size();
1525         }
1526
1527 protected:
1528         core::list<T> m_list;
1529 };
1530
1531 /*
1532         Thread-safe FIFO queue (well, actually a FILO also)
1533 */
1534
1535 template<typename T>
1536 class MutexedQueue
1537 {
1538 public:
1539         MutexedQueue()
1540         {
1541                 m_mutex.Init();
1542         }
1543         u32 size()
1544         {
1545                 JMutexAutoLock lock(m_mutex);
1546                 return m_list.size();
1547         }
1548         void push_back(T t)
1549         {
1550                 JMutexAutoLock lock(m_mutex);
1551                 m_list.push_back(t);
1552         }
1553         T pop_front(u32 wait_time_max_ms=0)
1554         {
1555                 u32 wait_time_ms = 0;
1556
1557                 for(;;)
1558                 {
1559                         {
1560                                 JMutexAutoLock lock(m_mutex);
1561
1562                                 if(m_list.size() > 0)
1563                                 {
1564                                         typename core::list<T>::Iterator begin = m_list.begin();
1565                                         T t = *begin;
1566                                         m_list.erase(begin);
1567                                         return t;
1568                                 }
1569
1570                                 if(wait_time_ms >= wait_time_max_ms)
1571                                         throw ItemNotFoundException("MutexedQueue: queue is empty");
1572                         }
1573
1574                         // Wait a while before trying again
1575                         sleep_ms(10);
1576                         wait_time_ms += 10;
1577                 }
1578         }
1579         T pop_back(u32 wait_time_max_ms=0)
1580         {
1581                 u32 wait_time_ms = 0;
1582
1583                 for(;;)
1584                 {
1585                         {
1586                                 JMutexAutoLock lock(m_mutex);
1587
1588                                 if(m_list.size() > 0)
1589                                 {
1590                                         typename core::list<T>::Iterator last = m_list.getLast();
1591                                         T t = *last;
1592                                         m_list.erase(last);
1593                                         return t;
1594                                 }
1595
1596                                 if(wait_time_ms >= wait_time_max_ms)
1597                                         throw ItemNotFoundException("MutexedQueue: queue is empty");
1598                         }
1599
1600                         // Wait a while before trying again
1601                         sleep_ms(10);
1602                         wait_time_ms += 10;
1603                 }
1604         }
1605
1606         JMutex & getMutex()
1607         {
1608                 return m_mutex;
1609         }
1610
1611         core::list<T> & getList()
1612         {
1613                 return m_list;
1614         }
1615
1616 protected:
1617         JMutex m_mutex;
1618         core::list<T> m_list;
1619 };
1620
1621 /*
1622         A single worker thread - multiple client threads queue framework.
1623 */
1624
1625 template<typename Caller, typename Data>
1626 class CallerInfo
1627 {
1628 public:
1629         Caller caller;
1630         Data data;
1631 };
1632
1633 template<typename Key, typename T, typename Caller, typename CallerData>
1634 class GetResult
1635 {
1636 public:
1637         Key key;
1638         T item;
1639         core::list<CallerInfo<Caller, CallerData> > callers;
1640 };
1641
1642 template<typename Key, typename T, typename Caller, typename CallerData>
1643 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1644 {
1645 };
1646
1647 template<typename Key, typename T, typename Caller, typename CallerData>
1648 class GetRequest
1649 {
1650 public:
1651         GetRequest()
1652         {
1653                 dest = NULL;
1654         }
1655         GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1656         {
1657                 dest = a_dest;
1658         }
1659         GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1660                         Key a_key)
1661         {
1662                 dest = a_dest;
1663                 key = a_key;
1664         }
1665         ~GetRequest()
1666         {
1667         }
1668         
1669         Key key;
1670         ResultQueue<Key, T, Caller, CallerData> *dest;
1671         core::list<CallerInfo<Caller, CallerData> > callers;
1672 };
1673
1674 template<typename Key, typename T, typename Caller, typename CallerData>
1675 class RequestQueue
1676 {
1677 public:
1678         u32 size()
1679         {
1680                 return m_queue.size();
1681         }
1682
1683         void add(Key key, Caller caller, CallerData callerdata,
1684                         ResultQueue<Key, T, Caller, CallerData> *dest)
1685         {
1686                 JMutexAutoLock lock(m_queue.getMutex());
1687                 
1688                 /*
1689                         If the caller is already on the list, only update CallerData
1690                 */
1691                 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1692                                 i = m_queue.getList().begin();
1693                                 i != m_queue.getList().end(); i++)
1694                 {
1695                         GetRequest<Key, T, Caller, CallerData> &request = *i;
1696
1697                         if(request.key == key)
1698                         {
1699                                 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1700                                                 i = request.callers.begin();
1701                                                 i != request.callers.end(); i++)
1702                                 {
1703                                         CallerInfo<Caller, CallerData> &ca = *i;
1704                                         if(ca.caller == caller)
1705                                         {
1706                                                 ca.data = callerdata;
1707                                                 return;
1708                                         }
1709                                 }
1710                                 CallerInfo<Caller, CallerData> ca;
1711                                 ca.caller = caller;
1712                                 ca.data = callerdata;
1713                                 request.callers.push_back(ca);
1714                                 return;
1715                         }
1716                 }
1717
1718                 /*
1719                         Else add a new request to the queue
1720                 */
1721
1722                 GetRequest<Key, T, Caller, CallerData> request;
1723                 request.key = key;
1724                 CallerInfo<Caller, CallerData> ca;
1725                 ca.caller = caller;
1726                 ca.data = callerdata;
1727                 request.callers.push_back(ca);
1728                 request.dest = dest;
1729                 
1730                 m_queue.getList().push_back(request);
1731         }
1732
1733         GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1734         {
1735                 return m_queue.pop_front(wait_if_empty);
1736         }
1737
1738 private:
1739         MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1740 };
1741
1742 /*
1743         Pseudo-random (VC++ rand() sucks)
1744 */
1745 int myrand(void);
1746 void mysrand(unsigned seed);
1747 #define MYRAND_MAX 32767
1748
1749 inline int myrand_range(int min, int max)
1750 {
1751         if(max-min > MYRAND_MAX)
1752         {
1753                 dstream<<"WARNING: myrand_range: max-min > MYRAND_MAX"<<std::endl;
1754                 assert(0);
1755         }
1756         if(min > max)
1757         {
1758                 assert(0);
1759                 return max;
1760         }
1761         return (myrand()%(max-min+1))+min;
1762 }
1763
1764 /*
1765         Miscellaneous functions
1766 */
1767
1768 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
1769                 f32 *distance_ptr=NULL);
1770
1771 /*
1772         Queue with unique values with fast checking of value existence
1773 */
1774
1775 template<typename Value>
1776 class UniqueQueue
1777 {
1778 public:
1779         
1780         /*
1781                 Does nothing if value is already queued.
1782                 Return value:
1783                         true: value added
1784                         false: value already exists
1785         */
1786         bool push_back(Value value)
1787         {
1788                 // Check if already exists
1789                 if(m_map.find(value) != NULL)
1790                         return false;
1791
1792                 // Add
1793                 m_map.insert(value, 0);
1794                 m_list.push_back(value);
1795                 
1796                 return true;
1797         }
1798
1799         Value pop_front()
1800         {
1801                 typename core::list<Value>::Iterator i = m_list.begin();
1802                 Value value = *i;
1803                 m_map.remove(value);
1804                 m_list.erase(i);
1805                 return value;
1806         }
1807
1808         u32 size()
1809         {
1810                 assert(m_list.size() == m_map.size());
1811                 return m_list.size();
1812         }
1813
1814 private:
1815         core::map<Value, u8> m_map;
1816         core::list<Value> m_list;
1817 };
1818
1819 #if 1
1820 template<typename Key, typename Value>
1821 class MutexedMap
1822 {
1823 public:
1824         MutexedMap()
1825         {
1826                 m_mutex.Init();
1827                 assert(m_mutex.IsInitialized());
1828         }
1829         
1830         void set(const Key &name, const Value &value)
1831         {
1832                 JMutexAutoLock lock(m_mutex);
1833
1834                 m_values[name] = value;
1835         }
1836         
1837         bool get(const Key &name, Value *result)
1838         {
1839                 JMutexAutoLock lock(m_mutex);
1840
1841                 typename core::map<Key, Value>::Node *n;
1842                 n = m_values.find(name);
1843
1844                 if(n == NULL)
1845                         return false;
1846                 
1847                 if(result != NULL)
1848                         *result = n->getValue();
1849                         
1850                 return true;
1851         }
1852
1853 private:
1854         core::map<Key, Value> m_values;
1855         JMutex m_mutex;
1856 };
1857 #endif
1858
1859 /*
1860         Generates ids for comparable values.
1861         Id=0 is reserved for "no value".
1862
1863         Is fast at:
1864         - Returning value by id (very fast)
1865         - Returning id by value
1866         - Generating a new id for a value
1867
1868         Is not able to:
1869         - Remove an id/value pair (is possible to implement but slow)
1870 */
1871 template<typename T>
1872 class MutexedIdGenerator
1873 {
1874 public:
1875         MutexedIdGenerator()
1876         {
1877                 m_mutex.Init();
1878                 assert(m_mutex.IsInitialized());
1879         }
1880         
1881         // Returns true if found
1882         bool getValue(u32 id, T &value)
1883         {
1884                 if(id == 0)
1885                         return false;
1886                 JMutexAutoLock lock(m_mutex);
1887                 if(m_id_to_value.size() < id)
1888                         return false;
1889                 value = m_id_to_value[id-1];
1890                 return true;
1891         }
1892         
1893         // If id exists for value, returns the id.
1894         // Otherwise generates an id for the value.
1895         u32 getId(const T &value)
1896         {
1897                 JMutexAutoLock lock(m_mutex);
1898                 typename core::map<T, u32>::Node *n;
1899                 n = m_value_to_id.find(value);
1900                 if(n != NULL)
1901                         return n->getValue();
1902                 m_id_to_value.push_back(value);
1903                 u32 new_id = m_id_to_value.size();
1904                 m_value_to_id.insert(value, new_id);
1905                 return new_id;
1906         }
1907
1908 private:
1909         JMutex m_mutex;
1910         // Values are stored here at id-1 position (id 1 = [0])
1911         core::array<T> m_id_to_value;
1912         core::map<T, u32> m_value_to_id;
1913 };
1914
1915 /*
1916         Checks if a string contains only supplied characters
1917 */
1918 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1919 {
1920         for(u32 i=0; i<s.size(); i++)
1921         {
1922                 bool confirmed = false;
1923                 for(u32 j=0; j<allowed_chars.size(); j++)
1924                 {
1925                         if(s[i] == allowed_chars[j])
1926                         {
1927                                 confirmed = true;
1928                                 break;
1929                         }
1930                 }
1931                 if(confirmed == false)
1932                         return false;
1933         }
1934         return true;
1935 }
1936
1937 /*
1938         Forcefully wraps string into rows using \n
1939         (no word wrap, used for showing paths in gui)
1940 */
1941 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1942 {
1943         std::string to;
1944         for(u32 i=0; i<from.size(); i++)
1945         {
1946                 if(i != 0 && i%rowlen == 0)
1947                         to += '\n';
1948                 to += from[i];
1949         }
1950         return to;
1951 }
1952
1953 /*
1954         Some helper stuff
1955 */
1956 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1957 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1958
1959 /*
1960         Returns integer position of node in given floating point position
1961 */
1962 inline v3s16 floatToInt(v3f p, f32 d)
1963 {
1964         v3s16 p2(
1965                 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1966                 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1967                 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1968         return p2;
1969 }
1970
1971 /*
1972         Returns floating point position of node in given integer position
1973 */
1974 inline v3f intToFloat(v3s16 p, f32 d)
1975 {
1976         v3f p2(
1977                 (f32)p.X * d,
1978                 (f32)p.Y * d,
1979                 (f32)p.Z * d
1980         );
1981         return p2;
1982 }
1983
1984 /*
1985         More serialization stuff
1986 */
1987
1988 // Creates a string with the length as the first two bytes
1989 inline std::string serializeString(const std::string &plain)
1990 {
1991         //assert(plain.size() <= 65535);
1992         if(plain.size() > 65535)
1993                 throw SerializationError("String too long for serializeString");
1994         char buf[2];
1995         writeU16((u8*)&buf[0], plain.size());
1996         std::string s;
1997         s.append(buf, 2);
1998         s.append(plain);
1999         return s;
2000 }
2001
2002 // Creates a string with the length as the first two bytes from wide string
2003 inline std::string serializeWideString(const std::wstring &plain)
2004 {
2005         //assert(plain.size() <= 65535);
2006         if(plain.size() > 65535)
2007                 throw SerializationError("String too long for serializeString");
2008         char buf[2];
2009         writeU16((u8*)buf, plain.size());
2010         std::string s;
2011         s.append(buf, 2);
2012         for(u32 i=0; i<plain.size(); i++)
2013         {
2014                 writeU16((u8*)buf, plain[i]);
2015                 s.append(buf, 2);
2016         }
2017         return s;
2018 }
2019
2020 // Reads a string with the length as the first two bytes
2021 inline std::string deSerializeString(std::istream &is)
2022 {
2023         char buf[2];
2024         is.read(buf, 2);
2025         if(is.gcount() != 2)
2026                 throw SerializationError("deSerializeString: size not read");
2027         u16 s_size = readU16((u8*)buf);
2028         if(s_size == 0)
2029                 return "";
2030         Buffer<char> buf2(s_size);
2031         is.read(&buf2[0], s_size);
2032         std::string s;
2033         s.reserve(s_size);
2034         s.append(&buf2[0], s_size);
2035         return s;
2036 }
2037
2038 // Reads a wide string with the length as the first two bytes
2039 inline std::wstring deSerializeWideString(std::istream &is)
2040 {
2041         char buf[2];
2042         is.read(buf, 2);
2043         if(is.gcount() != 2)
2044                 throw SerializationError("deSerializeString: size not read");
2045         u16 s_size = readU16((u8*)buf);
2046         if(s_size == 0)
2047                 return L"";
2048         std::wstring s;
2049         s.reserve(s_size);
2050         for(u32 i=0; i<s_size; i++)
2051         {
2052                 is.read(&buf[0], 2);
2053                 wchar_t c16 = readU16((u8*)buf);
2054                 s.append(&c16, 1);
2055         }
2056         return s;
2057 }
2058
2059 // Creates a string with the length as the first four bytes
2060 inline std::string serializeLongString(const std::string &plain)
2061 {
2062         char buf[4];
2063         writeU32((u8*)&buf[0], plain.size());
2064         std::string s;
2065         s.append(buf, 4);
2066         s.append(plain);
2067         return s;
2068 }
2069
2070 // Reads a string with the length as the first four bytes
2071 inline std::string deSerializeLongString(std::istream &is)
2072 {
2073         char buf[4];
2074         is.read(buf, 4);
2075         if(is.gcount() != 4)
2076                 throw SerializationError("deSerializeLongString: size not read");
2077         u32 s_size = readU32((u8*)buf);
2078         if(s_size == 0)
2079                 return "";
2080         Buffer<char> buf2(s_size);
2081         is.read(&buf2[0], s_size);
2082         std::string s;
2083         s.reserve(s_size);
2084         s.append(&buf2[0], s_size);
2085         return s;
2086 }
2087
2088 //
2089
2090 inline u32 time_to_daynight_ratio(u32 time_of_day)
2091 {
2092         const s32 daylength = 16;
2093         const s32 nightlength = 6;
2094         const s32 daytimelength = 8;
2095         s32 d = daylength;
2096         s32 t = (((time_of_day)%24000)/(24000/d));
2097         if(t < nightlength/2 || t >= d - nightlength/2)
2098                 //return 300;
2099                 return 350;
2100         else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
2101                 return 1000;
2102         else
2103                 return 750;
2104 }
2105
2106 // Random helper. Usually d=BS
2107 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
2108 {
2109         return core::aabbox3d<f32>(
2110                 (float)p.X * d - 0.5*d,
2111                 (float)p.Y * d - 0.5*d,
2112                 (float)p.Z * d - 0.5*d,
2113                 (float)p.X * d + 0.5*d,
2114                 (float)p.Y * d + 0.5*d,
2115                 (float)p.Z * d + 0.5*d
2116         );
2117 }
2118         
2119 class IntervalLimiter
2120 {
2121 public:
2122         IntervalLimiter():
2123                 m_accumulator(0)
2124         {
2125         }
2126         /*
2127                 dtime: time from last call to this method
2128                 wanted_interval: interval wanted
2129                 return value:
2130                         true: action should be skipped
2131                         false: action should be done
2132         */
2133         bool step(float dtime, float wanted_interval)
2134         {
2135                 m_accumulator += dtime;
2136                 if(m_accumulator < wanted_interval)
2137                         return false;
2138                 m_accumulator -= wanted_interval;
2139                 return true;
2140         }
2141 protected:
2142         float m_accumulator;
2143 };
2144
2145 std::string translatePassword(std::string playername, std::wstring password);
2146
2147 #endif
2148