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