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);
697 // Calculates the borders of a "d-radius" cube
698 inline void getFacePositions(core::list<v3s16> &list, u16 d)
702 list.push_back(v3s16(0,0,0));
708 This is an optimized sequence of coordinates.
710 list.push_back(v3s16( 0, 1, 0)); // top
711 list.push_back(v3s16( 0, 0, 1)); // back
712 list.push_back(v3s16(-1, 0, 0)); // left
713 list.push_back(v3s16( 1, 0, 0)); // right
714 list.push_back(v3s16( 0, 0,-1)); // front
715 list.push_back(v3s16( 0,-1, 0)); // bottom
717 list.push_back(v3s16(-1, 0, 1)); // back left
718 list.push_back(v3s16( 1, 0, 1)); // back right
719 list.push_back(v3s16(-1, 0,-1)); // front left
720 list.push_back(v3s16( 1, 0,-1)); // front right
721 list.push_back(v3s16(-1,-1, 0)); // bottom left
722 list.push_back(v3s16( 1,-1, 0)); // bottom right
723 list.push_back(v3s16( 0,-1, 1)); // bottom back
724 list.push_back(v3s16( 0,-1,-1)); // bottom front
725 list.push_back(v3s16(-1, 1, 0)); // top left
726 list.push_back(v3s16( 1, 1, 0)); // top right
727 list.push_back(v3s16( 0, 1, 1)); // top back
728 list.push_back(v3s16( 0, 1,-1)); // top front
730 list.push_back(v3s16(-1, 1, 1)); // top back-left
731 list.push_back(v3s16( 1, 1, 1)); // top back-right
732 list.push_back(v3s16(-1, 1,-1)); // top front-left
733 list.push_back(v3s16( 1, 1,-1)); // top front-right
734 list.push_back(v3s16(-1,-1, 1)); // bottom back-left
735 list.push_back(v3s16( 1,-1, 1)); // bottom back-right
736 list.push_back(v3s16(-1,-1,-1)); // bottom front-left
737 list.push_back(v3s16( 1,-1,-1)); // bottom front-right
742 // Take blocks in all sides, starting from y=0 and going +-y
743 for(s16 y=0; y<=d-1; y++)
745 // Left and right side, including borders
746 for(s16 z=-d; z<=d; z++)
748 list.push_back(v3s16(d,y,z));
749 list.push_back(v3s16(-d,y,z));
752 list.push_back(v3s16(d,-y,z));
753 list.push_back(v3s16(-d,-y,z));
756 // Back and front side, excluding borders
757 for(s16 x=-d+1; x<=d-1; x++)
759 list.push_back(v3s16(x,y,d));
760 list.push_back(v3s16(x,y,-d));
763 list.push_back(v3s16(x,-y,d));
764 list.push_back(v3s16(x,-y,-d));
769 // Take the bottom and top face with borders
770 // -d<x<d, y=+-d, -d<z<d
771 for(s16 x=-d; x<=d; x++)
772 for(s16 z=-d; z<=d; z++)
774 list.push_back(v3s16(x,-d,z));
775 list.push_back(v3s16(x,d,z));
779 class IndentationRaiser
782 IndentationRaiser(u16 *indentation)
784 m_indentation = indentation;
795 inline s16 getContainerPos(s16 p, s16 d)
797 return (p>=0 ? p : p-d+1) / d;
800 inline v2s16 getContainerPos(v2s16 p, s16 d)
803 getContainerPos(p.X, d),
804 getContainerPos(p.Y, d)
808 inline v3s16 getContainerPos(v3s16 p, s16 d)
811 getContainerPos(p.X, d),
812 getContainerPos(p.Y, d),
813 getContainerPos(p.Z, d)
817 inline v2s16 getContainerPos(v2s16 p, v2s16 d)
820 getContainerPos(p.X, d.X),
821 getContainerPos(p.Y, d.Y)
825 inline v3s16 getContainerPos(v3s16 p, v3s16 d)
828 getContainerPos(p.X, d.X),
829 getContainerPos(p.Y, d.Y),
830 getContainerPos(p.Z, d.Z)
834 inline bool isInArea(v3s16 p, s16 d)
837 p.X >= 0 && p.X < d &&
838 p.Y >= 0 && p.Y < d &&
843 inline bool isInArea(v2s16 p, s16 d)
846 p.X >= 0 && p.X < d &&
851 inline bool isInArea(v3s16 p, v3s16 d)
854 p.X >= 0 && p.X < d.X &&
855 p.Y >= 0 && p.Y < d.Y &&
856 p.Z >= 0 && p.Z < d.Z
860 inline s16 rangelim(s16 i, s16 max)
869 #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
871 inline v3s16 arealim(v3s16 p, s16 d)
888 inline std::wstring narrow_to_wide(const std::string& mbs)
890 size_t wcl = mbs.size();
891 Buffer<wchar_t> wcs(wcl+1);
892 size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
893 if(l == (size_t)(-1))
894 return L"<invalid multibyte string>";
899 inline std::string wide_to_narrow(const std::wstring& wcs)
901 size_t mbl = wcs.size()*4;
902 SharedBuffer<char> mbs(mbl+1);
903 size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
904 if(l == (size_t)(-1))
911 // Split a string using the given delimiter. Returns a vector containing
912 // the component parts.
913 inline std::vector<std::wstring> str_split(const std::wstring &str, wchar_t delimiter)
915 std::vector<std::wstring> parts;
916 std::wstringstream sstr(str);
918 while(std::getline(sstr, part, delimiter))
919 parts.push_back(part);
925 See test.cpp for example cases.
926 wraps degrees to the range of -360...360
927 NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
929 inline float wrapDegrees(float f)
931 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
937 // NOTE: This would be used for wrapping to 0...360
943 // 10, 0.5, -0.5, -0.5
948 /* Wrap to 0...360 */
949 inline float wrapDegrees_0_360(float f)
951 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
963 // 10, 0.5, -0.5, -0.5
968 /* Wrap to -180...180 */
969 inline float wrapDegrees_180(float f)
972 f = wrapDegrees_0_360(f);
977 inline std::string lowercase(const std::string &s)
980 for(size_t i=0; i<s.size(); i++)
983 if(c >= 'A' && c <= 'Z')
990 inline bool is_yes(const std::string &s)
992 std::string s2 = lowercase(trim(s));
993 if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
998 inline s32 mystoi(const std::string &s, s32 min, s32 max)
1000 s32 i = atoi(s.c_str());
1009 // MSVC2010 includes it's own versions of these
1010 //#if !defined(_MSC_VER) || _MSC_VER < 1600
1012 inline s32 mystoi(std::string s)
1014 return atoi(s.c_str());
1017 inline s32 mystoi(std::wstring s)
1019 return atoi(wide_to_narrow(s).c_str());
1022 inline float mystof(std::string s)
1025 std::istringstream ss(s);
1035 inline std::string itos(s32 i)
1037 std::ostringstream o;
1042 inline std::string ftos(float f)
1044 std::ostringstream o;
1049 inline void str_replace(std::string & str, std::string const & pattern,
1050 std::string const & replacement)
1052 std::string::size_type start = str.find(pattern, 0);
1053 while(start != str.npos)
1055 str.replace(start, pattern.size(), replacement);
1056 start = str.find(pattern, start+replacement.size());
1060 inline void str_replace_char(std::string & str, char from, char to)
1062 for(unsigned int i=0; i<str.size(); i++)
1070 A base class for simple background thread implementation
1073 class SimpleThread : public JThread
1087 virtual ~SimpleThread()
1090 virtual void * Thread() = 0;
1094 JMutexAutoLock lock(run_mutex);
1097 void setRun(bool a_run)
1099 JMutexAutoLock lock(run_mutex);
1112 FIFO queue (well, actually a FILO also)
1114 template<typename T>
1120 m_list.push_back(t);
1125 if(m_list.size() == 0)
1126 throw ItemNotFoundException("Queue: queue is empty");
1128 typename core::list<T>::Iterator begin = m_list.begin();
1130 m_list.erase(begin);
1135 if(m_list.size() == 0)
1136 throw ItemNotFoundException("Queue: queue is empty");
1138 typename core::list<T>::Iterator last = m_list.getLast();
1146 return m_list.size();
1150 core::list<T> m_list;
1154 Thread-safe FIFO queue (well, actually a FILO also)
1157 template<typename T>
1167 JMutexAutoLock lock(m_mutex);
1168 return m_list.size();
1172 JMutexAutoLock lock(m_mutex);
1173 m_list.push_back(t);
1175 T pop_front(u32 wait_time_max_ms=0)
1177 u32 wait_time_ms = 0;
1182 JMutexAutoLock lock(m_mutex);
1184 if(m_list.size() > 0)
1186 typename core::list<T>::Iterator begin = m_list.begin();
1188 m_list.erase(begin);
1192 if(wait_time_ms >= wait_time_max_ms)
1193 throw ItemNotFoundException("MutexedQueue: queue is empty");
1196 // Wait a while before trying again
1201 T pop_back(u32 wait_time_max_ms=0)
1203 u32 wait_time_ms = 0;
1208 JMutexAutoLock lock(m_mutex);
1210 if(m_list.size() > 0)
1212 typename core::list<T>::Iterator last = m_list.getLast();
1218 if(wait_time_ms >= wait_time_max_ms)
1219 throw ItemNotFoundException("MutexedQueue: queue is empty");
1222 // Wait a while before trying again
1233 core::list<T> & getList()
1240 core::list<T> m_list;
1244 A single worker thread - multiple client threads queue framework.
1247 template<typename Caller, typename Data>
1255 template<typename Key, typename T, typename Caller, typename CallerData>
1261 core::list<CallerInfo<Caller, CallerData> > callers;
1264 template<typename Key, typename T, typename Caller, typename CallerData>
1265 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1269 template<typename Key, typename T, typename Caller, typename CallerData>
1277 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1281 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1292 ResultQueue<Key, T, Caller, CallerData> *dest;
1293 core::list<CallerInfo<Caller, CallerData> > callers;
1296 template<typename Key, typename T, typename Caller, typename CallerData>
1302 return m_queue.size();
1305 void add(Key key, Caller caller, CallerData callerdata,
1306 ResultQueue<Key, T, Caller, CallerData> *dest)
1308 JMutexAutoLock lock(m_queue.getMutex());
1311 If the caller is already on the list, only update CallerData
1313 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1314 i = m_queue.getList().begin();
1315 i != m_queue.getList().end(); i++)
1317 GetRequest<Key, T, Caller, CallerData> &request = *i;
1319 if(request.key == key)
1321 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1322 i = request.callers.begin();
1323 i != request.callers.end(); i++)
1325 CallerInfo<Caller, CallerData> &ca = *i;
1326 if(ca.caller == caller)
1328 ca.data = callerdata;
1332 CallerInfo<Caller, CallerData> ca;
1334 ca.data = callerdata;
1335 request.callers.push_back(ca);
1341 Else add a new request to the queue
1344 GetRequest<Key, T, Caller, CallerData> request;
1346 CallerInfo<Caller, CallerData> ca;
1348 ca.data = callerdata;
1349 request.callers.push_back(ca);
1350 request.dest = dest;
1352 m_queue.getList().push_back(request);
1355 GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1357 return m_queue.pop_front(wait_if_empty);
1361 MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1365 Pseudo-random (VC++ rand() sucks)
1368 void mysrand(unsigned seed);
1369 #define MYRAND_MAX 32767
1371 int myrand_range(int min, int max);
1374 Miscellaneous functions
1377 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
1378 f32 camera_fov, f32 range, f32 *distance_ptr=NULL);
1381 Queue with unique values with fast checking of value existence
1384 template<typename Value>
1390 Does nothing if value is already queued.
1393 false: value already exists
1395 bool push_back(Value value)
1397 // Check if already exists
1398 if(m_map.find(value) != NULL)
1402 m_map.insert(value, 0);
1403 m_list.push_back(value);
1410 typename core::list<Value>::Iterator i = m_list.begin();
1412 m_map.remove(value);
1419 assert(m_list.size() == m_map.size());
1420 return m_list.size();
1424 core::map<Value, u8> m_map;
1425 core::list<Value> m_list;
1429 template<typename Key, typename Value>
1436 assert(m_mutex.IsInitialized());
1439 void set(const Key &name, const Value &value)
1441 JMutexAutoLock lock(m_mutex);
1443 m_values[name] = value;
1446 bool get(const Key &name, Value *result)
1448 JMutexAutoLock lock(m_mutex);
1450 typename core::map<Key, Value>::Node *n;
1451 n = m_values.find(name);
1457 *result = n->getValue();
1463 core::map<Key, Value> m_values;
1469 Generates ids for comparable values.
1470 Id=0 is reserved for "no value".
1473 - Returning value by id (very fast)
1474 - Returning id by value
1475 - Generating a new id for a value
1478 - Remove an id/value pair (is possible to implement but slow)
1480 template<typename T>
1481 class MutexedIdGenerator
1484 MutexedIdGenerator()
1487 assert(m_mutex.IsInitialized());
1490 // Returns true if found
1491 bool getValue(u32 id, T &value)
1495 JMutexAutoLock lock(m_mutex);
1496 if(m_id_to_value.size() < id)
1498 value = m_id_to_value[id-1];
1502 // If id exists for value, returns the id.
1503 // Otherwise generates an id for the value.
1504 u32 getId(const T &value)
1506 JMutexAutoLock lock(m_mutex);
1507 typename core::map<T, u32>::Node *n;
1508 n = m_value_to_id.find(value);
1510 return n->getValue();
1511 m_id_to_value.push_back(value);
1512 u32 new_id = m_id_to_value.size();
1513 m_value_to_id.insert(value, new_id);
1519 // Values are stored here at id-1 position (id 1 = [0])
1520 core::array<T> m_id_to_value;
1521 core::map<T, u32> m_value_to_id;
1525 Checks if a string contains only supplied characters
1527 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1529 for(u32 i=0; i<s.size(); i++)
1531 bool confirmed = false;
1532 for(u32 j=0; j<allowed_chars.size(); j++)
1534 if(s[i] == allowed_chars[j])
1540 if(confirmed == false)
1547 Forcefully wraps string into rows using \n
1548 (no word wrap, used for showing paths in gui)
1550 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1553 for(u32 i=0; i<from.size(); i++)
1555 if(i != 0 && i%rowlen == 0)
1565 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1566 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1569 Returns integer position of node in given floating point position
1571 inline v3s16 floatToInt(v3f p, f32 d)
1574 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1575 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1576 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1581 Returns floating point position of node in given integer position
1583 inline v3f intToFloat(v3s16 p, f32 d)
1594 More serialization stuff
1597 // Creates a string with the length as the first two bytes
1598 inline std::string serializeString(const std::string &plain)
1600 //assert(plain.size() <= 65535);
1601 if(plain.size() > 65535)
1602 throw SerializationError("String too long for serializeString");
1604 writeU16((u8*)&buf[0], plain.size());
1611 // Creates a string with the length as the first two bytes from wide string
1612 inline std::string serializeWideString(const std::wstring &plain)
1614 //assert(plain.size() <= 65535);
1615 if(plain.size() > 65535)
1616 throw SerializationError("String too long for serializeString");
1618 writeU16((u8*)buf, plain.size());
1621 for(u32 i=0; i<plain.size(); i++)
1623 writeU16((u8*)buf, plain[i]);
1629 // Reads a string with the length as the first two bytes
1630 inline std::string deSerializeString(std::istream &is)
1634 if(is.gcount() != 2)
1635 throw SerializationError("deSerializeString: size not read");
1636 u16 s_size = readU16((u8*)buf);
1639 Buffer<char> buf2(s_size);
1640 is.read(&buf2[0], s_size);
1643 s.append(&buf2[0], s_size);
1647 // Reads a wide string with the length as the first two bytes
1648 inline std::wstring deSerializeWideString(std::istream &is)
1652 if(is.gcount() != 2)
1653 throw SerializationError("deSerializeString: size not read");
1654 u16 s_size = readU16((u8*)buf);
1659 for(u32 i=0; i<s_size; i++)
1661 is.read(&buf[0], 2);
1662 wchar_t c16 = readU16((u8*)buf);
1668 // Creates a string with the length as the first four bytes
1669 inline std::string serializeLongString(const std::string &plain)
1672 writeU32((u8*)&buf[0], plain.size());
1679 // Reads a string with the length as the first four bytes
1680 inline std::string deSerializeLongString(std::istream &is)
1684 if(is.gcount() != 4)
1685 throw SerializationError("deSerializeLongString: size not read");
1686 u32 s_size = readU32((u8*)buf);
1689 Buffer<char> buf2(s_size);
1690 is.read(&buf2[0], s_size);
1693 s.append(&buf2[0], s_size);
1697 // Creates a string encoded in JSON format (almost equivalent to a C string literal)
1698 std::string serializeJsonString(const std::string &plain);
1700 // Reads a string encoded in JSON format
1701 std::string deSerializeJsonString(std::istream &is);
1705 inline u32 time_to_daynight_ratio(u32 time_of_day)
1707 const s32 daylength = 16;
1708 const s32 nightlength = 6;
1709 const s32 daytimelength = 8;
1711 s32 t = (((time_of_day)%24000)/(24000/d));
1712 if(t < nightlength/2 || t >= d - nightlength/2)
1715 else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
1721 // Random helper. Usually d=BS
1722 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
1724 return core::aabbox3d<f32>(
1725 (float)p.X * d - 0.5*d,
1726 (float)p.Y * d - 0.5*d,
1727 (float)p.Z * d - 0.5*d,
1728 (float)p.X * d + 0.5*d,
1729 (float)p.Y * d + 0.5*d,
1730 (float)p.Z * d + 0.5*d
1734 class IntervalLimiter
1742 dtime: time from last call to this method
1743 wanted_interval: interval wanted
1745 true: action should be skipped
1746 false: action should be done
1748 bool step(float dtime, float wanted_interval)
1750 m_accumulator += dtime;
1751 if(m_accumulator < wanted_interval)
1753 m_accumulator -= wanted_interval;
1757 float m_accumulator;
1761 Splits a list into "pages". For example, the list [1,2,3,4,5] split
1762 into two pages would be [1,2,3],[4,5]. This function computes the
1763 minimum and maximum indices of a single page.
1765 length: Length of the list that should be split
1766 page: Page number, 1 <= page <= pagecount
1767 pagecount: The number of pages, >= 1
1768 minindex: Receives the minimum index (inclusive).
1769 maxindex: Receives the maximum index (exclusive).
1771 Ensures 0 <= minindex <= maxindex <= length.
1773 inline void paging(u32 length, u32 page, u32 pagecount, u32 &minindex, u32 &maxindex)
1775 if(length < 1 || pagecount < 1 || page < 1 || page > pagecount)
1777 // Special cases or invalid parameters
1778 minindex = maxindex = 0;
1780 else if(pagecount <= length)
1782 // Less pages than entries in the list:
1783 // Each page contains at least one entry
1784 minindex = (length * (page-1) + (pagecount-1)) / pagecount;
1785 maxindex = (length * page + (pagecount-1)) / pagecount;
1789 // More pages than entries in the list:
1790 // Make sure the empty pages are at the end
1804 std::string translatePassword(std::string playername, std::wstring password);
1806 enum PointedThingType
1808 POINTEDTHING_NOTHING,
1815 PointedThingType type;
1816 v3s16 node_undersurface;
1817 v3s16 node_abovesurface;
1821 std::string dump() const;
1822 void serialize(std::ostream &os) const;
1823 void deSerialize(std::istream &is);
1824 bool operator==(const PointedThing &pt2) const;
1825 bool operator!=(const PointedThing &pt2) const;