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"
36 #include "exceptions.h"
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 writeV2S16(u8 *data, v2s16 p)
153 writeS16(&data[0], p.X);
154 writeS16(&data[2], p.Y);
157 inline v2s16 readV2S16(u8 *data)
160 p.X = readS16(&data[0]);
161 p.Y = readS16(&data[2]);
165 inline void writeV2S32(u8 *data, v2s32 p)
167 writeS32(&data[0], p.X);
168 writeS32(&data[2], p.Y);
171 inline v2s32 readV2S32(u8 *data)
174 p.X = readS32(&data[0]);
175 p.Y = readS32(&data[2]);
179 inline void writeV3S16(u8 *data, v3s16 p)
181 writeS16(&data[0], p.X);
182 writeS16(&data[2], p.Y);
183 writeS16(&data[4], p.Z);
186 inline v3s16 readV3S16(u8 *data)
189 p.X = readS16(&data[0]);
190 p.Y = readS16(&data[2]);
191 p.Z = readS16(&data[4]);
196 The above stuff directly interfaced to iostream
199 inline void writeU8(std::ostream &os, u8 p)
202 writeU8((u8*)buf, p);
205 inline u8 readU8(std::istream &is)
209 return readU8((u8*)buf);
212 inline void writeU16(std::ostream &os, u16 p)
215 writeU16((u8*)buf, p);
218 inline u16 readU16(std::istream &is)
222 return readU16((u8*)buf);
225 inline void writeU32(std::ostream &os, u16 p)
228 writeU16((u8*)buf, p);
231 inline u16 readU32(std::istream &is)
235 return readU32((u8*)buf);
238 inline void writeF1000(std::ostream &os, f32 p)
241 writeF1000((u8*)buf, p);
244 inline f32 readF1000(std::istream &is)
248 return readF1000((u8*)buf);
251 inline void writeV3F1000(std::ostream &os, v3f p)
254 writeV3F1000((u8*)buf, p);
257 inline v3f readV3F1000(std::istream &is)
261 return readV3F1000((u8*)buf);
265 None of these are used at the moment
268 template <typename T>
278 SharedPtr(SharedPtr<T> &t)
282 refcount = t.refcount;
290 SharedPtr<T> & operator=(T *t)
298 SharedPtr<T> & operator=(SharedPtr<T> &t)
301 refcount = t.refcount;
314 bool operator!=(T *t)
318 bool operator==(T *t)
322 T & operator[](unsigned int i)
329 assert((*refcount) > 0);
342 template <typename T>
346 Buffer(unsigned int size)
351 Buffer(const Buffer &buffer)
353 m_size = buffer.m_size;
354 data = new T[buffer.m_size];
355 memcpy(data, buffer.data, buffer.m_size);
357 Buffer(T *t, unsigned int size)
361 memcpy(data, t, size);
367 T & operator[](unsigned int i) const
371 T * operator*() const
375 unsigned int getSize() const
384 template <typename T>
392 refcount = new unsigned int;
395 SharedBuffer(unsigned int size)
399 data = new T[m_size];
402 refcount = new unsigned int;
405 SharedBuffer(const SharedBuffer &buffer)
407 //std::cout<<"SharedBuffer(const SharedBuffer &buffer)"<<std::endl;
408 m_size = buffer.m_size;
410 refcount = buffer.refcount;
413 SharedBuffer & operator=(const SharedBuffer & buffer)
415 //std::cout<<"SharedBuffer & operator=(const SharedBuffer & buffer)"<<std::endl;
419 m_size = buffer.m_size;
421 refcount = buffer.refcount;
428 SharedBuffer(T *t, unsigned int size)
433 data = new T[m_size];
434 memcpy(data, t, m_size);
438 refcount = new unsigned int;
444 SharedBuffer(const Buffer<T> &buffer)
446 m_size = buffer.getSize();
449 data = new T[m_size];
450 memcpy(data, *buffer, buffer.getSize());
454 refcount = new unsigned int;
461 T & operator[](unsigned int i) const
466 T * operator*() const
470 unsigned int getSize() const
477 assert((*refcount) > 0);
488 unsigned int *refcount;
491 inline SharedBuffer<u8> SharedBufferFromString(const char *string)
493 SharedBuffer<u8> b((u8*)string, strlen(string)+1);
498 class MutexedVariable
501 MutexedVariable(T value):
509 JMutexAutoLock lock(m_mutex);
515 JMutexAutoLock lock(m_mutex);
519 // You'll want to grab this in a SharedPtr
520 JMutexAutoLock * getLock()
522 return new JMutexAutoLock(m_mutex);
525 // You pretty surely want to grab the lock when accessing this
539 TimeTaker(const char *name, u32 *result=NULL);
546 u32 stop(bool quiet=false);
558 // Sets the color of all vertices in the mesh
559 void setMeshVerticesColor(scene::IMesh* mesh, video::SColor& color);
562 // Calculates the borders of a "d-radius" cube
563 inline void getFacePositions(core::list<v3s16> &list, u16 d)
567 list.push_back(v3s16(0,0,0));
573 This is an optimized sequence of coordinates.
575 list.push_back(v3s16( 0, 1, 0)); // top
576 list.push_back(v3s16( 0, 0, 1)); // back
577 list.push_back(v3s16(-1, 0, 0)); // left
578 list.push_back(v3s16( 1, 0, 0)); // right
579 list.push_back(v3s16( 0, 0,-1)); // front
580 list.push_back(v3s16( 0,-1, 0)); // bottom
582 list.push_back(v3s16(-1, 0, 1)); // back left
583 list.push_back(v3s16( 1, 0, 1)); // back right
584 list.push_back(v3s16(-1, 0,-1)); // front left
585 list.push_back(v3s16( 1, 0,-1)); // front right
586 list.push_back(v3s16(-1,-1, 0)); // bottom left
587 list.push_back(v3s16( 1,-1, 0)); // bottom right
588 list.push_back(v3s16( 0,-1, 1)); // bottom back
589 list.push_back(v3s16( 0,-1,-1)); // bottom front
590 list.push_back(v3s16(-1, 1, 0)); // top left
591 list.push_back(v3s16( 1, 1, 0)); // top right
592 list.push_back(v3s16( 0, 1, 1)); // top back
593 list.push_back(v3s16( 0, 1,-1)); // top front
595 list.push_back(v3s16(-1, 1, 1)); // top back-left
596 list.push_back(v3s16( 1, 1, 1)); // top back-right
597 list.push_back(v3s16(-1, 1,-1)); // top front-left
598 list.push_back(v3s16( 1, 1,-1)); // top front-right
599 list.push_back(v3s16(-1,-1, 1)); // bottom back-left
600 list.push_back(v3s16( 1,-1, 1)); // bottom back-right
601 list.push_back(v3s16(-1,-1,-1)); // bottom front-left
602 list.push_back(v3s16( 1,-1,-1)); // bottom front-right
607 // Take blocks in all sides, starting from y=0 and going +-y
608 for(s16 y=0; y<=d-1; y++)
610 // Left and right side, including borders
611 for(s16 z=-d; z<=d; z++)
613 list.push_back(v3s16(d,y,z));
614 list.push_back(v3s16(-d,y,z));
617 list.push_back(v3s16(d,-y,z));
618 list.push_back(v3s16(-d,-y,z));
621 // Back and front side, excluding borders
622 for(s16 x=-d+1; x<=d-1; x++)
624 list.push_back(v3s16(x,y,d));
625 list.push_back(v3s16(x,y,-d));
628 list.push_back(v3s16(x,-y,d));
629 list.push_back(v3s16(x,-y,-d));
634 // Take the bottom and top face with borders
635 // -d<x<d, y=+-d, -d<z<d
636 for(s16 x=-d; x<=d; x++)
637 for(s16 z=-d; z<=d; z++)
639 list.push_back(v3s16(x,-d,z));
640 list.push_back(v3s16(x,d,z));
644 class IndentationRaiser
647 IndentationRaiser(u16 *indentation)
649 m_indentation = indentation;
660 inline s16 getContainerPos(s16 p, s16 d)
662 return (p>=0 ? p : p-d+1) / d;
665 inline v2s16 getContainerPos(v2s16 p, s16 d)
668 getContainerPos(p.X, d),
669 getContainerPos(p.Y, d)
673 inline v3s16 getContainerPos(v3s16 p, s16 d)
676 getContainerPos(p.X, d),
677 getContainerPos(p.Y, d),
678 getContainerPos(p.Z, d)
682 inline v2s16 getContainerPos(v2s16 p, v2s16 d)
685 getContainerPos(p.X, d.X),
686 getContainerPos(p.Y, d.Y)
690 inline v3s16 getContainerPos(v3s16 p, v3s16 d)
693 getContainerPos(p.X, d.X),
694 getContainerPos(p.Y, d.Y),
695 getContainerPos(p.Z, d.Z)
699 inline bool isInArea(v3s16 p, s16 d)
702 p.X >= 0 && p.X < d &&
703 p.Y >= 0 && p.Y < d &&
708 inline bool isInArea(v2s16 p, s16 d)
711 p.X >= 0 && p.X < d &&
716 inline bool isInArea(v3s16 p, v3s16 d)
719 p.X >= 0 && p.X < d.X &&
720 p.Y >= 0 && p.Y < d.Y &&
721 p.Z >= 0 && p.Z < d.Z
725 inline s16 rangelim(s16 i, s16 max)
734 #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
736 inline v3s16 arealim(v3s16 p, s16 d)
753 inline std::wstring narrow_to_wide(const std::string& mbs)
755 size_t wcl = mbs.size();
756 Buffer<wchar_t> wcs(wcl+1);
757 size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
758 if(l == (size_t)(-1))
759 return L"<invalid multibyte string>";
764 inline std::string wide_to_narrow(const std::wstring& wcs)
766 size_t mbl = wcs.size()*4;
767 SharedBuffer<char> mbs(mbl+1);
768 size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
769 if(l == (size_t)(-1))
776 // Split a string using the given delimiter. Returns a vector containing
777 // the component parts.
778 inline std::vector<std::wstring> str_split(const std::wstring &str, wchar_t delimiter)
780 std::vector<std::wstring> parts;
781 std::wstringstream sstr(str);
783 while(std::getline(sstr, part, delimiter))
784 parts.push_back(part);
790 See test.cpp for example cases.
791 wraps degrees to the range of -360...360
792 NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
794 inline float wrapDegrees(float f)
796 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
802 // NOTE: This would be used for wrapping to 0...360
808 // 10, 0.5, -0.5, -0.5
813 /* Wrap to 0...360 */
814 inline float wrapDegrees_0_360(float f)
816 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
828 // 10, 0.5, -0.5, -0.5
833 /* Wrap to -180...180 */
834 inline float wrapDegrees_180(float f)
837 f = wrapDegrees_0_360(f);
842 inline std::string lowercase(const std::string &s)
845 for(size_t i=0; i<s.size(); i++)
848 if(c >= 'A' && c <= 'Z')
855 inline bool is_yes(const std::string &s)
857 std::string s2 = lowercase(trim(s));
858 if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
863 inline s32 stoi(const std::string &s, s32 min, s32 max)
865 s32 i = atoi(s.c_str());
874 // MSVC2010 includes it's own versions of these
875 #if !defined(_MSC_VER) || _MSC_VER < 1600
877 inline s32 stoi(std::string s)
879 return atoi(s.c_str());
882 inline s32 stoi(std::wstring s)
884 return atoi(wide_to_narrow(s).c_str());
887 inline float stof(std::string s)
890 std::istringstream ss(s);
897 inline std::string itos(s32 i)
899 std::ostringstream o;
904 inline std::string ftos(float f)
906 std::ostringstream o;
911 inline void str_replace(std::string & str, std::string const & pattern,
912 std::string const & replacement)
914 std::string::size_type start = str.find(pattern, 0);
915 while(start != str.npos)
917 str.replace(start, pattern.size(), replacement);
918 start = str.find(pattern, start+replacement.size());
922 inline void str_replace_char(std::string & str, char from, char to)
924 for(unsigned int i=0; i<str.size(); i++)
932 A base class for simple background thread implementation
935 class SimpleThread : public JThread
949 virtual ~SimpleThread()
952 virtual void * Thread() = 0;
956 JMutexAutoLock lock(run_mutex);
959 void setRun(bool a_run)
961 JMutexAutoLock lock(run_mutex);
974 FIFO queue (well, actually a FILO also)
987 if(m_list.size() == 0)
988 throw ItemNotFoundException("Queue: queue is empty");
990 typename core::list<T>::Iterator begin = m_list.begin();
997 if(m_list.size() == 0)
998 throw ItemNotFoundException("Queue: queue is empty");
1000 typename core::list<T>::Iterator last = m_list.getLast();
1008 return m_list.size();
1012 core::list<T> m_list;
1016 Thread-safe FIFO queue (well, actually a FILO also)
1019 template<typename T>
1029 JMutexAutoLock lock(m_mutex);
1030 return m_list.size();
1034 JMutexAutoLock lock(m_mutex);
1035 m_list.push_back(t);
1037 T pop_front(u32 wait_time_max_ms=0)
1039 u32 wait_time_ms = 0;
1044 JMutexAutoLock lock(m_mutex);
1046 if(m_list.size() > 0)
1048 typename core::list<T>::Iterator begin = m_list.begin();
1050 m_list.erase(begin);
1054 if(wait_time_ms >= wait_time_max_ms)
1055 throw ItemNotFoundException("MutexedQueue: queue is empty");
1058 // Wait a while before trying again
1063 T pop_back(u32 wait_time_max_ms=0)
1065 u32 wait_time_ms = 0;
1070 JMutexAutoLock lock(m_mutex);
1072 if(m_list.size() > 0)
1074 typename core::list<T>::Iterator last = m_list.getLast();
1080 if(wait_time_ms >= wait_time_max_ms)
1081 throw ItemNotFoundException("MutexedQueue: queue is empty");
1084 // Wait a while before trying again
1095 core::list<T> & getList()
1102 core::list<T> m_list;
1106 A single worker thread - multiple client threads queue framework.
1109 template<typename Caller, typename Data>
1117 template<typename Key, typename T, typename Caller, typename CallerData>
1123 core::list<CallerInfo<Caller, CallerData> > callers;
1126 template<typename Key, typename T, typename Caller, typename CallerData>
1127 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1131 template<typename Key, typename T, typename Caller, typename CallerData>
1139 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1143 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1154 ResultQueue<Key, T, Caller, CallerData> *dest;
1155 core::list<CallerInfo<Caller, CallerData> > callers;
1158 template<typename Key, typename T, typename Caller, typename CallerData>
1164 return m_queue.size();
1167 void add(Key key, Caller caller, CallerData callerdata,
1168 ResultQueue<Key, T, Caller, CallerData> *dest)
1170 JMutexAutoLock lock(m_queue.getMutex());
1173 If the caller is already on the list, only update CallerData
1175 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1176 i = m_queue.getList().begin();
1177 i != m_queue.getList().end(); i++)
1179 GetRequest<Key, T, Caller, CallerData> &request = *i;
1181 if(request.key == key)
1183 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1184 i = request.callers.begin();
1185 i != request.callers.end(); i++)
1187 CallerInfo<Caller, CallerData> &ca = *i;
1188 if(ca.caller == caller)
1190 ca.data = callerdata;
1194 CallerInfo<Caller, CallerData> ca;
1196 ca.data = callerdata;
1197 request.callers.push_back(ca);
1203 Else add a new request to the queue
1206 GetRequest<Key, T, Caller, CallerData> request;
1208 CallerInfo<Caller, CallerData> ca;
1210 ca.data = callerdata;
1211 request.callers.push_back(ca);
1212 request.dest = dest;
1214 m_queue.getList().push_back(request);
1217 GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1219 return m_queue.pop_front(wait_if_empty);
1223 MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1227 Pseudo-random (VC++ rand() sucks)
1230 void mysrand(unsigned seed);
1231 #define MYRAND_MAX 32767
1233 inline int myrand_range(int min, int max)
1235 if(max-min > MYRAND_MAX)
1237 dstream<<"WARNING: myrand_range: max-min > MYRAND_MAX"<<std::endl;
1245 return (myrand()%(max-min+1))+min;
1249 Miscellaneous functions
1252 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
1253 f32 camera_fov, f32 range, f32 *distance_ptr=NULL);
1256 Queue with unique values with fast checking of value existence
1259 template<typename Value>
1265 Does nothing if value is already queued.
1268 false: value already exists
1270 bool push_back(Value value)
1272 // Check if already exists
1273 if(m_map.find(value) != NULL)
1277 m_map.insert(value, 0);
1278 m_list.push_back(value);
1285 typename core::list<Value>::Iterator i = m_list.begin();
1287 m_map.remove(value);
1294 assert(m_list.size() == m_map.size());
1295 return m_list.size();
1299 core::map<Value, u8> m_map;
1300 core::list<Value> m_list;
1304 template<typename Key, typename Value>
1311 assert(m_mutex.IsInitialized());
1314 void set(const Key &name, const Value &value)
1316 JMutexAutoLock lock(m_mutex);
1318 m_values[name] = value;
1321 bool get(const Key &name, Value *result)
1323 JMutexAutoLock lock(m_mutex);
1325 typename core::map<Key, Value>::Node *n;
1326 n = m_values.find(name);
1332 *result = n->getValue();
1338 core::map<Key, Value> m_values;
1344 Generates ids for comparable values.
1345 Id=0 is reserved for "no value".
1348 - Returning value by id (very fast)
1349 - Returning id by value
1350 - Generating a new id for a value
1353 - Remove an id/value pair (is possible to implement but slow)
1355 template<typename T>
1356 class MutexedIdGenerator
1359 MutexedIdGenerator()
1362 assert(m_mutex.IsInitialized());
1365 // Returns true if found
1366 bool getValue(u32 id, T &value)
1370 JMutexAutoLock lock(m_mutex);
1371 if(m_id_to_value.size() < id)
1373 value = m_id_to_value[id-1];
1377 // If id exists for value, returns the id.
1378 // Otherwise generates an id for the value.
1379 u32 getId(const T &value)
1381 JMutexAutoLock lock(m_mutex);
1382 typename core::map<T, u32>::Node *n;
1383 n = m_value_to_id.find(value);
1385 return n->getValue();
1386 m_id_to_value.push_back(value);
1387 u32 new_id = m_id_to_value.size();
1388 m_value_to_id.insert(value, new_id);
1394 // Values are stored here at id-1 position (id 1 = [0])
1395 core::array<T> m_id_to_value;
1396 core::map<T, u32> m_value_to_id;
1400 Checks if a string contains only supplied characters
1402 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1404 for(u32 i=0; i<s.size(); i++)
1406 bool confirmed = false;
1407 for(u32 j=0; j<allowed_chars.size(); j++)
1409 if(s[i] == allowed_chars[j])
1415 if(confirmed == false)
1422 Forcefully wraps string into rows using \n
1423 (no word wrap, used for showing paths in gui)
1425 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1428 for(u32 i=0; i<from.size(); i++)
1430 if(i != 0 && i%rowlen == 0)
1440 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1441 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1444 Returns integer position of node in given floating point position
1446 inline v3s16 floatToInt(v3f p, f32 d)
1449 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1450 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1451 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1456 Returns floating point position of node in given integer position
1458 inline v3f intToFloat(v3s16 p, f32 d)
1469 More serialization stuff
1472 // Creates a string with the length as the first two bytes
1473 inline std::string serializeString(const std::string &plain)
1475 //assert(plain.size() <= 65535);
1476 if(plain.size() > 65535)
1477 throw SerializationError("String too long for serializeString");
1479 writeU16((u8*)&buf[0], plain.size());
1486 // Creates a string with the length as the first two bytes from wide string
1487 inline std::string serializeWideString(const std::wstring &plain)
1489 //assert(plain.size() <= 65535);
1490 if(plain.size() > 65535)
1491 throw SerializationError("String too long for serializeString");
1493 writeU16((u8*)buf, plain.size());
1496 for(u32 i=0; i<plain.size(); i++)
1498 writeU16((u8*)buf, plain[i]);
1504 // Reads a string with the length as the first two bytes
1505 inline std::string deSerializeString(std::istream &is)
1509 if(is.gcount() != 2)
1510 throw SerializationError("deSerializeString: size not read");
1511 u16 s_size = readU16((u8*)buf);
1514 Buffer<char> buf2(s_size);
1515 is.read(&buf2[0], s_size);
1518 s.append(&buf2[0], s_size);
1522 // Reads a wide string with the length as the first two bytes
1523 inline std::wstring deSerializeWideString(std::istream &is)
1527 if(is.gcount() != 2)
1528 throw SerializationError("deSerializeString: size not read");
1529 u16 s_size = readU16((u8*)buf);
1534 for(u32 i=0; i<s_size; i++)
1536 is.read(&buf[0], 2);
1537 wchar_t c16 = readU16((u8*)buf);
1543 // Creates a string with the length as the first four bytes
1544 inline std::string serializeLongString(const std::string &plain)
1547 writeU32((u8*)&buf[0], plain.size());
1554 // Reads a string with the length as the first four bytes
1555 inline std::string deSerializeLongString(std::istream &is)
1559 if(is.gcount() != 4)
1560 throw SerializationError("deSerializeLongString: size not read");
1561 u32 s_size = readU32((u8*)buf);
1564 Buffer<char> buf2(s_size);
1565 is.read(&buf2[0], s_size);
1568 s.append(&buf2[0], s_size);
1574 inline u32 time_to_daynight_ratio(u32 time_of_day)
1576 const s32 daylength = 16;
1577 const s32 nightlength = 6;
1578 const s32 daytimelength = 8;
1580 s32 t = (((time_of_day)%24000)/(24000/d));
1581 if(t < nightlength/2 || t >= d - nightlength/2)
1584 else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
1590 // Random helper. Usually d=BS
1591 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
1593 return core::aabbox3d<f32>(
1594 (float)p.X * d - 0.5*d,
1595 (float)p.Y * d - 0.5*d,
1596 (float)p.Z * d - 0.5*d,
1597 (float)p.X * d + 0.5*d,
1598 (float)p.Y * d + 0.5*d,
1599 (float)p.Z * d + 0.5*d
1603 class IntervalLimiter
1611 dtime: time from last call to this method
1612 wanted_interval: interval wanted
1614 true: action should be skipped
1615 false: action should be done
1617 bool step(float dtime, float wanted_interval)
1619 m_accumulator += dtime;
1620 if(m_accumulator < wanted_interval)
1622 m_accumulator -= wanted_interval;
1626 float m_accumulator;
1629 std::string translatePassword(std::string playername, std::wstring password);