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