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