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, u32 p)
228 writeU16((u8*)buf, p);
231 inline u32 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 int myrand_range(int min, int max);
1236 Miscellaneous functions
1239 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
1240 f32 camera_fov, f32 range, f32 *distance_ptr=NULL);
1243 Queue with unique values with fast checking of value existence
1246 template<typename Value>
1252 Does nothing if value is already queued.
1255 false: value already exists
1257 bool push_back(Value value)
1259 // Check if already exists
1260 if(m_map.find(value) != NULL)
1264 m_map.insert(value, 0);
1265 m_list.push_back(value);
1272 typename core::list<Value>::Iterator i = m_list.begin();
1274 m_map.remove(value);
1281 assert(m_list.size() == m_map.size());
1282 return m_list.size();
1286 core::map<Value, u8> m_map;
1287 core::list<Value> m_list;
1291 template<typename Key, typename Value>
1298 assert(m_mutex.IsInitialized());
1301 void set(const Key &name, const Value &value)
1303 JMutexAutoLock lock(m_mutex);
1305 m_values[name] = value;
1308 bool get(const Key &name, Value *result)
1310 JMutexAutoLock lock(m_mutex);
1312 typename core::map<Key, Value>::Node *n;
1313 n = m_values.find(name);
1319 *result = n->getValue();
1325 core::map<Key, Value> m_values;
1331 Generates ids for comparable values.
1332 Id=0 is reserved for "no value".
1335 - Returning value by id (very fast)
1336 - Returning id by value
1337 - Generating a new id for a value
1340 - Remove an id/value pair (is possible to implement but slow)
1342 template<typename T>
1343 class MutexedIdGenerator
1346 MutexedIdGenerator()
1349 assert(m_mutex.IsInitialized());
1352 // Returns true if found
1353 bool getValue(u32 id, T &value)
1357 JMutexAutoLock lock(m_mutex);
1358 if(m_id_to_value.size() < id)
1360 value = m_id_to_value[id-1];
1364 // If id exists for value, returns the id.
1365 // Otherwise generates an id for the value.
1366 u32 getId(const T &value)
1368 JMutexAutoLock lock(m_mutex);
1369 typename core::map<T, u32>::Node *n;
1370 n = m_value_to_id.find(value);
1372 return n->getValue();
1373 m_id_to_value.push_back(value);
1374 u32 new_id = m_id_to_value.size();
1375 m_value_to_id.insert(value, new_id);
1381 // Values are stored here at id-1 position (id 1 = [0])
1382 core::array<T> m_id_to_value;
1383 core::map<T, u32> m_value_to_id;
1387 Checks if a string contains only supplied characters
1389 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1391 for(u32 i=0; i<s.size(); i++)
1393 bool confirmed = false;
1394 for(u32 j=0; j<allowed_chars.size(); j++)
1396 if(s[i] == allowed_chars[j])
1402 if(confirmed == false)
1409 Forcefully wraps string into rows using \n
1410 (no word wrap, used for showing paths in gui)
1412 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1415 for(u32 i=0; i<from.size(); i++)
1417 if(i != 0 && i%rowlen == 0)
1427 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1428 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1431 Returns integer position of node in given floating point position
1433 inline v3s16 floatToInt(v3f p, f32 d)
1436 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1437 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1438 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1443 Returns floating point position of node in given integer position
1445 inline v3f intToFloat(v3s16 p, f32 d)
1456 More serialization stuff
1459 // Creates a string with the length as the first two bytes
1460 inline std::string serializeString(const std::string &plain)
1462 //assert(plain.size() <= 65535);
1463 if(plain.size() > 65535)
1464 throw SerializationError("String too long for serializeString");
1466 writeU16((u8*)&buf[0], plain.size());
1473 // Creates a string with the length as the first two bytes from wide string
1474 inline std::string serializeWideString(const std::wstring &plain)
1476 //assert(plain.size() <= 65535);
1477 if(plain.size() > 65535)
1478 throw SerializationError("String too long for serializeString");
1480 writeU16((u8*)buf, plain.size());
1483 for(u32 i=0; i<plain.size(); i++)
1485 writeU16((u8*)buf, plain[i]);
1491 // Reads a string with the length as the first two bytes
1492 inline std::string deSerializeString(std::istream &is)
1496 if(is.gcount() != 2)
1497 throw SerializationError("deSerializeString: size not read");
1498 u16 s_size = readU16((u8*)buf);
1501 Buffer<char> buf2(s_size);
1502 is.read(&buf2[0], s_size);
1505 s.append(&buf2[0], s_size);
1509 // Reads a wide string with the length as the first two bytes
1510 inline std::wstring deSerializeWideString(std::istream &is)
1514 if(is.gcount() != 2)
1515 throw SerializationError("deSerializeString: size not read");
1516 u16 s_size = readU16((u8*)buf);
1521 for(u32 i=0; i<s_size; i++)
1523 is.read(&buf[0], 2);
1524 wchar_t c16 = readU16((u8*)buf);
1530 // Creates a string with the length as the first four bytes
1531 inline std::string serializeLongString(const std::string &plain)
1534 writeU32((u8*)&buf[0], plain.size());
1541 // Reads a string with the length as the first four bytes
1542 inline std::string deSerializeLongString(std::istream &is)
1546 if(is.gcount() != 4)
1547 throw SerializationError("deSerializeLongString: size not read");
1548 u32 s_size = readU32((u8*)buf);
1551 Buffer<char> buf2(s_size);
1552 is.read(&buf2[0], s_size);
1555 s.append(&buf2[0], s_size);
1561 inline u32 time_to_daynight_ratio(u32 time_of_day)
1563 const s32 daylength = 16;
1564 const s32 nightlength = 6;
1565 const s32 daytimelength = 8;
1567 s32 t = (((time_of_day)%24000)/(24000/d));
1568 if(t < nightlength/2 || t >= d - nightlength/2)
1571 else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
1577 // Random helper. Usually d=BS
1578 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
1580 return core::aabbox3d<f32>(
1581 (float)p.X * d - 0.5*d,
1582 (float)p.Y * d - 0.5*d,
1583 (float)p.Z * d - 0.5*d,
1584 (float)p.X * d + 0.5*d,
1585 (float)p.Y * d + 0.5*d,
1586 (float)p.Z * d + 0.5*d
1590 class IntervalLimiter
1598 dtime: time from last call to this method
1599 wanted_interval: interval wanted
1601 true: action should be skipped
1602 false: action should be done
1604 bool step(float dtime, float wanted_interval)
1606 m_accumulator += dtime;
1607 if(m_accumulator < wanted_interval)
1609 m_accumulator -= wanted_interval;
1613 float m_accumulator;
1616 std::string translatePassword(std::string playername, std::wstring password);