]> git.lizzy.rs Git - dragonfireclient.git/blob - src/utility.h
Working version before block send priorization update
[dragonfireclient.git] / src / utility.h
1 /*
2 (c) 2010 Perttu Ahola <celeron55@gmail.com>
3 */
4
5 #ifndef UTILITY_HEADER
6 #define UTILITY_HEADER
7
8 #include "common_irrlicht.h"
9 #include "debug.h"
10 #include "strfnd.h"
11 #include <iostream>
12 #include <string>
13
14 extern const v3s16 g_26dirs[26];
15
16 inline void writeU32(u8 *data, u32 i)
17 {
18         data[0] = ((i>>24)&0xff);
19         data[1] = ((i>>16)&0xff);
20         data[2] = ((i>> 8)&0xff);
21         data[3] = ((i>> 0)&0xff);
22 }
23
24 inline void writeU16(u8 *data, u16 i)
25 {
26         data[0] = ((i>> 8)&0xff);
27         data[1] = ((i>> 0)&0xff);
28 }
29
30 inline void writeU8(u8 *data, u8 i)
31 {
32         data[0] = ((i>> 0)&0xff);
33 }
34
35 inline u32 readU32(u8 *data)
36 {
37         return (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | (data[3]<<0);
38 }
39
40 inline u16 readU16(u8 *data)
41 {
42         return (data[0]<<8) | (data[1]<<0);
43 }
44
45 inline u8 readU8(u8 *data)
46 {
47         return (data[0]<<0);
48 }
49
50 // Signed variants of the above
51
52 inline void writeS32(u8 *data, s32 i){
53         writeU32(data, (u32)i);
54 }
55 inline s32 readS32(u8 *data){
56         return (s32)readU32(data);
57 }
58
59 inline void writeS16(u8 *data, s16 i){
60         writeU16(data, (u16)i);
61 }
62 inline s16 readS16(u8 *data){
63         return (s16)readU16(data);
64 }
65
66 inline void writeV3S32(u8 *data, v3s32 p)
67 {
68         writeS32(&data[0], p.X);
69         writeS32(&data[4], p.Y);
70         writeS32(&data[8], p.Z);
71 }
72
73 inline v3s32 readV3S32(u8 *data)
74 {
75         v3s32 p;
76         p.X = readS32(&data[0]);
77         p.Y = readS32(&data[4]);
78         p.Z = readS32(&data[8]);
79         return p;
80 }
81
82 inline void writeV2S16(u8 *data, v2s16 p)
83 {
84         writeS16(&data[0], p.X);
85         writeS16(&data[2], p.Y);
86 }
87
88 inline v2s16 readV2S16(u8 *data)
89 {
90         v2s16 p;
91         p.X = readS16(&data[0]);
92         p.Y = readS16(&data[2]);
93         return p;
94 }
95
96 inline void writeV2S32(u8 *data, v2s32 p)
97 {
98         writeS32(&data[0], p.X);
99         writeS32(&data[2], p.Y);
100 }
101
102 inline v2s32 readV2S32(u8 *data)
103 {
104         v2s32 p;
105         p.X = readS32(&data[0]);
106         p.Y = readS32(&data[2]);
107         return p;
108 }
109
110 inline void writeV3S16(u8 *data, v3s16 p)
111 {
112         writeS16(&data[0], p.X);
113         writeS16(&data[2], p.Y);
114         writeS16(&data[4], p.Z);
115 }
116
117 inline v3s16 readV3S16(u8 *data)
118 {
119         v3s16 p;
120         p.X = readS16(&data[0]);
121         p.Y = readS16(&data[2]);
122         p.Z = readS16(&data[4]);
123         return p;
124 }
125
126 /*
127         None of these are used at the moment
128 */
129
130 template <typename T>
131 class SharedPtr
132 {
133 public:
134         SharedPtr(T *t=NULL)
135         {
136                 refcount = new int;
137                 *refcount = 1;
138                 ptr = t;
139         }
140         SharedPtr(SharedPtr<T> &t)
141         {
142                 //*this = t;
143                 drop();
144                 refcount = t.refcount;
145                 (*refcount)++;
146                 ptr = t.ptr;
147         }
148         ~SharedPtr()
149         {
150                 drop();
151         }
152         SharedPtr<T> & operator=(T *t)
153         {
154                 drop();
155                 refcount = new int;
156                 *refcount = 1;
157                 ptr = t;
158                 return *this;
159         }
160         SharedPtr<T> & operator=(SharedPtr<T> &t)
161         {
162                 drop();
163                 refcount = t.refcount;
164                 (*refcount)++;
165                 ptr = t.ptr;
166                 return *this;
167         }
168         T* operator->()
169         {
170                 return ptr;
171         }
172         T & operator*()
173         {
174                 return *ptr;
175         }
176         bool operator!=(T *t)
177         {
178                 return ptr != t;
179         }
180         bool operator==(T *t)
181         {
182                 return ptr == t;
183         }
184 private:
185         void drop()
186         {
187                 assert((*refcount) > 0);
188                 (*refcount)--;
189                 if(*refcount == 0)
190                 {
191                         delete refcount;
192                         if(ptr != NULL)
193                                 delete ptr;
194                 }
195         }
196         T *ptr;
197         int *refcount;
198 };
199
200 template <typename T>
201 class Buffer
202 {
203 public:
204         Buffer(unsigned int size)
205         {
206                 m_size = size;
207                 data = new T[size];
208         }
209         Buffer(const Buffer &buffer)
210         {
211                 m_size = buffer.m_size;
212                 data = new T[buffer.m_size];
213                 memcpy(data, buffer.data, buffer.m_size);
214         }
215         Buffer(T *t, unsigned int size)
216         {
217                 m_size = size;
218                 data = new T[size];
219                 memcpy(data, t, size);
220         }
221         ~Buffer()
222         {
223                 delete[] data;
224         }
225         T & operator[](unsigned int i) const
226         {
227                 return data[i];
228         }
229         T * operator*() const
230         {
231                 return data;
232         }
233         unsigned int getSize() const
234         {
235                 return m_size;
236         }
237 private:
238         T *data;
239         unsigned int m_size;
240 };
241
242 template <typename T>
243 class SharedBuffer
244 {
245 public:
246         SharedBuffer(unsigned int size)
247         {
248                 m_size = size;
249                 data = new T[size];
250                 refcount = new unsigned int;
251                 (*refcount) = 1;
252         }
253         SharedBuffer(const SharedBuffer &buffer)
254         {
255                 //std::cout<<"SharedBuffer(const SharedBuffer &buffer)"<<std::endl;
256                 m_size = buffer.m_size;
257                 data = buffer.data;
258                 refcount = buffer.refcount;
259                 (*refcount)++;
260         }
261         SharedBuffer & operator=(const SharedBuffer & buffer)
262         {
263                 //std::cout<<"SharedBuffer & operator=(const SharedBuffer & buffer)"<<std::endl;
264                 if(this == &buffer)
265                         return *this;
266                 drop();
267                 m_size = buffer.m_size;
268                 data = buffer.data;
269                 refcount = buffer.refcount;
270                 (*refcount)++;
271                 return *this;
272         }
273         /*
274                 Copies whole buffer
275         */
276         SharedBuffer(T *t, unsigned int size)
277         {
278                 m_size = size;
279                 data = new T[size];
280                 memcpy(data, t, size);
281                 refcount = new unsigned int;
282                 (*refcount) = 1;
283         }
284         /*
285                 Copies whole buffer
286         */
287         SharedBuffer(const Buffer<T> &buffer)
288         {
289                 m_size = buffer.m_size;
290                 data = new T[buffer.getSize()];
291                 memcpy(data, *buffer, buffer.getSize());
292                 refcount = new unsigned int;
293                 (*refcount) = 1;
294         }
295         ~SharedBuffer()
296         {
297                 drop();
298         }
299         T & operator[](unsigned int i) const
300         {
301                 return data[i];
302         }
303         T * operator*() const
304         {
305                 return data;
306         }
307         unsigned int getSize() const
308         {
309                 return m_size;
310         }
311 private:
312         void drop()
313         {
314                 assert((*refcount) > 0);
315                 (*refcount)--;
316                 if(*refcount == 0)
317                 {
318                         delete[] data;
319                         delete refcount;
320                 }
321         }
322         T *data;
323         unsigned int m_size;
324         unsigned int *refcount;
325 };
326
327 inline SharedBuffer<u8> SharedBufferFromString(const char *string)
328 {
329         SharedBuffer<u8> b((u8*)string, strlen(string)+1);
330         return b;
331 }
332
333 template<typename T>
334 class MutexedVariable
335 {
336 public:
337         MutexedVariable(T value):
338                 m_value(value)
339         {
340                 m_mutex.Init();
341         }
342
343         T get()
344         {
345                 JMutexAutoLock lock(m_mutex);
346                 return m_value;
347         }
348
349         void set(T value)
350         {
351                 JMutexAutoLock lock(m_mutex);
352                 m_value = value;
353         }
354         
355         // You'll want to grab this in a SharedPtr
356         JMutexAutoLock * getLock()
357         {
358                 return new JMutexAutoLock(m_mutex);
359         }
360         
361         // You pretty surely want to grab the lock when accessing this
362         T m_value;
363
364 private:
365         JMutex m_mutex;
366 };
367
368 /*
369         TimeTaker
370 */
371
372 class TimeTaker
373 {
374 public:
375         TimeTaker(const char *name, IrrlichtDevice *dev)
376         {
377                 m_name = name;
378                 m_dev = dev;
379                 m_time1 = m_dev->getTimer()->getRealTime();
380                 m_running = true;
381         }
382         ~TimeTaker()
383         {
384                 stop();
385         }
386         u32 stop(bool quiet=false)
387         {
388                 if(m_running)
389                 {
390                         u32 time2 = m_dev->getTimer()->getRealTime();
391                         u32 dtime = time2 - m_time1;
392                         if(quiet == false)
393                                 std::cout<<m_name<<" took "<<dtime<<"ms"<<std::endl;
394                         m_running = false;
395                         return dtime;
396                 }
397                 return 0;
398         }
399 private:
400         const char *m_name;
401         IrrlichtDevice *m_dev;
402         u32 m_time1;
403         bool m_running;
404 };
405
406 // Calculates the borders of a "d-radius" cube
407 inline void getFacePositions(core::list<v3s16> &list, u16 d)
408 {
409         if(d == 0)
410         {
411                 list.push_back(v3s16(0,0,0));
412                 return;
413         }
414         if(d == 1)
415         {
416                 /*
417                         This is an optimized sequence of coordinates.
418                 */
419                 list.push_back(v3s16( 0, 0, 1)); // back
420                 list.push_back(v3s16(-1, 0, 0)); // left
421                 list.push_back(v3s16( 1, 0, 0)); // right
422                 list.push_back(v3s16( 0, 0,-1)); // front
423                 list.push_back(v3s16( 0,-1, 0)); // bottom
424                 list.push_back(v3s16( 0, 1, 0)); // top
425                 // 6
426                 list.push_back(v3s16(-1, 0, 1)); // back left
427                 list.push_back(v3s16( 1, 0, 1)); // back right
428                 list.push_back(v3s16(-1, 0,-1)); // front left
429                 list.push_back(v3s16( 1, 0,-1)); // front right
430                 list.push_back(v3s16(-1,-1, 0)); // bottom left
431                 list.push_back(v3s16( 1,-1, 0)); // bottom right
432                 list.push_back(v3s16( 0,-1, 1)); // bottom back
433                 list.push_back(v3s16( 0,-1,-1)); // bottom front
434                 list.push_back(v3s16(-1, 1, 0)); // top left
435                 list.push_back(v3s16( 1, 1, 0)); // top right
436                 list.push_back(v3s16( 0, 1, 1)); // top back
437                 list.push_back(v3s16( 0, 1,-1)); // top front
438                 // 18
439                 list.push_back(v3s16(-1, 1, 1)); // top back-left
440                 list.push_back(v3s16( 1, 1, 1)); // top back-right
441                 list.push_back(v3s16(-1, 1,-1)); // top front-left
442                 list.push_back(v3s16( 1, 1,-1)); // top front-right
443                 list.push_back(v3s16(-1,-1, 1)); // bottom back-left
444                 list.push_back(v3s16( 1,-1, 1)); // bottom back-right
445                 list.push_back(v3s16(-1,-1,-1)); // bottom front-left
446                 list.push_back(v3s16( 1,-1,-1)); // bottom front-right
447                 // 26
448                 return;
449         }
450
451         // Take blocks in all sides, starting from y=0 and going +-y
452         for(s16 y=0; y<=d-1; y++)
453         {
454                 // Left and right side, including borders
455                 for(s16 z=-d; z<=d; z++)
456                 {
457                         list.push_back(v3s16(d,y,z));
458                         list.push_back(v3s16(-d,y,z));
459                         if(y != 0)
460                         {
461                                 list.push_back(v3s16(d,-y,z));
462                                 list.push_back(v3s16(-d,-y,z));
463                         }
464                 }
465                 // Back and front side, excluding borders
466                 for(s16 x=-d+1; x<=d-1; x++)
467                 {
468                         list.push_back(v3s16(x,y,d));
469                         list.push_back(v3s16(x,y,-d));
470                         if(y != 0)
471                         {
472                                 list.push_back(v3s16(x,-y,d));
473                                 list.push_back(v3s16(x,-y,-d));
474                         }
475                 }
476         }
477
478         // Take the bottom and top face with borders
479         // -d<x<d, y=+-d, -d<z<d
480         for(s16 x=-d; x<=d; x++)
481         for(s16 z=-d; z<=d; z++)
482         {
483                 list.push_back(v3s16(x,-d,z));
484                 list.push_back(v3s16(x,d,z));
485         }
486 }
487
488 class IndentationRaiser
489 {
490 public:
491         IndentationRaiser(u16 *indentation)
492         {
493                 m_indentation = indentation;
494                 (*m_indentation)++;
495         }
496         ~IndentationRaiser()
497         {
498                 (*m_indentation)--;
499         }
500 private:
501         u16 *m_indentation;
502 };
503
504 inline s16 getContainerPos(s16 p, s16 d)
505 {
506         return (p>=0 ? p : p-d+1) / d;
507 }
508
509 inline v2s16 getContainerPos(v2s16 p, s16 d)
510 {
511         return v2s16(
512                 getContainerPos(p.X, d),
513                 getContainerPos(p.Y, d)
514         );
515 }
516
517 inline v3s16 getContainerPos(v3s16 p, s16 d)
518 {
519         return v3s16(
520                 getContainerPos(p.X, d),
521                 getContainerPos(p.Y, d),
522                 getContainerPos(p.Z, d)
523         );
524 }
525
526 inline bool isInArea(v3s16 p, s16 d)
527 {
528         return (
529                 p.X >= 0 && p.X < d &&
530                 p.Y >= 0 && p.Y < d &&
531                 p.Z >= 0 && p.Z < d
532         );
533 }
534
535 inline bool isInArea(v2s16 p, s16 d)
536 {
537         return (
538                 p.X >= 0 && p.X < d &&
539                 p.Y >= 0 && p.Y < d
540         );
541 }
542
543 inline std::wstring narrow_to_wide(const std::string& mbs)
544 {
545         size_t wcl = mbs.size();
546         SharedBuffer<wchar_t> wcs(wcl+1);
547         size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
548         wcs[l] = 0;
549         return *wcs;
550 }
551
552 inline std::string wide_to_narrow(const std::wstring& wcs)
553 {
554         size_t mbl = wcs.size()*4;
555         SharedBuffer<char> mbs(mbl+1);
556         size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
557         if((int)l == -1)
558                 mbs[0] = 0;
559         else
560                 mbs[l] = 0;
561         return *mbs;
562 }
563
564 /*
565         See test.cpp for example cases.
566         wraps degrees to the range of -360...360
567         NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
568 */
569 inline float wrapDegrees(float f)
570 {
571         // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
572         // This results in
573         // 10, 720, -1, -361
574         int i = floor(f);
575         // 0, 2, 0, -1
576         int l = i / 360;
577         // NOTE: This would be used for wrapping to 0...360
578         // 0, 2, -1, -2
579         /*if(i < 0)
580                 l -= 1;*/
581         // 0, 720, 0, -360
582         int k = l * 360;
583         // 10, 0.5, -0.5, -0.5
584         f -= float(k);
585         return f;
586 }
587
588 inline std::string lowercase(std::string s)
589 {
590         for(size_t i=0; i<s.size(); i++)
591         {
592                 if(s[i] >= 'A' && s[i] <= 'Z')
593                         s[i] -= 'A' - 'a';
594         }
595         return s;
596 }
597
598 inline bool is_yes(std::string s)
599 {
600         s = lowercase(trim(s));
601         if(s == "y" || s == "yes" || s == "true")
602                 return true;
603         return false;
604 }
605
606 inline s32 stoi(std::string s, s32 min, s32 max)
607 {
608         s32 i = atoi(s.c_str());
609         if(i < min)
610                 i = min;
611         if(i > max)
612                 i = max;
613         return i;
614 }
615
616 #endif
617