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