3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
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.
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.
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.
20 #ifndef UTILITY_HEADER
21 #define UTILITY_HEADER
30 #include <jmutexautolock.h>
33 #include "common_irrlicht.h"
35 #include "exceptions.h"
37 #include "strfnd.h" // For trim()
39 extern const v3s16 g_6dirs[6];
41 extern const v3s16 g_26dirs[26];
44 extern const v3s16 g_27dirs[27];
46 inline void writeU64(u8 *data, u64 i)
48 data[0] = ((i>>56)&0xff);
49 data[1] = ((i>>48)&0xff);
50 data[2] = ((i>>40)&0xff);
51 data[3] = ((i>>32)&0xff);
52 data[4] = ((i>>24)&0xff);
53 data[5] = ((i>>16)&0xff);
54 data[6] = ((i>> 8)&0xff);
55 data[7] = ((i>> 0)&0xff);
58 inline void writeU32(u8 *data, u32 i)
60 data[0] = ((i>>24)&0xff);
61 data[1] = ((i>>16)&0xff);
62 data[2] = ((i>> 8)&0xff);
63 data[3] = ((i>> 0)&0xff);
66 inline void writeU16(u8 *data, u16 i)
68 data[0] = ((i>> 8)&0xff);
69 data[1] = ((i>> 0)&0xff);
72 inline void writeU8(u8 *data, u8 i)
74 data[0] = ((i>> 0)&0xff);
77 inline u64 readU64(u8 *data)
79 return ((u64)data[0]<<56) | ((u64)data[1]<<48)
80 | ((u64)data[2]<<40) | ((u64)data[3]<<32)
81 | ((u64)data[4]<<24) | ((u64)data[5]<<16)
82 | ((u64)data[6]<<8) | ((u64)data[7]<<0);
85 inline u32 readU32(u8 *data)
87 return (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | (data[3]<<0);
90 inline u16 readU16(u8 *data)
92 return (data[0]<<8) | (data[1]<<0);
95 inline u8 readU8(u8 *data)
100 inline void writeS32(u8 *data, s32 i){
101 writeU32(data, (u32)i);
103 inline s32 readS32(u8 *data){
104 return (s32)readU32(data);
107 inline void writeS16(u8 *data, s16 i){
108 writeU16(data, (u16)i);
110 inline s16 readS16(u8 *data){
111 return (s16)readU16(data);
114 inline void writeS8(u8 *data, s8 i){
115 writeU8(data, (u8)i);
117 inline s8 readS8(u8 *data){
118 return (s8)readU8(data);
121 inline void writeF1000(u8 *data, f32 i){
122 writeS32(data, i*1000);
124 inline f32 readF1000(u8 *data){
125 return (f32)readS32(data)/1000.;
128 inline void writeV3S32(u8 *data, v3s32 p)
130 writeS32(&data[0], p.X);
131 writeS32(&data[4], p.Y);
132 writeS32(&data[8], p.Z);
134 inline v3s32 readV3S32(u8 *data)
137 p.X = readS32(&data[0]);
138 p.Y = readS32(&data[4]);
139 p.Z = readS32(&data[8]);
143 inline void writeV3F1000(u8 *data, v3f p)
145 writeF1000(&data[0], p.X);
146 writeF1000(&data[4], p.Y);
147 writeF1000(&data[8], p.Z);
149 inline v3f readV3F1000(u8 *data)
152 p.X = (float)readF1000(&data[0]);
153 p.Y = (float)readF1000(&data[4]);
154 p.Z = (float)readF1000(&data[8]);
158 inline void writeV2F1000(u8 *data, v2f p)
160 writeF1000(&data[0], p.X);
161 writeF1000(&data[4], p.Y);
163 inline v2f readV2F1000(u8 *data)
166 p.X = (float)readF1000(&data[0]);
167 p.Y = (float)readF1000(&data[4]);
171 inline void writeV2S16(u8 *data, v2s16 p)
173 writeS16(&data[0], p.X);
174 writeS16(&data[2], p.Y);
177 inline v2s16 readV2S16(u8 *data)
180 p.X = readS16(&data[0]);
181 p.Y = readS16(&data[2]);
185 inline void writeV2S32(u8 *data, v2s32 p)
187 writeS32(&data[0], p.X);
188 writeS32(&data[2], p.Y);
191 inline v2s32 readV2S32(u8 *data)
194 p.X = readS32(&data[0]);
195 p.Y = readS32(&data[2]);
199 inline void writeV3S16(u8 *data, v3s16 p)
201 writeS16(&data[0], p.X);
202 writeS16(&data[2], p.Y);
203 writeS16(&data[4], p.Z);
206 inline v3s16 readV3S16(u8 *data)
209 p.X = readS16(&data[0]);
210 p.Y = readS16(&data[2]);
211 p.Z = readS16(&data[4]);
216 The above stuff directly interfaced to iostream
219 inline void writeU8(std::ostream &os, u8 p)
222 writeU8((u8*)buf, p);
225 inline u8 readU8(std::istream &is)
229 return readU8((u8*)buf);
232 inline void writeU16(std::ostream &os, u16 p)
235 writeU16((u8*)buf, p);
238 inline u16 readU16(std::istream &is)
242 return readU16((u8*)buf);
245 inline void writeU32(std::ostream &os, u32 p)
248 writeU32((u8*)buf, p);
251 inline u32 readU32(std::istream &is)
255 return readU32((u8*)buf);
258 inline void writeS32(std::ostream &os, s32 p)
261 writeS32((u8*)buf, p);
264 inline s32 readS32(std::istream &is)
268 return readS32((u8*)buf);
271 inline void writeS16(std::ostream &os, s16 p)
274 writeS16((u8*)buf, p);
277 inline s16 readS16(std::istream &is)
281 return readS16((u8*)buf);
284 inline void writeS8(std::ostream &os, s8 p)
287 writeS8((u8*)buf, p);
290 inline s8 readS8(std::istream &is)
294 return readS8((u8*)buf);
297 inline void writeF1000(std::ostream &os, f32 p)
300 writeF1000((u8*)buf, p);
303 inline f32 readF1000(std::istream &is)
307 return readF1000((u8*)buf);
310 inline void writeV3F1000(std::ostream &os, v3f p)
313 writeV3F1000((u8*)buf, p);
316 inline v3f readV3F1000(std::istream &is)
320 return readV3F1000((u8*)buf);
323 inline void writeV2F1000(std::ostream &os, v2f p)
326 writeV2F1000((u8*)buf, p);
329 inline v2f readV2F1000(std::istream &is)
333 return readV2F1000((u8*)buf);
336 inline void writeV2S16(std::ostream &os, v2s16 p)
339 writeV2S16((u8*)buf, p);
342 inline v2s16 readV2S16(std::istream &is)
346 return readV2S16((u8*)buf);
349 inline void writeV3S16(std::ostream &os, v3s16 p)
352 writeV3S16((u8*)buf, p);
355 inline v3s16 readV3S16(std::istream &is)
359 return readV3S16((u8*)buf);
363 None of these are used at the moment
366 template <typename T>
376 SharedPtr(SharedPtr<T> &t)
380 refcount = t.refcount;
388 SharedPtr<T> & operator=(T *t)
396 SharedPtr<T> & operator=(SharedPtr<T> &t)
399 refcount = t.refcount;
412 bool operator!=(T *t)
416 bool operator==(T *t)
420 T & operator[](unsigned int i)
427 assert((*refcount) > 0);
440 template <typename T>
449 Buffer(unsigned int size)
457 Buffer(const Buffer &buffer)
459 m_size = buffer.m_size;
462 data = new T[buffer.m_size];
463 memcpy(data, buffer.data, buffer.m_size);
468 Buffer(const T *t, unsigned int size)
474 memcpy(data, t, size);
483 Buffer& operator=(const Buffer &buffer)
488 m_size = buffer.m_size;
491 data = new T[buffer.m_size];
492 memcpy(data, buffer.data, buffer.m_size);
498 T & operator[](unsigned int i) const
502 T * operator*() const
506 unsigned int getSize() const
520 template <typename T>
528 refcount = new unsigned int;
531 SharedBuffer(unsigned int size)
535 data = new T[m_size];
538 refcount = new unsigned int;
541 SharedBuffer(const SharedBuffer &buffer)
543 //std::cout<<"SharedBuffer(const SharedBuffer &buffer)"<<std::endl;
544 m_size = buffer.m_size;
546 refcount = buffer.refcount;
549 SharedBuffer & operator=(const SharedBuffer & buffer)
551 //std::cout<<"SharedBuffer & operator=(const SharedBuffer & buffer)"<<std::endl;
555 m_size = buffer.m_size;
557 refcount = buffer.refcount;
564 SharedBuffer(T *t, unsigned int size)
569 data = new T[m_size];
570 memcpy(data, t, m_size);
574 refcount = new unsigned int;
580 SharedBuffer(const Buffer<T> &buffer)
582 m_size = buffer.getSize();
585 data = new T[m_size];
586 memcpy(data, *buffer, buffer.getSize());
590 refcount = new unsigned int;
597 T & operator[](unsigned int i) const
602 T * operator*() const
606 unsigned int getSize() const
610 operator Buffer<T>() const
612 return Buffer<T>(data, m_size);
617 assert((*refcount) > 0);
628 unsigned int *refcount;
631 inline SharedBuffer<u8> SharedBufferFromString(const char *string)
633 SharedBuffer<u8> b((u8*)string, strlen(string)+1);
638 class MutexedVariable
641 MutexedVariable(T value):
649 JMutexAutoLock lock(m_mutex);
655 JMutexAutoLock lock(m_mutex);
659 // You'll want to grab this in a SharedPtr
660 JMutexAutoLock * getLock()
662 return new JMutexAutoLock(m_mutex);
665 // You pretty surely want to grab the lock when accessing this
679 TimeTaker(const char *name, u32 *result=NULL);
686 u32 stop(bool quiet=false);
698 // Sets the color of all vertices in the mesh
699 void setMeshVerticesColor(scene::IMesh* mesh, video::SColor& color);
702 // Calculates the borders of a "d-radius" cube
703 inline void getFacePositions(core::list<v3s16> &list, u16 d)
707 list.push_back(v3s16(0,0,0));
713 This is an optimized sequence of coordinates.
715 list.push_back(v3s16( 0, 1, 0)); // top
716 list.push_back(v3s16( 0, 0, 1)); // back
717 list.push_back(v3s16(-1, 0, 0)); // left
718 list.push_back(v3s16( 1, 0, 0)); // right
719 list.push_back(v3s16( 0, 0,-1)); // front
720 list.push_back(v3s16( 0,-1, 0)); // bottom
722 list.push_back(v3s16(-1, 0, 1)); // back left
723 list.push_back(v3s16( 1, 0, 1)); // back right
724 list.push_back(v3s16(-1, 0,-1)); // front left
725 list.push_back(v3s16( 1, 0,-1)); // front right
726 list.push_back(v3s16(-1,-1, 0)); // bottom left
727 list.push_back(v3s16( 1,-1, 0)); // bottom right
728 list.push_back(v3s16( 0,-1, 1)); // bottom back
729 list.push_back(v3s16( 0,-1,-1)); // bottom front
730 list.push_back(v3s16(-1, 1, 0)); // top left
731 list.push_back(v3s16( 1, 1, 0)); // top right
732 list.push_back(v3s16( 0, 1, 1)); // top back
733 list.push_back(v3s16( 0, 1,-1)); // top front
735 list.push_back(v3s16(-1, 1, 1)); // top back-left
736 list.push_back(v3s16( 1, 1, 1)); // top back-right
737 list.push_back(v3s16(-1, 1,-1)); // top front-left
738 list.push_back(v3s16( 1, 1,-1)); // top front-right
739 list.push_back(v3s16(-1,-1, 1)); // bottom back-left
740 list.push_back(v3s16( 1,-1, 1)); // bottom back-right
741 list.push_back(v3s16(-1,-1,-1)); // bottom front-left
742 list.push_back(v3s16( 1,-1,-1)); // bottom front-right
747 // Take blocks in all sides, starting from y=0 and going +-y
748 for(s16 y=0; y<=d-1; y++)
750 // Left and right side, including borders
751 for(s16 z=-d; z<=d; z++)
753 list.push_back(v3s16(d,y,z));
754 list.push_back(v3s16(-d,y,z));
757 list.push_back(v3s16(d,-y,z));
758 list.push_back(v3s16(-d,-y,z));
761 // Back and front side, excluding borders
762 for(s16 x=-d+1; x<=d-1; x++)
764 list.push_back(v3s16(x,y,d));
765 list.push_back(v3s16(x,y,-d));
768 list.push_back(v3s16(x,-y,d));
769 list.push_back(v3s16(x,-y,-d));
774 // Take the bottom and top face with borders
775 // -d<x<d, y=+-d, -d<z<d
776 for(s16 x=-d; x<=d; x++)
777 for(s16 z=-d; z<=d; z++)
779 list.push_back(v3s16(x,-d,z));
780 list.push_back(v3s16(x,d,z));
784 class IndentationRaiser
787 IndentationRaiser(u16 *indentation)
789 m_indentation = indentation;
800 inline s16 getContainerPos(s16 p, s16 d)
802 return (p>=0 ? p : p-d+1) / d;
805 inline v2s16 getContainerPos(v2s16 p, s16 d)
808 getContainerPos(p.X, d),
809 getContainerPos(p.Y, d)
813 inline v3s16 getContainerPos(v3s16 p, s16 d)
816 getContainerPos(p.X, d),
817 getContainerPos(p.Y, d),
818 getContainerPos(p.Z, d)
822 inline v2s16 getContainerPos(v2s16 p, v2s16 d)
825 getContainerPos(p.X, d.X),
826 getContainerPos(p.Y, d.Y)
830 inline v3s16 getContainerPos(v3s16 p, v3s16 d)
833 getContainerPos(p.X, d.X),
834 getContainerPos(p.Y, d.Y),
835 getContainerPos(p.Z, d.Z)
839 inline bool isInArea(v3s16 p, s16 d)
842 p.X >= 0 && p.X < d &&
843 p.Y >= 0 && p.Y < d &&
848 inline bool isInArea(v2s16 p, s16 d)
851 p.X >= 0 && p.X < d &&
856 inline bool isInArea(v3s16 p, v3s16 d)
859 p.X >= 0 && p.X < d.X &&
860 p.Y >= 0 && p.Y < d.Y &&
861 p.Z >= 0 && p.Z < d.Z
865 inline s16 rangelim(s16 i, s16 max)
874 #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
876 inline v3s16 arealim(v3s16 p, s16 d)
893 inline std::wstring narrow_to_wide(const std::string& mbs)
895 size_t wcl = mbs.size();
896 Buffer<wchar_t> wcs(wcl+1);
897 size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
898 if(l == (size_t)(-1))
899 return L"<invalid multibyte string>";
904 inline std::string wide_to_narrow(const std::wstring& wcs)
906 size_t mbl = wcs.size()*4;
907 SharedBuffer<char> mbs(mbl+1);
908 size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
909 if(l == (size_t)(-1))
916 // Split a string using the given delimiter. Returns a vector containing
917 // the component parts.
918 inline std::vector<std::wstring> str_split(const std::wstring &str, wchar_t delimiter)
920 std::vector<std::wstring> parts;
921 std::wstringstream sstr(str);
923 while(std::getline(sstr, part, delimiter))
924 parts.push_back(part);
930 See test.cpp for example cases.
931 wraps degrees to the range of -360...360
932 NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
934 inline float wrapDegrees(float f)
936 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
942 // NOTE: This would be used for wrapping to 0...360
948 // 10, 0.5, -0.5, -0.5
953 /* Wrap to 0...360 */
954 inline float wrapDegrees_0_360(float f)
956 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
968 // 10, 0.5, -0.5, -0.5
973 /* Wrap to -180...180 */
974 inline float wrapDegrees_180(float f)
977 f = wrapDegrees_0_360(f);
982 inline std::string lowercase(const std::string &s)
985 for(size_t i=0; i<s.size(); i++)
988 if(c >= 'A' && c <= 'Z')
995 inline bool is_yes(const std::string &s)
997 std::string s2 = lowercase(trim(s));
998 if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
1003 inline s32 mystoi(const std::string &s, s32 min, s32 max)
1005 s32 i = atoi(s.c_str());
1014 // MSVC2010 includes it's own versions of these
1015 //#if !defined(_MSC_VER) || _MSC_VER < 1600
1017 inline s32 mystoi(std::string s)
1019 return atoi(s.c_str());
1022 inline s32 mystoi(std::wstring s)
1024 return atoi(wide_to_narrow(s).c_str());
1027 inline float mystof(std::string s)
1030 std::istringstream ss(s);
1040 inline std::string itos(s32 i)
1042 std::ostringstream o;
1047 inline std::string ftos(float f)
1049 std::ostringstream o;
1054 inline void str_replace(std::string & str, std::string const & pattern,
1055 std::string const & replacement)
1057 std::string::size_type start = str.find(pattern, 0);
1058 while(start != str.npos)
1060 str.replace(start, pattern.size(), replacement);
1061 start = str.find(pattern, start+replacement.size());
1065 inline void str_replace_char(std::string & str, char from, char to)
1067 for(unsigned int i=0; i<str.size(); i++)
1075 A base class for simple background thread implementation
1078 class SimpleThread : public JThread
1092 virtual ~SimpleThread()
1095 virtual void * Thread() = 0;
1099 JMutexAutoLock lock(run_mutex);
1102 void setRun(bool a_run)
1104 JMutexAutoLock lock(run_mutex);
1117 FIFO queue (well, actually a FILO also)
1119 template<typename T>
1125 m_list.push_back(t);
1130 if(m_list.size() == 0)
1131 throw ItemNotFoundException("Queue: queue is empty");
1133 typename core::list<T>::Iterator begin = m_list.begin();
1135 m_list.erase(begin);
1140 if(m_list.size() == 0)
1141 throw ItemNotFoundException("Queue: queue is empty");
1143 typename core::list<T>::Iterator last = m_list.getLast();
1151 return m_list.size();
1155 core::list<T> m_list;
1159 Thread-safe FIFO queue (well, actually a FILO also)
1162 template<typename T>
1172 JMutexAutoLock lock(m_mutex);
1173 return m_list.size();
1177 JMutexAutoLock lock(m_mutex);
1178 m_list.push_back(t);
1180 T pop_front(u32 wait_time_max_ms=0)
1182 u32 wait_time_ms = 0;
1187 JMutexAutoLock lock(m_mutex);
1189 if(m_list.size() > 0)
1191 typename core::list<T>::Iterator begin = m_list.begin();
1193 m_list.erase(begin);
1197 if(wait_time_ms >= wait_time_max_ms)
1198 throw ItemNotFoundException("MutexedQueue: queue is empty");
1201 // Wait a while before trying again
1206 T pop_back(u32 wait_time_max_ms=0)
1208 u32 wait_time_ms = 0;
1213 JMutexAutoLock lock(m_mutex);
1215 if(m_list.size() > 0)
1217 typename core::list<T>::Iterator last = m_list.getLast();
1223 if(wait_time_ms >= wait_time_max_ms)
1224 throw ItemNotFoundException("MutexedQueue: queue is empty");
1227 // Wait a while before trying again
1238 core::list<T> & getList()
1245 core::list<T> m_list;
1249 A single worker thread - multiple client threads queue framework.
1252 template<typename Caller, typename Data>
1260 template<typename Key, typename T, typename Caller, typename CallerData>
1266 core::list<CallerInfo<Caller, CallerData> > callers;
1269 template<typename Key, typename T, typename Caller, typename CallerData>
1270 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1274 template<typename Key, typename T, typename Caller, typename CallerData>
1282 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1286 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1297 ResultQueue<Key, T, Caller, CallerData> *dest;
1298 core::list<CallerInfo<Caller, CallerData> > callers;
1301 template<typename Key, typename T, typename Caller, typename CallerData>
1307 return m_queue.size();
1310 void add(Key key, Caller caller, CallerData callerdata,
1311 ResultQueue<Key, T, Caller, CallerData> *dest)
1313 JMutexAutoLock lock(m_queue.getMutex());
1316 If the caller is already on the list, only update CallerData
1318 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1319 i = m_queue.getList().begin();
1320 i != m_queue.getList().end(); i++)
1322 GetRequest<Key, T, Caller, CallerData> &request = *i;
1324 if(request.key == key)
1326 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1327 i = request.callers.begin();
1328 i != request.callers.end(); i++)
1330 CallerInfo<Caller, CallerData> &ca = *i;
1331 if(ca.caller == caller)
1333 ca.data = callerdata;
1337 CallerInfo<Caller, CallerData> ca;
1339 ca.data = callerdata;
1340 request.callers.push_back(ca);
1346 Else add a new request to the queue
1349 GetRequest<Key, T, Caller, CallerData> request;
1351 CallerInfo<Caller, CallerData> ca;
1353 ca.data = callerdata;
1354 request.callers.push_back(ca);
1355 request.dest = dest;
1357 m_queue.getList().push_back(request);
1360 GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1362 return m_queue.pop_front(wait_if_empty);
1366 MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1370 Pseudo-random (VC++ rand() sucks)
1373 void mysrand(unsigned seed);
1374 #define MYRAND_MAX 32767
1376 int myrand_range(int min, int max);
1379 Miscellaneous functions
1382 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
1383 f32 camera_fov, f32 range, f32 *distance_ptr=NULL);
1386 Queue with unique values with fast checking of value existence
1389 template<typename Value>
1395 Does nothing if value is already queued.
1398 false: value already exists
1400 bool push_back(Value value)
1402 // Check if already exists
1403 if(m_map.find(value) != NULL)
1407 m_map.insert(value, 0);
1408 m_list.push_back(value);
1415 typename core::list<Value>::Iterator i = m_list.begin();
1417 m_map.remove(value);
1424 assert(m_list.size() == m_map.size());
1425 return m_list.size();
1429 core::map<Value, u8> m_map;
1430 core::list<Value> m_list;
1434 template<typename Key, typename Value>
1441 assert(m_mutex.IsInitialized());
1444 void set(const Key &name, const Value &value)
1446 JMutexAutoLock lock(m_mutex);
1448 m_values[name] = value;
1451 bool get(const Key &name, Value *result)
1453 JMutexAutoLock lock(m_mutex);
1455 typename core::map<Key, Value>::Node *n;
1456 n = m_values.find(name);
1462 *result = n->getValue();
1468 core::map<Key, Value> m_values;
1474 Generates ids for comparable values.
1475 Id=0 is reserved for "no value".
1478 - Returning value by id (very fast)
1479 - Returning id by value
1480 - Generating a new id for a value
1483 - Remove an id/value pair (is possible to implement but slow)
1485 template<typename T>
1486 class MutexedIdGenerator
1489 MutexedIdGenerator()
1492 assert(m_mutex.IsInitialized());
1495 // Returns true if found
1496 bool getValue(u32 id, T &value)
1500 JMutexAutoLock lock(m_mutex);
1501 if(m_id_to_value.size() < id)
1503 value = m_id_to_value[id-1];
1507 // If id exists for value, returns the id.
1508 // Otherwise generates an id for the value.
1509 u32 getId(const T &value)
1511 JMutexAutoLock lock(m_mutex);
1512 typename core::map<T, u32>::Node *n;
1513 n = m_value_to_id.find(value);
1515 return n->getValue();
1516 m_id_to_value.push_back(value);
1517 u32 new_id = m_id_to_value.size();
1518 m_value_to_id.insert(value, new_id);
1524 // Values are stored here at id-1 position (id 1 = [0])
1525 core::array<T> m_id_to_value;
1526 core::map<T, u32> m_value_to_id;
1530 Checks if a string contains only supplied characters
1532 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1534 for(u32 i=0; i<s.size(); i++)
1536 bool confirmed = false;
1537 for(u32 j=0; j<allowed_chars.size(); j++)
1539 if(s[i] == allowed_chars[j])
1545 if(confirmed == false)
1552 Forcefully wraps string into rows using \n
1553 (no word wrap, used for showing paths in gui)
1555 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1558 for(u32 i=0; i<from.size(); i++)
1560 if(i != 0 && i%rowlen == 0)
1570 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1571 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1574 Returns integer position of node in given floating point position
1576 inline v3s16 floatToInt(v3f p, f32 d)
1579 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1580 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1581 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1586 Returns floating point position of node in given integer position
1588 inline v3f intToFloat(v3s16 p, f32 d)
1599 More serialization stuff
1602 // Creates a string with the length as the first two bytes
1603 inline std::string serializeString(const std::string &plain)
1605 //assert(plain.size() <= 65535);
1606 if(plain.size() > 65535)
1607 throw SerializationError("String too long for serializeString");
1609 writeU16((u8*)&buf[0], plain.size());
1616 // Creates a string with the length as the first two bytes from wide string
1617 inline std::string serializeWideString(const std::wstring &plain)
1619 //assert(plain.size() <= 65535);
1620 if(plain.size() > 65535)
1621 throw SerializationError("String too long for serializeString");
1623 writeU16((u8*)buf, plain.size());
1626 for(u32 i=0; i<plain.size(); i++)
1628 writeU16((u8*)buf, plain[i]);
1634 // Reads a string with the length as the first two bytes
1635 inline std::string deSerializeString(std::istream &is)
1639 if(is.gcount() != 2)
1640 throw SerializationError("deSerializeString: size not read");
1641 u16 s_size = readU16((u8*)buf);
1644 Buffer<char> buf2(s_size);
1645 is.read(&buf2[0], s_size);
1648 s.append(&buf2[0], s_size);
1652 // Reads a wide string with the length as the first two bytes
1653 inline std::wstring deSerializeWideString(std::istream &is)
1657 if(is.gcount() != 2)
1658 throw SerializationError("deSerializeString: size not read");
1659 u16 s_size = readU16((u8*)buf);
1664 for(u32 i=0; i<s_size; i++)
1666 is.read(&buf[0], 2);
1667 wchar_t c16 = readU16((u8*)buf);
1673 // Creates a string with the length as the first four bytes
1674 inline std::string serializeLongString(const std::string &plain)
1677 writeU32((u8*)&buf[0], plain.size());
1684 // Reads a string with the length as the first four bytes
1685 inline std::string deSerializeLongString(std::istream &is)
1689 if(is.gcount() != 4)
1690 throw SerializationError("deSerializeLongString: size not read");
1691 u32 s_size = readU32((u8*)buf);
1694 Buffer<char> buf2(s_size);
1695 is.read(&buf2[0], s_size);
1698 s.append(&buf2[0], s_size);
1704 inline u32 time_to_daynight_ratio(u32 time_of_day)
1706 const s32 daylength = 16;
1707 const s32 nightlength = 6;
1708 const s32 daytimelength = 8;
1710 s32 t = (((time_of_day)%24000)/(24000/d));
1711 if(t < nightlength/2 || t >= d - nightlength/2)
1714 else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
1720 // Random helper. Usually d=BS
1721 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
1723 return core::aabbox3d<f32>(
1724 (float)p.X * d - 0.5*d,
1725 (float)p.Y * d - 0.5*d,
1726 (float)p.Z * d - 0.5*d,
1727 (float)p.X * d + 0.5*d,
1728 (float)p.Y * d + 0.5*d,
1729 (float)p.Z * d + 0.5*d
1733 class IntervalLimiter
1741 dtime: time from last call to this method
1742 wanted_interval: interval wanted
1744 true: action should be skipped
1745 false: action should be done
1747 bool step(float dtime, float wanted_interval)
1749 m_accumulator += dtime;
1750 if(m_accumulator < wanted_interval)
1752 m_accumulator -= wanted_interval;
1756 float m_accumulator;
1759 std::string translatePassword(std::string playername, std::wstring password);
1761 enum PointedThingType
1763 POINTEDTHING_NOTHING,
1770 PointedThingType type;
1771 v3s16 node_undersurface;
1772 v3s16 node_abovesurface;
1776 std::string dump() const;
1777 void serialize(std::ostream &os) const;
1778 void deSerialize(std::istream &is);
1779 bool operator==(const PointedThing &pt2) const;
1780 bool operator!=(const PointedThing &pt2) const;