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 writeF1000(u8 *data, f32 i){
108 writeS32(data, i*1000);
110 inline f32 readF1000(u8 *data){
111 return (f32)readS32(data)/1000.;
114 inline void writeS16(u8 *data, s16 i){
115 writeU16(data, (u16)i);
117 inline s16 readS16(u8 *data){
118 return (s16)readU16(data);
121 inline void writeV3S32(u8 *data, v3s32 p)
123 writeS32(&data[0], p.X);
124 writeS32(&data[4], p.Y);
125 writeS32(&data[8], p.Z);
127 inline v3s32 readV3S32(u8 *data)
130 p.X = readS32(&data[0]);
131 p.Y = readS32(&data[4]);
132 p.Z = readS32(&data[8]);
136 inline void writeV3F1000(u8 *data, v3f p)
138 writeF1000(&data[0], p.X);
139 writeF1000(&data[4], p.Y);
140 writeF1000(&data[8], p.Z);
142 inline v3f readV3F1000(u8 *data)
145 p.X = (float)readF1000(&data[0]);
146 p.Y = (float)readF1000(&data[4]);
147 p.Z = (float)readF1000(&data[8]);
151 inline void writeV2F1000(u8 *data, v2f p)
153 writeF1000(&data[0], p.X);
154 writeF1000(&data[4], p.Y);
156 inline v2f readV2F1000(u8 *data)
159 p.X = (float)readF1000(&data[0]);
160 p.Y = (float)readF1000(&data[4]);
164 inline void writeV2S16(u8 *data, v2s16 p)
166 writeS16(&data[0], p.X);
167 writeS16(&data[2], p.Y);
170 inline v2s16 readV2S16(u8 *data)
173 p.X = readS16(&data[0]);
174 p.Y = readS16(&data[2]);
178 inline void writeV2S32(u8 *data, v2s32 p)
180 writeS32(&data[0], p.X);
181 writeS32(&data[2], p.Y);
184 inline v2s32 readV2S32(u8 *data)
187 p.X = readS32(&data[0]);
188 p.Y = readS32(&data[2]);
192 inline void writeV3S16(u8 *data, v3s16 p)
194 writeS16(&data[0], p.X);
195 writeS16(&data[2], p.Y);
196 writeS16(&data[4], p.Z);
199 inline v3s16 readV3S16(u8 *data)
202 p.X = readS16(&data[0]);
203 p.Y = readS16(&data[2]);
204 p.Z = readS16(&data[4]);
209 The above stuff directly interfaced to iostream
212 inline void writeU8(std::ostream &os, u8 p)
215 writeU8((u8*)buf, p);
218 inline u8 readU8(std::istream &is)
222 return readU8((u8*)buf);
225 inline void writeU16(std::ostream &os, u16 p)
228 writeU16((u8*)buf, p);
231 inline u16 readU16(std::istream &is)
235 return readU16((u8*)buf);
238 inline void writeU32(std::ostream &os, u32 p)
241 writeU32((u8*)buf, p);
244 inline u32 readU32(std::istream &is)
248 return readU32((u8*)buf);
251 inline void writeS32(std::ostream &os, u32 p)
254 writeS32((u8*)buf, p);
257 inline u32 readS32(std::istream &is)
261 return readS32((u8*)buf);
264 inline void writeF1000(std::ostream &os, f32 p)
267 writeF1000((u8*)buf, p);
270 inline f32 readF1000(std::istream &is)
274 return readF1000((u8*)buf);
277 inline void writeV3F1000(std::ostream &os, v3f p)
280 writeV3F1000((u8*)buf, p);
283 inline v3f readV3F1000(std::istream &is)
287 return readV3F1000((u8*)buf);
290 inline void writeV2F1000(std::ostream &os, v2f p)
293 writeV2F1000((u8*)buf, p);
296 inline v2f readV2F1000(std::istream &is)
300 return readV2F1000((u8*)buf);
303 inline void writeV2S16(std::ostream &os, v2s16 p)
306 writeV2S16((u8*)buf, p);
309 inline v2s16 readV2S16(std::istream &is)
313 return readV2S16((u8*)buf);
316 inline void writeV3S16(std::ostream &os, v3s16 p)
319 writeV3S16((u8*)buf, p);
322 inline v3s16 readV3S16(std::istream &is)
326 return readV3S16((u8*)buf);
330 None of these are used at the moment
333 template <typename T>
343 SharedPtr(SharedPtr<T> &t)
347 refcount = t.refcount;
355 SharedPtr<T> & operator=(T *t)
363 SharedPtr<T> & operator=(SharedPtr<T> &t)
366 refcount = t.refcount;
379 bool operator!=(T *t)
383 bool operator==(T *t)
387 T & operator[](unsigned int i)
394 assert((*refcount) > 0);
407 template <typename T>
416 Buffer(unsigned int size)
424 Buffer(const Buffer &buffer)
426 m_size = buffer.m_size;
429 data = new T[buffer.m_size];
430 memcpy(data, buffer.data, buffer.m_size);
435 Buffer(const T *t, unsigned int size)
441 memcpy(data, t, size);
450 Buffer& operator=(const Buffer &buffer)
455 m_size = buffer.m_size;
458 data = new T[buffer.m_size];
459 memcpy(data, buffer.data, buffer.m_size);
465 T & operator[](unsigned int i) const
469 T * operator*() const
473 unsigned int getSize() const
487 template <typename T>
495 refcount = new unsigned int;
498 SharedBuffer(unsigned int size)
502 data = new T[m_size];
505 refcount = new unsigned int;
508 SharedBuffer(const SharedBuffer &buffer)
510 //std::cout<<"SharedBuffer(const SharedBuffer &buffer)"<<std::endl;
511 m_size = buffer.m_size;
513 refcount = buffer.refcount;
516 SharedBuffer & operator=(const SharedBuffer & buffer)
518 //std::cout<<"SharedBuffer & operator=(const SharedBuffer & buffer)"<<std::endl;
522 m_size = buffer.m_size;
524 refcount = buffer.refcount;
531 SharedBuffer(T *t, unsigned int size)
536 data = new T[m_size];
537 memcpy(data, t, m_size);
541 refcount = new unsigned int;
547 SharedBuffer(const Buffer<T> &buffer)
549 m_size = buffer.getSize();
552 data = new T[m_size];
553 memcpy(data, *buffer, buffer.getSize());
557 refcount = new unsigned int;
564 T & operator[](unsigned int i) const
569 T * operator*() const
573 unsigned int getSize() const
577 operator Buffer<T>() const
579 return Buffer<T>(data, m_size);
584 assert((*refcount) > 0);
595 unsigned int *refcount;
598 inline SharedBuffer<u8> SharedBufferFromString(const char *string)
600 SharedBuffer<u8> b((u8*)string, strlen(string)+1);
605 class MutexedVariable
608 MutexedVariable(T value):
616 JMutexAutoLock lock(m_mutex);
622 JMutexAutoLock lock(m_mutex);
626 // You'll want to grab this in a SharedPtr
627 JMutexAutoLock * getLock()
629 return new JMutexAutoLock(m_mutex);
632 // You pretty surely want to grab the lock when accessing this
646 TimeTaker(const char *name, u32 *result=NULL);
653 u32 stop(bool quiet=false);
665 // Sets the color of all vertices in the mesh
666 void setMeshVerticesColor(scene::IMesh* mesh, video::SColor& color);
669 // Calculates the borders of a "d-radius" cube
670 inline void getFacePositions(core::list<v3s16> &list, u16 d)
674 list.push_back(v3s16(0,0,0));
680 This is an optimized sequence of coordinates.
682 list.push_back(v3s16( 0, 1, 0)); // top
683 list.push_back(v3s16( 0, 0, 1)); // back
684 list.push_back(v3s16(-1, 0, 0)); // left
685 list.push_back(v3s16( 1, 0, 0)); // right
686 list.push_back(v3s16( 0, 0,-1)); // front
687 list.push_back(v3s16( 0,-1, 0)); // bottom
689 list.push_back(v3s16(-1, 0, 1)); // back left
690 list.push_back(v3s16( 1, 0, 1)); // back right
691 list.push_back(v3s16(-1, 0,-1)); // front left
692 list.push_back(v3s16( 1, 0,-1)); // front right
693 list.push_back(v3s16(-1,-1, 0)); // bottom left
694 list.push_back(v3s16( 1,-1, 0)); // bottom right
695 list.push_back(v3s16( 0,-1, 1)); // bottom back
696 list.push_back(v3s16( 0,-1,-1)); // bottom front
697 list.push_back(v3s16(-1, 1, 0)); // top left
698 list.push_back(v3s16( 1, 1, 0)); // top right
699 list.push_back(v3s16( 0, 1, 1)); // top back
700 list.push_back(v3s16( 0, 1,-1)); // top front
702 list.push_back(v3s16(-1, 1, 1)); // top back-left
703 list.push_back(v3s16( 1, 1, 1)); // top back-right
704 list.push_back(v3s16(-1, 1,-1)); // top front-left
705 list.push_back(v3s16( 1, 1,-1)); // top front-right
706 list.push_back(v3s16(-1,-1, 1)); // bottom back-left
707 list.push_back(v3s16( 1,-1, 1)); // bottom back-right
708 list.push_back(v3s16(-1,-1,-1)); // bottom front-left
709 list.push_back(v3s16( 1,-1,-1)); // bottom front-right
714 // Take blocks in all sides, starting from y=0 and going +-y
715 for(s16 y=0; y<=d-1; y++)
717 // Left and right side, including borders
718 for(s16 z=-d; z<=d; z++)
720 list.push_back(v3s16(d,y,z));
721 list.push_back(v3s16(-d,y,z));
724 list.push_back(v3s16(d,-y,z));
725 list.push_back(v3s16(-d,-y,z));
728 // Back and front side, excluding borders
729 for(s16 x=-d+1; x<=d-1; x++)
731 list.push_back(v3s16(x,y,d));
732 list.push_back(v3s16(x,y,-d));
735 list.push_back(v3s16(x,-y,d));
736 list.push_back(v3s16(x,-y,-d));
741 // Take the bottom and top face with borders
742 // -d<x<d, y=+-d, -d<z<d
743 for(s16 x=-d; x<=d; x++)
744 for(s16 z=-d; z<=d; z++)
746 list.push_back(v3s16(x,-d,z));
747 list.push_back(v3s16(x,d,z));
751 class IndentationRaiser
754 IndentationRaiser(u16 *indentation)
756 m_indentation = indentation;
767 inline s16 getContainerPos(s16 p, s16 d)
769 return (p>=0 ? p : p-d+1) / d;
772 inline v2s16 getContainerPos(v2s16 p, s16 d)
775 getContainerPos(p.X, d),
776 getContainerPos(p.Y, d)
780 inline v3s16 getContainerPos(v3s16 p, s16 d)
783 getContainerPos(p.X, d),
784 getContainerPos(p.Y, d),
785 getContainerPos(p.Z, d)
789 inline v2s16 getContainerPos(v2s16 p, v2s16 d)
792 getContainerPos(p.X, d.X),
793 getContainerPos(p.Y, d.Y)
797 inline v3s16 getContainerPos(v3s16 p, v3s16 d)
800 getContainerPos(p.X, d.X),
801 getContainerPos(p.Y, d.Y),
802 getContainerPos(p.Z, d.Z)
806 inline bool isInArea(v3s16 p, s16 d)
809 p.X >= 0 && p.X < d &&
810 p.Y >= 0 && p.Y < d &&
815 inline bool isInArea(v2s16 p, s16 d)
818 p.X >= 0 && p.X < d &&
823 inline bool isInArea(v3s16 p, v3s16 d)
826 p.X >= 0 && p.X < d.X &&
827 p.Y >= 0 && p.Y < d.Y &&
828 p.Z >= 0 && p.Z < d.Z
832 inline s16 rangelim(s16 i, s16 max)
841 #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
843 inline v3s16 arealim(v3s16 p, s16 d)
860 inline std::wstring narrow_to_wide(const std::string& mbs)
862 size_t wcl = mbs.size();
863 Buffer<wchar_t> wcs(wcl+1);
864 size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
865 if(l == (size_t)(-1))
866 return L"<invalid multibyte string>";
871 inline std::string wide_to_narrow(const std::wstring& wcs)
873 size_t mbl = wcs.size()*4;
874 SharedBuffer<char> mbs(mbl+1);
875 size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
876 if(l == (size_t)(-1))
883 // Split a string using the given delimiter. Returns a vector containing
884 // the component parts.
885 inline std::vector<std::wstring> str_split(const std::wstring &str, wchar_t delimiter)
887 std::vector<std::wstring> parts;
888 std::wstringstream sstr(str);
890 while(std::getline(sstr, part, delimiter))
891 parts.push_back(part);
897 See test.cpp for example cases.
898 wraps degrees to the range of -360...360
899 NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
901 inline float wrapDegrees(float f)
903 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
909 // NOTE: This would be used for wrapping to 0...360
915 // 10, 0.5, -0.5, -0.5
920 /* Wrap to 0...360 */
921 inline float wrapDegrees_0_360(float f)
923 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
935 // 10, 0.5, -0.5, -0.5
940 /* Wrap to -180...180 */
941 inline float wrapDegrees_180(float f)
944 f = wrapDegrees_0_360(f);
949 inline std::string lowercase(const std::string &s)
952 for(size_t i=0; i<s.size(); i++)
955 if(c >= 'A' && c <= 'Z')
962 inline bool is_yes(const std::string &s)
964 std::string s2 = lowercase(trim(s));
965 if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
970 inline s32 mystoi(const std::string &s, s32 min, s32 max)
972 s32 i = atoi(s.c_str());
981 // MSVC2010 includes it's own versions of these
982 //#if !defined(_MSC_VER) || _MSC_VER < 1600
984 inline s32 mystoi(std::string s)
986 return atoi(s.c_str());
989 inline s32 mystoi(std::wstring s)
991 return atoi(wide_to_narrow(s).c_str());
994 inline float mystof(std::string s)
997 std::istringstream ss(s);
1007 inline std::string itos(s32 i)
1009 std::ostringstream o;
1014 inline std::string ftos(float f)
1016 std::ostringstream o;
1021 inline void str_replace(std::string & str, std::string const & pattern,
1022 std::string const & replacement)
1024 std::string::size_type start = str.find(pattern, 0);
1025 while(start != str.npos)
1027 str.replace(start, pattern.size(), replacement);
1028 start = str.find(pattern, start+replacement.size());
1032 inline void str_replace_char(std::string & str, char from, char to)
1034 for(unsigned int i=0; i<str.size(); i++)
1042 A base class for simple background thread implementation
1045 class SimpleThread : public JThread
1059 virtual ~SimpleThread()
1062 virtual void * Thread() = 0;
1066 JMutexAutoLock lock(run_mutex);
1069 void setRun(bool a_run)
1071 JMutexAutoLock lock(run_mutex);
1084 FIFO queue (well, actually a FILO also)
1086 template<typename T>
1092 m_list.push_back(t);
1097 if(m_list.size() == 0)
1098 throw ItemNotFoundException("Queue: queue is empty");
1100 typename core::list<T>::Iterator begin = m_list.begin();
1102 m_list.erase(begin);
1107 if(m_list.size() == 0)
1108 throw ItemNotFoundException("Queue: queue is empty");
1110 typename core::list<T>::Iterator last = m_list.getLast();
1118 return m_list.size();
1122 core::list<T> m_list;
1126 Thread-safe FIFO queue (well, actually a FILO also)
1129 template<typename T>
1139 JMutexAutoLock lock(m_mutex);
1140 return m_list.size();
1144 JMutexAutoLock lock(m_mutex);
1145 m_list.push_back(t);
1147 T pop_front(u32 wait_time_max_ms=0)
1149 u32 wait_time_ms = 0;
1154 JMutexAutoLock lock(m_mutex);
1156 if(m_list.size() > 0)
1158 typename core::list<T>::Iterator begin = m_list.begin();
1160 m_list.erase(begin);
1164 if(wait_time_ms >= wait_time_max_ms)
1165 throw ItemNotFoundException("MutexedQueue: queue is empty");
1168 // Wait a while before trying again
1173 T pop_back(u32 wait_time_max_ms=0)
1175 u32 wait_time_ms = 0;
1180 JMutexAutoLock lock(m_mutex);
1182 if(m_list.size() > 0)
1184 typename core::list<T>::Iterator last = m_list.getLast();
1190 if(wait_time_ms >= wait_time_max_ms)
1191 throw ItemNotFoundException("MutexedQueue: queue is empty");
1194 // Wait a while before trying again
1205 core::list<T> & getList()
1212 core::list<T> m_list;
1216 A single worker thread - multiple client threads queue framework.
1219 template<typename Caller, typename Data>
1227 template<typename Key, typename T, typename Caller, typename CallerData>
1233 core::list<CallerInfo<Caller, CallerData> > callers;
1236 template<typename Key, typename T, typename Caller, typename CallerData>
1237 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1241 template<typename Key, typename T, typename Caller, typename CallerData>
1249 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1253 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1264 ResultQueue<Key, T, Caller, CallerData> *dest;
1265 core::list<CallerInfo<Caller, CallerData> > callers;
1268 template<typename Key, typename T, typename Caller, typename CallerData>
1274 return m_queue.size();
1277 void add(Key key, Caller caller, CallerData callerdata,
1278 ResultQueue<Key, T, Caller, CallerData> *dest)
1280 JMutexAutoLock lock(m_queue.getMutex());
1283 If the caller is already on the list, only update CallerData
1285 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1286 i = m_queue.getList().begin();
1287 i != m_queue.getList().end(); i++)
1289 GetRequest<Key, T, Caller, CallerData> &request = *i;
1291 if(request.key == key)
1293 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1294 i = request.callers.begin();
1295 i != request.callers.end(); i++)
1297 CallerInfo<Caller, CallerData> &ca = *i;
1298 if(ca.caller == caller)
1300 ca.data = callerdata;
1304 CallerInfo<Caller, CallerData> ca;
1306 ca.data = callerdata;
1307 request.callers.push_back(ca);
1313 Else add a new request to the queue
1316 GetRequest<Key, T, Caller, CallerData> request;
1318 CallerInfo<Caller, CallerData> ca;
1320 ca.data = callerdata;
1321 request.callers.push_back(ca);
1322 request.dest = dest;
1324 m_queue.getList().push_back(request);
1327 GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1329 return m_queue.pop_front(wait_if_empty);
1333 MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1337 Pseudo-random (VC++ rand() sucks)
1340 void mysrand(unsigned seed);
1341 #define MYRAND_MAX 32767
1343 int myrand_range(int min, int max);
1346 Miscellaneous functions
1349 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
1350 f32 camera_fov, f32 range, f32 *distance_ptr=NULL);
1353 Queue with unique values with fast checking of value existence
1356 template<typename Value>
1362 Does nothing if value is already queued.
1365 false: value already exists
1367 bool push_back(Value value)
1369 // Check if already exists
1370 if(m_map.find(value) != NULL)
1374 m_map.insert(value, 0);
1375 m_list.push_back(value);
1382 typename core::list<Value>::Iterator i = m_list.begin();
1384 m_map.remove(value);
1391 assert(m_list.size() == m_map.size());
1392 return m_list.size();
1396 core::map<Value, u8> m_map;
1397 core::list<Value> m_list;
1401 template<typename Key, typename Value>
1408 assert(m_mutex.IsInitialized());
1411 void set(const Key &name, const Value &value)
1413 JMutexAutoLock lock(m_mutex);
1415 m_values[name] = value;
1418 bool get(const Key &name, Value *result)
1420 JMutexAutoLock lock(m_mutex);
1422 typename core::map<Key, Value>::Node *n;
1423 n = m_values.find(name);
1429 *result = n->getValue();
1435 core::map<Key, Value> m_values;
1441 Generates ids for comparable values.
1442 Id=0 is reserved for "no value".
1445 - Returning value by id (very fast)
1446 - Returning id by value
1447 - Generating a new id for a value
1450 - Remove an id/value pair (is possible to implement but slow)
1452 template<typename T>
1453 class MutexedIdGenerator
1456 MutexedIdGenerator()
1459 assert(m_mutex.IsInitialized());
1462 // Returns true if found
1463 bool getValue(u32 id, T &value)
1467 JMutexAutoLock lock(m_mutex);
1468 if(m_id_to_value.size() < id)
1470 value = m_id_to_value[id-1];
1474 // If id exists for value, returns the id.
1475 // Otherwise generates an id for the value.
1476 u32 getId(const T &value)
1478 JMutexAutoLock lock(m_mutex);
1479 typename core::map<T, u32>::Node *n;
1480 n = m_value_to_id.find(value);
1482 return n->getValue();
1483 m_id_to_value.push_back(value);
1484 u32 new_id = m_id_to_value.size();
1485 m_value_to_id.insert(value, new_id);
1491 // Values are stored here at id-1 position (id 1 = [0])
1492 core::array<T> m_id_to_value;
1493 core::map<T, u32> m_value_to_id;
1497 Checks if a string contains only supplied characters
1499 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1501 for(u32 i=0; i<s.size(); i++)
1503 bool confirmed = false;
1504 for(u32 j=0; j<allowed_chars.size(); j++)
1506 if(s[i] == allowed_chars[j])
1512 if(confirmed == false)
1519 Forcefully wraps string into rows using \n
1520 (no word wrap, used for showing paths in gui)
1522 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1525 for(u32 i=0; i<from.size(); i++)
1527 if(i != 0 && i%rowlen == 0)
1537 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1538 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1541 Returns integer position of node in given floating point position
1543 inline v3s16 floatToInt(v3f p, f32 d)
1546 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1547 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1548 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1553 Returns floating point position of node in given integer position
1555 inline v3f intToFloat(v3s16 p, f32 d)
1566 More serialization stuff
1569 // Creates a string with the length as the first two bytes
1570 inline std::string serializeString(const std::string &plain)
1572 //assert(plain.size() <= 65535);
1573 if(plain.size() > 65535)
1574 throw SerializationError("String too long for serializeString");
1576 writeU16((u8*)&buf[0], plain.size());
1583 // Creates a string with the length as the first two bytes from wide string
1584 inline std::string serializeWideString(const std::wstring &plain)
1586 //assert(plain.size() <= 65535);
1587 if(plain.size() > 65535)
1588 throw SerializationError("String too long for serializeString");
1590 writeU16((u8*)buf, plain.size());
1593 for(u32 i=0; i<plain.size(); i++)
1595 writeU16((u8*)buf, plain[i]);
1601 // Reads a string with the length as the first two bytes
1602 inline std::string deSerializeString(std::istream &is)
1606 if(is.gcount() != 2)
1607 throw SerializationError("deSerializeString: size not read");
1608 u16 s_size = readU16((u8*)buf);
1611 Buffer<char> buf2(s_size);
1612 is.read(&buf2[0], s_size);
1615 s.append(&buf2[0], s_size);
1619 // Reads a wide string with the length as the first two bytes
1620 inline std::wstring deSerializeWideString(std::istream &is)
1624 if(is.gcount() != 2)
1625 throw SerializationError("deSerializeString: size not read");
1626 u16 s_size = readU16((u8*)buf);
1631 for(u32 i=0; i<s_size; i++)
1633 is.read(&buf[0], 2);
1634 wchar_t c16 = readU16((u8*)buf);
1640 // Creates a string with the length as the first four bytes
1641 inline std::string serializeLongString(const std::string &plain)
1644 writeU32((u8*)&buf[0], plain.size());
1651 // Reads a string with the length as the first four bytes
1652 inline std::string deSerializeLongString(std::istream &is)
1656 if(is.gcount() != 4)
1657 throw SerializationError("deSerializeLongString: size not read");
1658 u32 s_size = readU32((u8*)buf);
1661 Buffer<char> buf2(s_size);
1662 is.read(&buf2[0], s_size);
1665 s.append(&buf2[0], s_size);
1671 inline u32 time_to_daynight_ratio(u32 time_of_day)
1673 const s32 daylength = 16;
1674 const s32 nightlength = 6;
1675 const s32 daytimelength = 8;
1677 s32 t = (((time_of_day)%24000)/(24000/d));
1678 if(t < nightlength/2 || t >= d - nightlength/2)
1681 else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
1687 // Random helper. Usually d=BS
1688 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
1690 return core::aabbox3d<f32>(
1691 (float)p.X * d - 0.5*d,
1692 (float)p.Y * d - 0.5*d,
1693 (float)p.Z * d - 0.5*d,
1694 (float)p.X * d + 0.5*d,
1695 (float)p.Y * d + 0.5*d,
1696 (float)p.Z * d + 0.5*d
1700 class IntervalLimiter
1708 dtime: time from last call to this method
1709 wanted_interval: interval wanted
1711 true: action should be skipped
1712 false: action should be done
1714 bool step(float dtime, float wanted_interval)
1716 m_accumulator += dtime;
1717 if(m_accumulator < wanted_interval)
1719 m_accumulator -= wanted_interval;
1723 float m_accumulator;
1726 std::string translatePassword(std::string playername, std::wstring password);