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 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 writeU32((u8*)buf, p);
231 inline u32 readU32(std::istream &is)
235 return readU32((u8*)buf);
238 inline void writeS32(std::ostream &os, u32 p)
241 writeS32((u8*)buf, p);
244 inline u32 readS32(std::istream &is)
248 return readS32((u8*)buf);
251 inline void writeF1000(std::ostream &os, f32 p)
254 writeF1000((u8*)buf, p);
257 inline f32 readF1000(std::istream &is)
261 return readF1000((u8*)buf);
264 inline void writeV3F1000(std::ostream &os, v3f p)
267 writeV3F1000((u8*)buf, p);
270 inline v3f readV3F1000(std::istream &is)
274 return readV3F1000((u8*)buf);
278 None of these are used at the moment
281 template <typename T>
291 SharedPtr(SharedPtr<T> &t)
295 refcount = t.refcount;
303 SharedPtr<T> & operator=(T *t)
311 SharedPtr<T> & operator=(SharedPtr<T> &t)
314 refcount = t.refcount;
327 bool operator!=(T *t)
331 bool operator==(T *t)
335 T & operator[](unsigned int i)
342 assert((*refcount) > 0);
355 template <typename T>
364 Buffer(unsigned int size)
372 Buffer(const Buffer &buffer)
374 m_size = buffer.m_size;
377 data = new T[buffer.m_size];
378 memcpy(data, buffer.data, buffer.m_size);
383 Buffer(const T *t, unsigned int size)
389 memcpy(data, t, size);
398 Buffer& operator=(const Buffer &buffer)
403 m_size = buffer.m_size;
406 data = new T[buffer.m_size];
407 memcpy(data, buffer.data, buffer.m_size);
413 T & operator[](unsigned int i) const
417 T * operator*() const
421 unsigned int getSize() const
435 template <typename T>
443 refcount = new unsigned int;
446 SharedBuffer(unsigned int size)
450 data = new T[m_size];
453 refcount = new unsigned int;
456 SharedBuffer(const SharedBuffer &buffer)
458 //std::cout<<"SharedBuffer(const SharedBuffer &buffer)"<<std::endl;
459 m_size = buffer.m_size;
461 refcount = buffer.refcount;
464 SharedBuffer & operator=(const SharedBuffer & buffer)
466 //std::cout<<"SharedBuffer & operator=(const SharedBuffer & buffer)"<<std::endl;
470 m_size = buffer.m_size;
472 refcount = buffer.refcount;
479 SharedBuffer(T *t, unsigned int size)
484 data = new T[m_size];
485 memcpy(data, t, m_size);
489 refcount = new unsigned int;
495 SharedBuffer(const Buffer<T> &buffer)
497 m_size = buffer.getSize();
500 data = new T[m_size];
501 memcpy(data, *buffer, buffer.getSize());
505 refcount = new unsigned int;
512 T & operator[](unsigned int i) const
517 T * operator*() const
521 unsigned int getSize() const
525 operator Buffer<T>() const
527 return Buffer<T>(data, m_size);
532 assert((*refcount) > 0);
543 unsigned int *refcount;
546 inline SharedBuffer<u8> SharedBufferFromString(const char *string)
548 SharedBuffer<u8> b((u8*)string, strlen(string)+1);
553 class MutexedVariable
556 MutexedVariable(T value):
564 JMutexAutoLock lock(m_mutex);
570 JMutexAutoLock lock(m_mutex);
574 // You'll want to grab this in a SharedPtr
575 JMutexAutoLock * getLock()
577 return new JMutexAutoLock(m_mutex);
580 // You pretty surely want to grab the lock when accessing this
594 TimeTaker(const char *name, u32 *result=NULL);
601 u32 stop(bool quiet=false);
613 // Sets the color of all vertices in the mesh
614 void setMeshVerticesColor(scene::IMesh* mesh, video::SColor& color);
617 // Calculates the borders of a "d-radius" cube
618 inline void getFacePositions(core::list<v3s16> &list, u16 d)
622 list.push_back(v3s16(0,0,0));
628 This is an optimized sequence of coordinates.
630 list.push_back(v3s16( 0, 1, 0)); // top
631 list.push_back(v3s16( 0, 0, 1)); // back
632 list.push_back(v3s16(-1, 0, 0)); // left
633 list.push_back(v3s16( 1, 0, 0)); // right
634 list.push_back(v3s16( 0, 0,-1)); // front
635 list.push_back(v3s16( 0,-1, 0)); // bottom
637 list.push_back(v3s16(-1, 0, 1)); // back left
638 list.push_back(v3s16( 1, 0, 1)); // back right
639 list.push_back(v3s16(-1, 0,-1)); // front left
640 list.push_back(v3s16( 1, 0,-1)); // front right
641 list.push_back(v3s16(-1,-1, 0)); // bottom left
642 list.push_back(v3s16( 1,-1, 0)); // bottom right
643 list.push_back(v3s16( 0,-1, 1)); // bottom back
644 list.push_back(v3s16( 0,-1,-1)); // bottom front
645 list.push_back(v3s16(-1, 1, 0)); // top left
646 list.push_back(v3s16( 1, 1, 0)); // top right
647 list.push_back(v3s16( 0, 1, 1)); // top back
648 list.push_back(v3s16( 0, 1,-1)); // top front
650 list.push_back(v3s16(-1, 1, 1)); // top back-left
651 list.push_back(v3s16( 1, 1, 1)); // top back-right
652 list.push_back(v3s16(-1, 1,-1)); // top front-left
653 list.push_back(v3s16( 1, 1,-1)); // top front-right
654 list.push_back(v3s16(-1,-1, 1)); // bottom back-left
655 list.push_back(v3s16( 1,-1, 1)); // bottom back-right
656 list.push_back(v3s16(-1,-1,-1)); // bottom front-left
657 list.push_back(v3s16( 1,-1,-1)); // bottom front-right
662 // Take blocks in all sides, starting from y=0 and going +-y
663 for(s16 y=0; y<=d-1; y++)
665 // Left and right side, including borders
666 for(s16 z=-d; z<=d; z++)
668 list.push_back(v3s16(d,y,z));
669 list.push_back(v3s16(-d,y,z));
672 list.push_back(v3s16(d,-y,z));
673 list.push_back(v3s16(-d,-y,z));
676 // Back and front side, excluding borders
677 for(s16 x=-d+1; x<=d-1; x++)
679 list.push_back(v3s16(x,y,d));
680 list.push_back(v3s16(x,y,-d));
683 list.push_back(v3s16(x,-y,d));
684 list.push_back(v3s16(x,-y,-d));
689 // Take the bottom and top face with borders
690 // -d<x<d, y=+-d, -d<z<d
691 for(s16 x=-d; x<=d; x++)
692 for(s16 z=-d; z<=d; z++)
694 list.push_back(v3s16(x,-d,z));
695 list.push_back(v3s16(x,d,z));
699 class IndentationRaiser
702 IndentationRaiser(u16 *indentation)
704 m_indentation = indentation;
715 inline s16 getContainerPos(s16 p, s16 d)
717 return (p>=0 ? p : p-d+1) / d;
720 inline v2s16 getContainerPos(v2s16 p, s16 d)
723 getContainerPos(p.X, d),
724 getContainerPos(p.Y, d)
728 inline v3s16 getContainerPos(v3s16 p, s16 d)
731 getContainerPos(p.X, d),
732 getContainerPos(p.Y, d),
733 getContainerPos(p.Z, d)
737 inline v2s16 getContainerPos(v2s16 p, v2s16 d)
740 getContainerPos(p.X, d.X),
741 getContainerPos(p.Y, d.Y)
745 inline v3s16 getContainerPos(v3s16 p, v3s16 d)
748 getContainerPos(p.X, d.X),
749 getContainerPos(p.Y, d.Y),
750 getContainerPos(p.Z, d.Z)
754 inline bool isInArea(v3s16 p, s16 d)
757 p.X >= 0 && p.X < d &&
758 p.Y >= 0 && p.Y < d &&
763 inline bool isInArea(v2s16 p, s16 d)
766 p.X >= 0 && p.X < d &&
771 inline bool isInArea(v3s16 p, v3s16 d)
774 p.X >= 0 && p.X < d.X &&
775 p.Y >= 0 && p.Y < d.Y &&
776 p.Z >= 0 && p.Z < d.Z
780 inline s16 rangelim(s16 i, s16 max)
789 #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
791 inline v3s16 arealim(v3s16 p, s16 d)
808 inline std::wstring narrow_to_wide(const std::string& mbs)
810 size_t wcl = mbs.size();
811 Buffer<wchar_t> wcs(wcl+1);
812 size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
813 if(l == (size_t)(-1))
814 return L"<invalid multibyte string>";
819 inline std::string wide_to_narrow(const std::wstring& wcs)
821 size_t mbl = wcs.size()*4;
822 SharedBuffer<char> mbs(mbl+1);
823 size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
824 if(l == (size_t)(-1))
831 // Split a string using the given delimiter. Returns a vector containing
832 // the component parts.
833 inline std::vector<std::wstring> str_split(const std::wstring &str, wchar_t delimiter)
835 std::vector<std::wstring> parts;
836 std::wstringstream sstr(str);
838 while(std::getline(sstr, part, delimiter))
839 parts.push_back(part);
845 See test.cpp for example cases.
846 wraps degrees to the range of -360...360
847 NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
849 inline float wrapDegrees(float f)
851 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
857 // NOTE: This would be used for wrapping to 0...360
863 // 10, 0.5, -0.5, -0.5
868 /* Wrap to 0...360 */
869 inline float wrapDegrees_0_360(float f)
871 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
883 // 10, 0.5, -0.5, -0.5
888 /* Wrap to -180...180 */
889 inline float wrapDegrees_180(float f)
892 f = wrapDegrees_0_360(f);
897 inline std::string lowercase(const std::string &s)
900 for(size_t i=0; i<s.size(); i++)
903 if(c >= 'A' && c <= 'Z')
910 inline bool is_yes(const std::string &s)
912 std::string s2 = lowercase(trim(s));
913 if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
918 inline s32 stoi(const std::string &s, s32 min, s32 max)
920 s32 i = atoi(s.c_str());
929 // MSVC2010 includes it's own versions of these
930 #if !defined(_MSC_VER) || _MSC_VER < 1600
932 inline s32 stoi(std::string s)
934 return atoi(s.c_str());
937 inline s32 stoi(std::wstring s)
939 return atoi(wide_to_narrow(s).c_str());
942 inline float stof(std::string s)
945 std::istringstream ss(s);
952 inline std::string itos(s32 i)
954 std::ostringstream o;
959 inline std::string ftos(float f)
961 std::ostringstream o;
966 inline void str_replace(std::string & str, std::string const & pattern,
967 std::string const & replacement)
969 std::string::size_type start = str.find(pattern, 0);
970 while(start != str.npos)
972 str.replace(start, pattern.size(), replacement);
973 start = str.find(pattern, start+replacement.size());
977 inline void str_replace_char(std::string & str, char from, char to)
979 for(unsigned int i=0; i<str.size(); i++)
987 A base class for simple background thread implementation
990 class SimpleThread : public JThread
1004 virtual ~SimpleThread()
1007 virtual void * Thread() = 0;
1011 JMutexAutoLock lock(run_mutex);
1014 void setRun(bool a_run)
1016 JMutexAutoLock lock(run_mutex);
1029 FIFO queue (well, actually a FILO also)
1031 template<typename T>
1037 m_list.push_back(t);
1042 if(m_list.size() == 0)
1043 throw ItemNotFoundException("Queue: queue is empty");
1045 typename core::list<T>::Iterator begin = m_list.begin();
1047 m_list.erase(begin);
1052 if(m_list.size() == 0)
1053 throw ItemNotFoundException("Queue: queue is empty");
1055 typename core::list<T>::Iterator last = m_list.getLast();
1063 return m_list.size();
1067 core::list<T> m_list;
1071 Thread-safe FIFO queue (well, actually a FILO also)
1074 template<typename T>
1084 JMutexAutoLock lock(m_mutex);
1085 return m_list.size();
1089 JMutexAutoLock lock(m_mutex);
1090 m_list.push_back(t);
1092 T pop_front(u32 wait_time_max_ms=0)
1094 u32 wait_time_ms = 0;
1099 JMutexAutoLock lock(m_mutex);
1101 if(m_list.size() > 0)
1103 typename core::list<T>::Iterator begin = m_list.begin();
1105 m_list.erase(begin);
1109 if(wait_time_ms >= wait_time_max_ms)
1110 throw ItemNotFoundException("MutexedQueue: queue is empty");
1113 // Wait a while before trying again
1118 T pop_back(u32 wait_time_max_ms=0)
1120 u32 wait_time_ms = 0;
1125 JMutexAutoLock lock(m_mutex);
1127 if(m_list.size() > 0)
1129 typename core::list<T>::Iterator last = m_list.getLast();
1135 if(wait_time_ms >= wait_time_max_ms)
1136 throw ItemNotFoundException("MutexedQueue: queue is empty");
1139 // Wait a while before trying again
1150 core::list<T> & getList()
1157 core::list<T> m_list;
1161 A single worker thread - multiple client threads queue framework.
1164 template<typename Caller, typename Data>
1172 template<typename Key, typename T, typename Caller, typename CallerData>
1178 core::list<CallerInfo<Caller, CallerData> > callers;
1181 template<typename Key, typename T, typename Caller, typename CallerData>
1182 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1186 template<typename Key, typename T, typename Caller, typename CallerData>
1194 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1198 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1209 ResultQueue<Key, T, Caller, CallerData> *dest;
1210 core::list<CallerInfo<Caller, CallerData> > callers;
1213 template<typename Key, typename T, typename Caller, typename CallerData>
1219 return m_queue.size();
1222 void add(Key key, Caller caller, CallerData callerdata,
1223 ResultQueue<Key, T, Caller, CallerData> *dest)
1225 JMutexAutoLock lock(m_queue.getMutex());
1228 If the caller is already on the list, only update CallerData
1230 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1231 i = m_queue.getList().begin();
1232 i != m_queue.getList().end(); i++)
1234 GetRequest<Key, T, Caller, CallerData> &request = *i;
1236 if(request.key == key)
1238 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1239 i = request.callers.begin();
1240 i != request.callers.end(); i++)
1242 CallerInfo<Caller, CallerData> &ca = *i;
1243 if(ca.caller == caller)
1245 ca.data = callerdata;
1249 CallerInfo<Caller, CallerData> ca;
1251 ca.data = callerdata;
1252 request.callers.push_back(ca);
1258 Else add a new request to the queue
1261 GetRequest<Key, T, Caller, CallerData> request;
1263 CallerInfo<Caller, CallerData> ca;
1265 ca.data = callerdata;
1266 request.callers.push_back(ca);
1267 request.dest = dest;
1269 m_queue.getList().push_back(request);
1272 GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1274 return m_queue.pop_front(wait_if_empty);
1278 MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1282 Pseudo-random (VC++ rand() sucks)
1285 void mysrand(unsigned seed);
1286 #define MYRAND_MAX 32767
1288 int myrand_range(int min, int max);
1291 Miscellaneous functions
1294 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
1295 f32 camera_fov, f32 range, f32 *distance_ptr=NULL);
1298 Queue with unique values with fast checking of value existence
1301 template<typename Value>
1307 Does nothing if value is already queued.
1310 false: value already exists
1312 bool push_back(Value value)
1314 // Check if already exists
1315 if(m_map.find(value) != NULL)
1319 m_map.insert(value, 0);
1320 m_list.push_back(value);
1327 typename core::list<Value>::Iterator i = m_list.begin();
1329 m_map.remove(value);
1336 assert(m_list.size() == m_map.size());
1337 return m_list.size();
1341 core::map<Value, u8> m_map;
1342 core::list<Value> m_list;
1346 template<typename Key, typename Value>
1353 assert(m_mutex.IsInitialized());
1356 void set(const Key &name, const Value &value)
1358 JMutexAutoLock lock(m_mutex);
1360 m_values[name] = value;
1363 bool get(const Key &name, Value *result)
1365 JMutexAutoLock lock(m_mutex);
1367 typename core::map<Key, Value>::Node *n;
1368 n = m_values.find(name);
1374 *result = n->getValue();
1380 core::map<Key, Value> m_values;
1386 Generates ids for comparable values.
1387 Id=0 is reserved for "no value".
1390 - Returning value by id (very fast)
1391 - Returning id by value
1392 - Generating a new id for a value
1395 - Remove an id/value pair (is possible to implement but slow)
1397 template<typename T>
1398 class MutexedIdGenerator
1401 MutexedIdGenerator()
1404 assert(m_mutex.IsInitialized());
1407 // Returns true if found
1408 bool getValue(u32 id, T &value)
1412 JMutexAutoLock lock(m_mutex);
1413 if(m_id_to_value.size() < id)
1415 value = m_id_to_value[id-1];
1419 // If id exists for value, returns the id.
1420 // Otherwise generates an id for the value.
1421 u32 getId(const T &value)
1423 JMutexAutoLock lock(m_mutex);
1424 typename core::map<T, u32>::Node *n;
1425 n = m_value_to_id.find(value);
1427 return n->getValue();
1428 m_id_to_value.push_back(value);
1429 u32 new_id = m_id_to_value.size();
1430 m_value_to_id.insert(value, new_id);
1436 // Values are stored here at id-1 position (id 1 = [0])
1437 core::array<T> m_id_to_value;
1438 core::map<T, u32> m_value_to_id;
1442 Checks if a string contains only supplied characters
1444 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1446 for(u32 i=0; i<s.size(); i++)
1448 bool confirmed = false;
1449 for(u32 j=0; j<allowed_chars.size(); j++)
1451 if(s[i] == allowed_chars[j])
1457 if(confirmed == false)
1464 Forcefully wraps string into rows using \n
1465 (no word wrap, used for showing paths in gui)
1467 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1470 for(u32 i=0; i<from.size(); i++)
1472 if(i != 0 && i%rowlen == 0)
1482 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1483 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1486 Returns integer position of node in given floating point position
1488 inline v3s16 floatToInt(v3f p, f32 d)
1491 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1492 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1493 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1498 Returns floating point position of node in given integer position
1500 inline v3f intToFloat(v3s16 p, f32 d)
1511 More serialization stuff
1514 // Creates a string with the length as the first two bytes
1515 inline std::string serializeString(const std::string &plain)
1517 //assert(plain.size() <= 65535);
1518 if(plain.size() > 65535)
1519 throw SerializationError("String too long for serializeString");
1521 writeU16((u8*)&buf[0], plain.size());
1528 // Creates a string with the length as the first two bytes from wide string
1529 inline std::string serializeWideString(const std::wstring &plain)
1531 //assert(plain.size() <= 65535);
1532 if(plain.size() > 65535)
1533 throw SerializationError("String too long for serializeString");
1535 writeU16((u8*)buf, plain.size());
1538 for(u32 i=0; i<plain.size(); i++)
1540 writeU16((u8*)buf, plain[i]);
1546 // Reads a string with the length as the first two bytes
1547 inline std::string deSerializeString(std::istream &is)
1551 if(is.gcount() != 2)
1552 throw SerializationError("deSerializeString: size not read");
1553 u16 s_size = readU16((u8*)buf);
1556 Buffer<char> buf2(s_size);
1557 is.read(&buf2[0], s_size);
1560 s.append(&buf2[0], s_size);
1564 // Reads a wide string with the length as the first two bytes
1565 inline std::wstring deSerializeWideString(std::istream &is)
1569 if(is.gcount() != 2)
1570 throw SerializationError("deSerializeString: size not read");
1571 u16 s_size = readU16((u8*)buf);
1576 for(u32 i=0; i<s_size; i++)
1578 is.read(&buf[0], 2);
1579 wchar_t c16 = readU16((u8*)buf);
1585 // Creates a string with the length as the first four bytes
1586 inline std::string serializeLongString(const std::string &plain)
1589 writeU32((u8*)&buf[0], plain.size());
1596 // Reads a string with the length as the first four bytes
1597 inline std::string deSerializeLongString(std::istream &is)
1601 if(is.gcount() != 4)
1602 throw SerializationError("deSerializeLongString: size not read");
1603 u32 s_size = readU32((u8*)buf);
1606 Buffer<char> buf2(s_size);
1607 is.read(&buf2[0], s_size);
1610 s.append(&buf2[0], s_size);
1616 inline u32 time_to_daynight_ratio(u32 time_of_day)
1618 const s32 daylength = 16;
1619 const s32 nightlength = 6;
1620 const s32 daytimelength = 8;
1622 s32 t = (((time_of_day)%24000)/(24000/d));
1623 if(t < nightlength/2 || t >= d - nightlength/2)
1626 else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
1632 // Random helper. Usually d=BS
1633 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
1635 return core::aabbox3d<f32>(
1636 (float)p.X * d - 0.5*d,
1637 (float)p.Y * d - 0.5*d,
1638 (float)p.Z * d - 0.5*d,
1639 (float)p.X * d + 0.5*d,
1640 (float)p.Y * d + 0.5*d,
1641 (float)p.Z * d + 0.5*d
1645 class IntervalLimiter
1653 dtime: time from last call to this method
1654 wanted_interval: interval wanted
1656 true: action should be skipped
1657 false: action should be done
1659 bool step(float dtime, float wanted_interval)
1661 m_accumulator += dtime;
1662 if(m_accumulator < wanted_interval)
1664 m_accumulator -= wanted_interval;
1668 float m_accumulator;
1671 std::string translatePassword(std::string playername, std::wstring password);