Use random-generated fallback textures when real textures are not found
[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 max)
589 {
590         if(i < 0)
591                 return 0;
592         if(i > max)
593                 return max;
594         return i;
595 }
596
597 #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
598
599 inline v3s16 arealim(v3s16 p, s16 d)
600 {
601         if(p.X < 0)
602                 p.X = 0;
603         if(p.Y < 0)
604                 p.Y = 0;
605         if(p.Z < 0)
606                 p.Z = 0;
607         if(p.X > d-1)
608                 p.X = d-1;
609         if(p.Y > d-1)
610                 p.Y = d-1;
611         if(p.Z > d-1)
612                 p.Z = d-1;
613         return p;
614 }
615
616 inline std::wstring narrow_to_wide(const std::string& mbs)
617 {
618         size_t wcl = mbs.size();
619         SharedBuffer<wchar_t> wcs(wcl+1);
620         size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
621         wcs[l] = 0;
622         return *wcs;
623 }
624
625 inline std::string wide_to_narrow(const std::wstring& wcs)
626 {
627         size_t mbl = wcs.size()*4;
628         SharedBuffer<char> mbs(mbl+1);
629         size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
630         if((int)l == -1)
631                 mbs[0] = 0;
632         else
633                 mbs[l] = 0;
634         return *mbs;
635 }
636
637 /*
638         See test.cpp for example cases.
639         wraps degrees to the range of -360...360
640         NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
641 */
642 inline float wrapDegrees(float f)
643 {
644         // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
645         // This results in
646         // 10, 720, -1, -361
647         int i = floor(f);
648         // 0, 2, 0, -1
649         int l = i / 360;
650         // NOTE: This would be used for wrapping to 0...360
651         // 0, 2, -1, -2
652         /*if(i < 0)
653                 l -= 1;*/
654         // 0, 720, 0, -360
655         int k = l * 360;
656         // 10, 0.5, -0.5, -0.5
657         f -= float(k);
658         return f;
659 }
660
661 inline std::string lowercase(const std::string &s)
662 {
663         std::string s2;
664         for(size_t i=0; i<s.size(); i++)
665         {
666                 char c = s[i];
667                 if(c >= 'A' && c <= 'Z')
668                         c -= 'A' - 'a';
669                 s2 += c;
670         }
671         return s2;
672 }
673
674 inline bool is_yes(const std::string &s)
675 {
676         std::string s2 = lowercase(trim(s));
677         if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
678                 return true;
679         return false;
680 }
681
682 inline s32 stoi(const std::string &s, s32 min, s32 max)
683 {
684         s32 i = atoi(s.c_str());
685         if(i < min)
686                 i = min;
687         if(i > max)
688                 i = max;
689         return i;
690 }
691
692 inline s32 stoi(std::string s)
693 {
694         return atoi(s.c_str());
695 }
696
697 inline float stof(std::string s)
698 {
699         float f;
700         std::istringstream ss(s);
701         ss>>f;
702         return f;
703 }
704
705 inline std::string itos(s32 i)
706 {
707         std::ostringstream o;
708         o<<i;
709         return o.str();
710 }
711
712 inline std::string ftos(float f)
713 {
714         std::ostringstream o;
715         o<<f;
716         return o.str();
717 }
718
719 inline void str_replace(std::string & str, std::string const & pattern,
720                 std::string const & replacement)
721 {
722         std::string::size_type start = str.find(pattern, 0);
723         while(start != str.npos)
724         {
725                 str.replace(start, pattern.size(), replacement);
726                 start = str.find(pattern, start+replacement.size());
727         }
728 }
729
730 inline void str_replace_char(std::string & str, char from, char to)
731 {
732         for(unsigned int i=0; i<str.size(); i++)
733         {
734                 if(str[i] == from)
735                         str[i] = to;
736         }
737 }
738
739 /*
740         A base class for simple background thread implementation
741 */
742
743 class SimpleThread : public JThread
744 {
745         bool run;
746         JMutex run_mutex;
747
748 public:
749
750         SimpleThread():
751                 JThread(),
752                 run(true)
753         {
754                 run_mutex.Init();
755         }
756
757         virtual ~SimpleThread()
758         {}
759
760         virtual void * Thread() = 0;
761
762         bool getRun()
763         {
764                 JMutexAutoLock lock(run_mutex);
765                 return run;
766         }
767         void setRun(bool a_run)
768         {
769                 JMutexAutoLock lock(run_mutex);
770                 run = a_run;
771         }
772
773         void stop()
774         {
775                 setRun(false);
776                 while(IsRunning())
777                         sleep_ms(100);
778         }
779 };
780
781 /*
782         Config stuff
783 */
784
785 enum ValueType
786 {
787         VALUETYPE_STRING,
788         VALUETYPE_FLAG // Doesn't take any arguments
789 };
790
791 struct ValueSpec
792 {
793         ValueSpec(ValueType a_type, const char *a_help=NULL)
794         {
795                 type = a_type;
796                 help = a_help;
797         }
798         ValueType type;
799         const char *help;
800 };
801
802 class Settings
803 {
804 public:
805
806         void writeLines(std::ostream &os)
807         {
808                 for(core::map<std::string, std::string>::Iterator
809                                 i = m_settings.getIterator();
810                                 i.atEnd() == false; i++)
811                 {
812                         std::string name = i.getNode()->getKey();
813                         std::string value = i.getNode()->getValue();
814                         os<<name<<" = "<<value<<"\n";
815                 }
816         }
817
818         bool parseConfigLine(const std::string &line)
819         {
820                 std::string trimmedline = trim(line);
821                 
822                 // Ignore comments
823                 if(trimmedline[0] == '#')
824                         return true;
825
826                 //dstream<<"trimmedline=\""<<trimmedline<<"\""<<std::endl;
827
828                 Strfnd sf(trim(line));
829
830                 std::string name = sf.next("=");
831                 name = trim(name);
832
833                 if(name == "")
834                         return true;
835                 
836                 std::string value = sf.next("\n");
837                 value = trim(value);
838
839                 /*dstream<<"Config name=\""<<name<<"\" value=\""
840                                 <<value<<"\""<<std::endl;*/
841                 
842                 m_settings[name] = value;
843                 
844                 return true;
845         }
846
847         // Returns false on EOF
848         bool parseConfigObject(std::istream &is)
849         {
850                 if(is.eof())
851                         return false;
852                 
853                 /*
854                         NOTE: This function might be expanded to allow multi-line
855                               settings.
856                 */
857                 std::string line;
858                 std::getline(is, line);
859                 //dstream<<"got line: \""<<line<<"\""<<std::endl;
860
861                 return parseConfigLine(line);
862         }
863
864         /*
865                 Read configuration file
866
867                 Returns true on success
868         */
869         bool readConfigFile(const char *filename)
870         {
871                 std::ifstream is(filename);
872                 if(is.good() == false)
873                 {
874                         dstream<<"Error opening configuration file \""
875                                         <<filename<<"\""<<std::endl;
876                         return false;
877                 }
878
879                 dstream<<"Parsing configuration file: \""
880                                 <<filename<<"\""<<std::endl;
881                                 
882                 while(parseConfigObject(is));
883                 
884                 return true;
885         }
886
887         /*
888                 Reads a configuration object from stream (usually a single line)
889                 and adds it to dst.
890                 
891                 Preserves comments and empty lines.
892
893                 Settings that were added to dst are also added to updated.
894                 key of updated is setting name, value of updated is dummy.
895
896                 Returns false on EOF
897         */
898         bool getUpdatedConfigObject(std::istream &is,
899                         core::list<std::string> &dst,
900                         core::map<std::string, bool> &updated)
901         {
902                 if(is.eof())
903                         return false;
904                 
905                 // NOTE: This function will be expanded to allow multi-line settings
906                 std::string line;
907                 std::getline(is, line);
908
909                 std::string trimmedline = trim(line);
910
911                 std::string line_end = "";
912                 if(is.eof() == false)
913                         line_end = "\n";
914                 
915                 // Ignore comments
916                 if(trimmedline[0] == '#')
917                 {
918                         dst.push_back(line+line_end);
919                         return true;
920                 }
921
922                 Strfnd sf(trim(line));
923
924                 std::string name = sf.next("=");
925                 name = trim(name);
926
927                 if(name == "")
928                 {
929                         dst.push_back(line+line_end);
930                         return true;
931                 }
932                 
933                 std::string value = sf.next("\n");
934                 value = trim(value);
935                 
936                 if(m_settings.find(name))
937                 {
938                         std::string newvalue = m_settings[name];
939                         
940                         if(newvalue != value)
941                         {
942                                 dstream<<"Changing value of \""<<name<<"\" = \""
943                                                 <<value<<"\" -> \""<<newvalue<<"\""
944                                                 <<std::endl;
945                         }
946
947                         dst.push_back(name + " = " + newvalue + line_end);
948
949                         updated[name] = true;
950                 }
951                 
952                 return true;
953         }
954
955         /*
956                 Updates configuration file
957
958                 Returns true on success
959         */
960         bool updateConfigFile(const char *filename)
961         {
962                 dstream<<"Updating configuration file: \""
963                                 <<filename<<"\""<<std::endl;
964                 
965                 core::list<std::string> objects;
966                 core::map<std::string, bool> updated;
967                 
968                 // Read and modify stuff
969                 {
970                         std::ifstream is(filename);
971                         if(is.good() == false)
972                         {
973                                 dstream<<"INFO: updateConfigFile():"
974                                                 " Error opening configuration file"
975                                                 " for reading: \""
976                                                 <<filename<<"\""<<std::endl;
977                         }
978                         else
979                         {
980                                 while(getUpdatedConfigObject(is, objects, updated));
981                         }
982                 }
983                 
984                 // Write stuff back
985                 {
986                         std::ofstream os(filename);
987                         if(os.good() == false)
988                         {
989                                 dstream<<"Error opening configuration file"
990                                                 " for writing: \""
991                                                 <<filename<<"\""<<std::endl;
992                                 return false;
993                         }
994                         
995                         /*
996                                 Write updated stuff
997                         */
998                         for(core::list<std::string>::Iterator
999                                         i = objects.begin();
1000                                         i != objects.end(); i++)
1001                         {
1002                                 os<<(*i);
1003                         }
1004
1005                         /*
1006                                 Write stuff that was not already in the file
1007                         */
1008                         for(core::map<std::string, std::string>::Iterator
1009                                         i = m_settings.getIterator();
1010                                         i.atEnd() == false; i++)
1011                         {
1012                                 if(updated.find(i.getNode()->getKey()))
1013                                         continue;
1014                                 std::string name = i.getNode()->getKey();
1015                                 std::string value = i.getNode()->getValue();
1016                                 dstream<<"Adding \""<<name<<"\" = \""<<value<<"\""
1017                                                 <<std::endl;
1018                                 os<<name<<" = "<<value<<"\n";
1019                         }
1020                 }
1021                 
1022                 return true;
1023         }
1024
1025         /*
1026                 NOTE: Types of allowed_options are ignored
1027
1028                 returns true on success
1029         */
1030         bool parseCommandLine(int argc, char *argv[],
1031                         core::map<std::string, ValueSpec> &allowed_options)
1032         {
1033                 int i=1;
1034                 for(;;)
1035                 {
1036                         if(i >= argc)
1037                                 break;
1038                         std::string argname = argv[i];
1039                         if(argname.substr(0, 2) != "--")
1040                         {
1041                                 dstream<<"Invalid command-line parameter \""
1042                                                 <<argname<<"\": --<option> expected."<<std::endl;
1043                                 return false;
1044                         }
1045                         i++;
1046
1047                         std::string name = argname.substr(2);
1048
1049                         core::map<std::string, ValueSpec>::Node *n;
1050                         n = allowed_options.find(name);
1051                         if(n == NULL)
1052                         {
1053                                 dstream<<"Unknown command-line parameter \""
1054                                                 <<argname<<"\""<<std::endl;
1055                                 return false;
1056                         }
1057
1058                         ValueType type = n->getValue().type;
1059
1060                         std::string value = "";
1061                         
1062                         if(type == VALUETYPE_FLAG)
1063                         {
1064                                 value = "true";
1065                         }
1066                         else
1067                         {
1068                                 if(i >= argc)
1069                                 {
1070                                         dstream<<"Invalid command-line parameter \""
1071                                                         <<name<<"\": missing value"<<std::endl;
1072                                         return false;
1073                                 }
1074                                 value = argv[i];
1075                                 i++;
1076                         }
1077                         
1078
1079                         dstream<<"Valid command-line parameter: \""
1080                                         <<name<<"\" = \""<<value<<"\""
1081                                         <<std::endl;
1082                         set(name, value);
1083                 }
1084
1085                 return true;
1086         }
1087
1088         void set(std::string name, std::string value)
1089         {
1090                 m_settings[name] = value;
1091         }
1092
1093         void setDefault(std::string name, std::string value)
1094         {
1095                 m_defaults[name] = value;
1096         }
1097
1098         bool exists(std::string name)
1099         {
1100                 return (m_settings.find(name) || m_defaults.find(name));
1101         }
1102
1103         std::string get(std::string name)
1104         {
1105                 core::map<std::string, std::string>::Node *n;
1106                 n = m_settings.find(name);
1107                 if(n == NULL)
1108                 {
1109                         n = m_defaults.find(name);
1110                         if(n == NULL)
1111                         {
1112                                 dstream<<"INFO: Settings: Setting not found: \""
1113                                                 <<name<<"\""<<std::endl;
1114                                 throw SettingNotFoundException("Setting not found");
1115                         }
1116                 }
1117
1118                 return n->getValue();
1119         }
1120
1121         bool getBool(std::string name)
1122         {
1123                 return is_yes(get(name));
1124         }
1125         
1126         bool getFlag(std::string name)
1127         {
1128                 try
1129                 {
1130                         return getBool(name);
1131                 }
1132                 catch(SettingNotFoundException &e)
1133                 {
1134                         return false;
1135                 }
1136         }
1137
1138         // Asks if empty
1139         bool getBoolAsk(std::string name, std::string question, bool def)
1140         {
1141                 // If it is in settings
1142                 if(m_settings.find(name))
1143                         return getBool(name);
1144                 
1145                 std::string s;
1146                 char templine[10];
1147                 std::cout<<question<<" [y/N]: ";
1148                 std::cin.getline(templine, 10);
1149                 s = templine;
1150
1151                 if(s == "")
1152                         return def;
1153
1154                 return is_yes(s);
1155         }
1156
1157         float getFloat(std::string name)
1158         {
1159                 return stof(get(name));
1160         }
1161
1162         u16 getU16(std::string name)
1163         {
1164                 return stoi(get(name), 0, 65535);
1165         }
1166
1167         u16 getU16Ask(std::string name, std::string question, u16 def)
1168         {
1169                 // If it is in settings
1170                 if(m_settings.find(name))
1171                         return getU16(name);
1172                 
1173                 std::string s;
1174                 char templine[10];
1175                 std::cout<<question<<" ["<<def<<"]: ";
1176                 std::cin.getline(templine, 10);
1177                 s = templine;
1178
1179                 if(s == "")
1180                         return def;
1181
1182                 return stoi(s, 0, 65535);
1183         }
1184
1185         s16 getS16(std::string name)
1186         {
1187                 return stoi(get(name), -32768, 32767);
1188         }
1189
1190         s32 getS32(std::string name)
1191         {
1192                 return stoi(get(name));
1193         }
1194
1195         v3f getV3F(std::string name)
1196         {
1197                 v3f value;
1198                 Strfnd f(get(name));
1199                 f.next("(");
1200                 value.X = stof(f.next(","));
1201                 value.Y = stof(f.next(","));
1202                 value.Z = stof(f.next(")"));
1203                 return value;
1204         }
1205
1206         u64 getU64(std::string name)
1207         {
1208                 u64 value = 0;
1209                 std::string s = get(name);
1210                 std::istringstream ss(s);
1211                 ss>>value;
1212                 return value;
1213         }
1214
1215         void setS32(std::string name, s32 value)
1216         {
1217                 set(name, itos(value));
1218         }
1219
1220         void setFloat(std::string name, float value)
1221         {
1222                 set(name, ftos(value));
1223         }
1224
1225         void setV3F(std::string name, v3f value)
1226         {
1227                 std::ostringstream os;
1228                 os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
1229                 set(name, os.str());
1230         }
1231
1232         void setU64(std::string name, u64 value)
1233         {
1234                 std::ostringstream os;
1235                 os<<value;
1236                 set(name, os.str());
1237         }
1238
1239         void clear()
1240         {
1241                 m_settings.clear();
1242                 m_defaults.clear();
1243         }
1244
1245         Settings & operator+=(Settings &other)
1246         {
1247                 if(&other == this)
1248                         return *this;
1249
1250                 for(core::map<std::string, std::string>::Iterator
1251                                 i = other.m_settings.getIterator();
1252                                 i.atEnd() == false; i++)
1253                 {
1254                         m_settings.insert(i.getNode()->getKey(),
1255                                         i.getNode()->getValue());
1256                 }
1257                 
1258                 for(core::map<std::string, std::string>::Iterator
1259                                 i = other.m_defaults.getIterator();
1260                                 i.atEnd() == false; i++)
1261                 {
1262                         m_defaults.insert(i.getNode()->getKey(),
1263                                         i.getNode()->getValue());
1264                 }
1265
1266         }
1267
1268         Settings & operator=(Settings &other)
1269         {
1270                 if(&other == this)
1271                         return *this;
1272
1273                 clear();
1274                 (*this) += other;
1275                 
1276                 return *this;
1277         }
1278
1279 private:
1280         core::map<std::string, std::string> m_settings;
1281         core::map<std::string, std::string> m_defaults;
1282 };
1283
1284 /*
1285         FIFO queue
1286 */
1287 template<typename T>
1288 class Queue
1289 {
1290 public:
1291         void push_back(T t)
1292         {
1293                 m_list.push_back(t);
1294         }
1295         
1296         T pop_front()
1297         {
1298                 if(m_list.size() == 0)
1299                         throw ItemNotFoundException("MutexedQueue: queue is empty");
1300
1301                 typename core::list<T>::Iterator begin = m_list.begin();
1302                 T t = *begin;
1303                 m_list.erase(begin);
1304                 return t;
1305         }
1306
1307         u32 size()
1308         {
1309                 return m_list.size();
1310         }
1311
1312 protected:
1313         core::list<T> m_list;
1314 };
1315
1316 /*
1317         Thread-safe FIFO queue
1318 */
1319
1320 template<typename T>
1321 class MutexedQueue
1322 {
1323 public:
1324         MutexedQueue()
1325         {
1326                 m_mutex.Init();
1327         }
1328         u32 size()
1329         {
1330                 return m_list.size();
1331         }
1332         void push_back(T t)
1333         {
1334                 JMutexAutoLock lock(m_mutex);
1335                 m_list.push_back(t);
1336         }
1337         T pop_front(u32 wait_time_max_ms=0)
1338         {
1339                 u32 wait_time_ms = 0;
1340
1341                 for(;;)
1342                 {
1343                         {
1344                                 JMutexAutoLock lock(m_mutex);
1345
1346                                 if(m_list.size() > 0)
1347                                 {
1348                                         typename core::list<T>::Iterator begin = m_list.begin();
1349                                         T t = *begin;
1350                                         m_list.erase(begin);
1351                                         return t;
1352                                 }
1353
1354                                 if(wait_time_ms >= wait_time_max_ms)
1355                                         throw ItemNotFoundException("MutexedQueue: queue is empty");
1356                         }
1357
1358                         // Wait a while before trying again
1359                         sleep_ms(10);
1360                         wait_time_ms += 10;
1361                 }
1362         }
1363
1364         JMutex & getMutex()
1365         {
1366                 return m_mutex;
1367         }
1368
1369         core::list<T> & getList()
1370         {
1371                 return m_list;
1372         }
1373
1374 protected:
1375         JMutex m_mutex;
1376         core::list<T> m_list;
1377 };
1378
1379 template<typename Caller, typename Data>
1380 class CallerInfo
1381 {
1382 public:
1383         Caller caller;
1384         Data data;
1385 };
1386
1387 template<typename Key, typename T, typename Caller, typename CallerData>
1388 class GetResult
1389 {
1390 public:
1391         Key key;
1392         T item;
1393         core::list<CallerInfo<Caller, CallerData> > callers;
1394 };
1395
1396 template<typename Key, typename T, typename Caller, typename CallerData>
1397 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1398 {
1399 };
1400
1401 template<typename Key, typename T, typename Caller, typename CallerData>
1402 class GetRequest
1403 {
1404 public:
1405         GetRequest()
1406         {
1407                 dest = NULL;
1408         }
1409         GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1410         {
1411                 dest = a_dest;
1412         }
1413         GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1414                         Key a_key)
1415         {
1416                 dest = a_dest;
1417                 key = a_key;
1418         }
1419         ~GetRequest()
1420         {
1421         }
1422         
1423         Key key;
1424         ResultQueue<Key, T, Caller, CallerData> *dest;
1425         core::list<CallerInfo<Caller, CallerData> > callers;
1426 };
1427
1428 /*
1429         Quickhands for typical request-result queues.
1430         Used for distributing work between threads.
1431 */
1432
1433 template<typename Key, typename T, typename Caller, typename CallerData>
1434 class RequestQueue
1435 {
1436 public:
1437         u32 size()
1438         {
1439                 return m_queue.size();
1440         }
1441
1442         void add(Key key, Caller caller, CallerData callerdata,
1443                         ResultQueue<Key, T, Caller, CallerData> *dest)
1444         {
1445                 JMutexAutoLock lock(m_queue.getMutex());
1446                 
1447                 /*
1448                         If the caller is already on the list, only update CallerData
1449                 */
1450                 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1451                                 i = m_queue.getList().begin();
1452                                 i != m_queue.getList().end(); i++)
1453                 {
1454                         GetRequest<Key, T, Caller, CallerData> &request = *i;
1455
1456                         if(request.key == key)
1457                         {
1458                                 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1459                                                 i = request.callers.begin();
1460                                                 i != request.callers.end(); i++)
1461                                 {
1462                                         CallerInfo<Caller, CallerData> &ca = *i;
1463                                         if(ca.caller == caller)
1464                                         {
1465                                                 ca.data = callerdata;
1466                                                 return;
1467                                         }
1468                                 }
1469                                 CallerInfo<Caller, CallerData> ca;
1470                                 ca.caller = caller;
1471                                 ca.data = callerdata;
1472                                 request.callers.push_back(ca);
1473                                 return;
1474                         }
1475                 }
1476
1477                 /*
1478                         Else add a new request to the queue
1479                 */
1480
1481                 GetRequest<Key, T, Caller, CallerData> request;
1482                 request.key = key;
1483                 CallerInfo<Caller, CallerData> ca;
1484                 ca.caller = caller;
1485                 ca.data = callerdata;
1486                 request.callers.push_back(ca);
1487                 request.dest = dest;
1488                 
1489                 m_queue.getList().push_back(request);
1490         }
1491
1492         GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1493         {
1494                 return m_queue.pop_front(wait_if_empty);
1495         }
1496
1497 private:
1498         MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1499 };
1500
1501 /*
1502         Pseudo-random (VC++ rand() sucks)
1503 */
1504 int myrand(void);
1505 void mysrand(unsigned seed);
1506 #define MYRAND_MAX 32767
1507
1508 inline int myrand_range(int min, int max)
1509 {
1510         if(min > max)
1511         {
1512                 assert(0);
1513                 return max;
1514         }
1515         return (myrand()%(max-min+1))+min;
1516 }
1517
1518 /*
1519         Miscellaneous functions
1520 */
1521
1522 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
1523                 f32 *distance_ptr=NULL);
1524
1525 /*
1526         Queue with unique values with fast checking of value existence
1527 */
1528
1529 template<typename Value>
1530 class UniqueQueue
1531 {
1532 public:
1533         
1534         /*
1535                 Does nothing if value is already queued.
1536                 Return value:
1537                         true: value added
1538                         false: value already exists
1539         */
1540         bool push_back(Value value)
1541         {
1542                 // Check if already exists
1543                 if(m_map.find(value) != NULL)
1544                         return false;
1545
1546                 // Add
1547                 m_map.insert(value, 0);
1548                 m_list.push_back(value);
1549                 
1550                 return true;
1551         }
1552
1553         Value pop_front()
1554         {
1555                 typename core::list<Value>::Iterator i = m_list.begin();
1556                 Value value = *i;
1557                 m_map.remove(value);
1558                 m_list.erase(i);
1559                 return value;
1560         }
1561
1562         u32 size()
1563         {
1564                 assert(m_list.size() == m_map.size());
1565                 return m_list.size();
1566         }
1567
1568 private:
1569         core::map<Value, u8> m_map;
1570         core::list<Value> m_list;
1571 };
1572
1573 #if 0
1574 template<typename Key, typename Value>
1575 class MutexedCache
1576 {
1577 public:
1578         MutexedCache()
1579         {
1580                 m_mutex.Init();
1581                 assert(m_mutex.IsInitialized());
1582         }
1583         
1584         void set(const Key &name, const Value &value)
1585         {
1586                 JMutexAutoLock lock(m_mutex);
1587
1588                 m_values[name] = value;
1589         }
1590         
1591         bool get(const Key &name, Value *result)
1592         {
1593                 JMutexAutoLock lock(m_mutex);
1594
1595                 typename core::map<Key, Value>::Node *n;
1596                 n = m_values.find(name);
1597
1598                 if(n == NULL)
1599                         return false;
1600
1601                 *result = n->getValue();
1602                 return true;
1603         }
1604
1605 private:
1606         core::map<Key, Value> m_values;
1607         JMutex m_mutex;
1608 };
1609 #endif
1610
1611 /*
1612         Generates ids for comparable values.
1613         Id=0 is reserved for "no value".
1614
1615         Is fast at:
1616         - Returning value by id (very fast)
1617         - Returning id by value
1618         - Generating a new id for a value
1619
1620         Is not able to:
1621         - Remove an id/value pair (is possible to implement but slow)
1622 */
1623 template<typename T>
1624 class MutexedIdGenerator
1625 {
1626 public:
1627         MutexedIdGenerator()
1628         {
1629                 m_mutex.Init();
1630                 assert(m_mutex.IsInitialized());
1631         }
1632         
1633         // Returns true if found
1634         bool getValue(u32 id, T &value)
1635         {
1636                 if(id == 0)
1637                         return false;
1638                 JMutexAutoLock lock(m_mutex);
1639                 if(m_id_to_value.size() < id)
1640                         return false;
1641                 value = m_id_to_value[id-1];
1642                 return true;
1643         }
1644         
1645         // If id exists for value, returns the id.
1646         // Otherwise generates an id for the value.
1647         u32 getId(const T &value)
1648         {
1649                 JMutexAutoLock lock(m_mutex);
1650                 typename core::map<T, u32>::Node *n;
1651                 n = m_value_to_id.find(value);
1652                 if(n != NULL)
1653                         return n->getValue();
1654                 m_id_to_value.push_back(value);
1655                 u32 new_id = m_id_to_value.size();
1656                 m_value_to_id.insert(value, new_id);
1657                 return new_id;
1658         }
1659
1660 private:
1661         JMutex m_mutex;
1662         // Values are stored here at id-1 position (id 1 = [0])
1663         core::array<T> m_id_to_value;
1664         core::map<T, u32> m_value_to_id;
1665 };
1666
1667 /*
1668         Checks if a string contains only supplied characters
1669 */
1670 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1671 {
1672         for(u32 i=0; i<s.size(); i++)
1673         {
1674                 bool confirmed = false;
1675                 for(u32 j=0; j<allowed_chars.size(); j++)
1676                 {
1677                         if(s[i] == allowed_chars[j])
1678                         {
1679                                 confirmed = true;
1680                                 break;
1681                         }
1682                 }
1683                 if(confirmed == false)
1684                         return false;
1685         }
1686         return true;
1687 }
1688
1689 /*
1690         Some helper stuff
1691 */
1692 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1693 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1694
1695 #endif
1696