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
29 #include <jmutexautolock.h>
31 #include "common_irrlicht.h"
34 #include "exceptions.h"
37 extern const v3s16 g_6dirs[6];
39 extern const v3s16 g_26dirs[26];
42 extern const v3s16 g_27dirs[27];
44 inline void writeU64(u8 *data, u64 i)
46 data[0] = ((i>>56)&0xff);
47 data[1] = ((i>>48)&0xff);
48 data[2] = ((i>>40)&0xff);
49 data[3] = ((i>>32)&0xff);
50 data[4] = ((i>>24)&0xff);
51 data[5] = ((i>>16)&0xff);
52 data[6] = ((i>> 8)&0xff);
53 data[7] = ((i>> 0)&0xff);
56 inline void writeU32(u8 *data, u32 i)
58 data[0] = ((i>>24)&0xff);
59 data[1] = ((i>>16)&0xff);
60 data[2] = ((i>> 8)&0xff);
61 data[3] = ((i>> 0)&0xff);
64 inline void writeU16(u8 *data, u16 i)
66 data[0] = ((i>> 8)&0xff);
67 data[1] = ((i>> 0)&0xff);
70 inline void writeU8(u8 *data, u8 i)
72 data[0] = ((i>> 0)&0xff);
75 inline u64 readU64(u8 *data)
77 return ((u64)data[0]<<56) | ((u64)data[1]<<48)
78 | ((u64)data[2]<<40) | ((u64)data[3]<<32)
79 | ((u64)data[4]<<24) | ((u64)data[5]<<16)
80 | ((u64)data[6]<<8) | ((u64)data[7]<<0);
83 inline u32 readU32(u8 *data)
85 return (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | (data[3]<<0);
88 inline u16 readU16(u8 *data)
90 return (data[0]<<8) | (data[1]<<0);
93 inline u8 readU8(u8 *data)
98 inline void writeS32(u8 *data, s32 i){
99 writeU32(data, (u32)i);
101 inline s32 readS32(u8 *data){
102 return (s32)readU32(data);
105 inline void writeF1000(u8 *data, f32 i){
106 writeS32(data, i*1000);
108 inline f32 readF1000(u8 *data){
109 return (f32)readS32(data)/1000.;
112 inline void writeS16(u8 *data, s16 i){
113 writeU16(data, (u16)i);
115 inline s16 readS16(u8 *data){
116 return (s16)readU16(data);
119 inline void writeV3S32(u8 *data, v3s32 p)
121 writeS32(&data[0], p.X);
122 writeS32(&data[4], p.Y);
123 writeS32(&data[8], p.Z);
125 inline v3s32 readV3S32(u8 *data)
128 p.X = readS32(&data[0]);
129 p.Y = readS32(&data[4]);
130 p.Z = readS32(&data[8]);
134 inline void writeV3F1000(u8 *data, v3f p)
136 writeF1000(&data[0], p.X);
137 writeF1000(&data[4], p.Y);
138 writeF1000(&data[8], p.Z);
140 inline v3f readV3F1000(u8 *data)
143 p.X = (float)readF1000(&data[0]);
144 p.Y = (float)readF1000(&data[4]);
145 p.Z = (float)readF1000(&data[8]);
149 inline void writeV2S16(u8 *data, v2s16 p)
151 writeS16(&data[0], p.X);
152 writeS16(&data[2], p.Y);
155 inline v2s16 readV2S16(u8 *data)
158 p.X = readS16(&data[0]);
159 p.Y = readS16(&data[2]);
163 inline void writeV2S32(u8 *data, v2s32 p)
165 writeS32(&data[0], p.X);
166 writeS32(&data[2], p.Y);
169 inline v2s32 readV2S32(u8 *data)
172 p.X = readS32(&data[0]);
173 p.Y = readS32(&data[2]);
177 inline void writeV3S16(u8 *data, v3s16 p)
179 writeS16(&data[0], p.X);
180 writeS16(&data[2], p.Y);
181 writeS16(&data[4], p.Z);
184 inline v3s16 readV3S16(u8 *data)
187 p.X = readS16(&data[0]);
188 p.Y = readS16(&data[2]);
189 p.Z = readS16(&data[4]);
194 The above stuff directly interfaced to iostream
197 inline void writeU8(std::ostream &os, u8 p)
200 writeU8((u8*)buf, p);
203 inline u8 readU8(std::istream &is)
207 return readU8((u8*)buf);
210 inline void writeU16(std::ostream &os, u16 p)
213 writeU16((u8*)buf, p);
216 inline u16 readU16(std::istream &is)
220 return readU16((u8*)buf);
223 inline void writeF1000(std::ostream &os, f32 p)
226 writeF1000((u8*)buf, p);
229 inline f32 readF1000(std::istream &is)
233 return readF1000((u8*)buf);
236 inline void writeV3F1000(std::ostream &os, v3f p)
239 writeV3F1000((u8*)buf, p);
242 inline v3f readV3F1000(std::istream &is)
246 return readV3F1000((u8*)buf);
250 None of these are used at the moment
253 template <typename T>
263 SharedPtr(SharedPtr<T> &t)
267 refcount = t.refcount;
275 SharedPtr<T> & operator=(T *t)
283 SharedPtr<T> & operator=(SharedPtr<T> &t)
286 refcount = t.refcount;
299 bool operator!=(T *t)
303 bool operator==(T *t)
307 T & operator[](unsigned int i)
314 assert((*refcount) > 0);
327 template <typename T>
331 Buffer(unsigned int size)
336 Buffer(const Buffer &buffer)
338 m_size = buffer.m_size;
339 data = new T[buffer.m_size];
340 memcpy(data, buffer.data, buffer.m_size);
342 Buffer(T *t, unsigned int size)
346 memcpy(data, t, size);
352 T & operator[](unsigned int i) const
356 T * operator*() const
360 unsigned int getSize() const
369 template <typename T>
373 SharedBuffer(unsigned int size)
377 refcount = new unsigned int;
380 SharedBuffer(const SharedBuffer &buffer)
382 //std::cout<<"SharedBuffer(const SharedBuffer &buffer)"<<std::endl;
383 m_size = buffer.m_size;
385 refcount = buffer.refcount;
388 SharedBuffer & operator=(const SharedBuffer & buffer)
390 //std::cout<<"SharedBuffer & operator=(const SharedBuffer & buffer)"<<std::endl;
394 m_size = buffer.m_size;
396 refcount = buffer.refcount;
403 SharedBuffer(T *t, unsigned int size)
407 memcpy(data, t, size);
408 refcount = new unsigned int;
414 SharedBuffer(const Buffer<T> &buffer)
416 m_size = buffer.m_size;
417 data = new T[buffer.getSize()];
418 memcpy(data, *buffer, buffer.getSize());
419 refcount = new unsigned int;
426 T & operator[](unsigned int i) const
430 T * operator*() const
434 unsigned int getSize() const
441 assert((*refcount) > 0);
451 unsigned int *refcount;
454 inline SharedBuffer<u8> SharedBufferFromString(const char *string)
456 SharedBuffer<u8> b((u8*)string, strlen(string)+1);
461 class MutexedVariable
464 MutexedVariable(T value):
472 JMutexAutoLock lock(m_mutex);
478 JMutexAutoLock lock(m_mutex);
482 // You'll want to grab this in a SharedPtr
483 JMutexAutoLock * getLock()
485 return new JMutexAutoLock(m_mutex);
488 // You pretty surely want to grab the lock when accessing this
499 class IrrlichtWrapper;
504 TimeTaker(const char *name, u32 *result=NULL);
511 u32 stop(bool quiet=false);
522 // Calculates the borders of a "d-radius" cube
523 inline void getFacePositions(core::list<v3s16> &list, u16 d)
527 list.push_back(v3s16(0,0,0));
533 This is an optimized sequence of coordinates.
535 list.push_back(v3s16( 0, 1, 0)); // top
536 list.push_back(v3s16( 0, 0, 1)); // back
537 list.push_back(v3s16(-1, 0, 0)); // left
538 list.push_back(v3s16( 1, 0, 0)); // right
539 list.push_back(v3s16( 0, 0,-1)); // front
540 list.push_back(v3s16( 0,-1, 0)); // bottom
542 list.push_back(v3s16(-1, 0, 1)); // back left
543 list.push_back(v3s16( 1, 0, 1)); // back right
544 list.push_back(v3s16(-1, 0,-1)); // front left
545 list.push_back(v3s16( 1, 0,-1)); // front right
546 list.push_back(v3s16(-1,-1, 0)); // bottom left
547 list.push_back(v3s16( 1,-1, 0)); // bottom right
548 list.push_back(v3s16( 0,-1, 1)); // bottom back
549 list.push_back(v3s16( 0,-1,-1)); // bottom front
550 list.push_back(v3s16(-1, 1, 0)); // top left
551 list.push_back(v3s16( 1, 1, 0)); // top right
552 list.push_back(v3s16( 0, 1, 1)); // top back
553 list.push_back(v3s16( 0, 1,-1)); // top front
555 list.push_back(v3s16(-1, 1, 1)); // top back-left
556 list.push_back(v3s16( 1, 1, 1)); // top back-right
557 list.push_back(v3s16(-1, 1,-1)); // top front-left
558 list.push_back(v3s16( 1, 1,-1)); // top front-right
559 list.push_back(v3s16(-1,-1, 1)); // bottom back-left
560 list.push_back(v3s16( 1,-1, 1)); // bottom back-right
561 list.push_back(v3s16(-1,-1,-1)); // bottom front-left
562 list.push_back(v3s16( 1,-1,-1)); // bottom front-right
567 // Take blocks in all sides, starting from y=0 and going +-y
568 for(s16 y=0; y<=d-1; y++)
570 // Left and right side, including borders
571 for(s16 z=-d; z<=d; z++)
573 list.push_back(v3s16(d,y,z));
574 list.push_back(v3s16(-d,y,z));
577 list.push_back(v3s16(d,-y,z));
578 list.push_back(v3s16(-d,-y,z));
581 // Back and front side, excluding borders
582 for(s16 x=-d+1; x<=d-1; x++)
584 list.push_back(v3s16(x,y,d));
585 list.push_back(v3s16(x,y,-d));
588 list.push_back(v3s16(x,-y,d));
589 list.push_back(v3s16(x,-y,-d));
594 // Take the bottom and top face with borders
595 // -d<x<d, y=+-d, -d<z<d
596 for(s16 x=-d; x<=d; x++)
597 for(s16 z=-d; z<=d; z++)
599 list.push_back(v3s16(x,-d,z));
600 list.push_back(v3s16(x,d,z));
604 class IndentationRaiser
607 IndentationRaiser(u16 *indentation)
609 m_indentation = indentation;
620 inline s16 getContainerPos(s16 p, s16 d)
622 return (p>=0 ? p : p-d+1) / d;
625 inline v2s16 getContainerPos(v2s16 p, s16 d)
628 getContainerPos(p.X, d),
629 getContainerPos(p.Y, d)
633 inline v3s16 getContainerPos(v3s16 p, s16 d)
636 getContainerPos(p.X, d),
637 getContainerPos(p.Y, d),
638 getContainerPos(p.Z, d)
642 inline v2s16 getContainerPos(v2s16 p, v2s16 d)
645 getContainerPos(p.X, d.X),
646 getContainerPos(p.Y, d.Y)
650 inline v3s16 getContainerPos(v3s16 p, v3s16 d)
653 getContainerPos(p.X, d.X),
654 getContainerPos(p.Y, d.Y),
655 getContainerPos(p.Z, d.Z)
659 inline bool isInArea(v3s16 p, s16 d)
662 p.X >= 0 && p.X < d &&
663 p.Y >= 0 && p.Y < d &&
668 inline bool isInArea(v2s16 p, s16 d)
671 p.X >= 0 && p.X < d &&
676 inline bool isInArea(v3s16 p, v3s16 d)
679 p.X >= 0 && p.X < d.X &&
680 p.Y >= 0 && p.Y < d.Y &&
681 p.Z >= 0 && p.Z < d.Z
685 inline s16 rangelim(s16 i, s16 max)
694 #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
696 inline v3s16 arealim(v3s16 p, s16 d)
713 inline std::wstring narrow_to_wide(const std::string& mbs)
715 size_t wcl = mbs.size();
716 Buffer<wchar_t> wcs(wcl+1);
717 size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
718 if(l == (size_t)(-1))
719 return L"<invalid multibyte string>";
724 inline std::string wide_to_narrow(const std::wstring& wcs)
726 size_t mbl = wcs.size()*4;
727 SharedBuffer<char> mbs(mbl+1);
728 size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
729 if(l == (size_t)(-1))
737 See test.cpp for example cases.
738 wraps degrees to the range of -360...360
739 NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
741 inline float wrapDegrees(float f)
743 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
749 // NOTE: This would be used for wrapping to 0...360
755 // 10, 0.5, -0.5, -0.5
760 inline std::string lowercase(const std::string &s)
763 for(size_t i=0; i<s.size(); i++)
766 if(c >= 'A' && c <= 'Z')
773 inline bool is_yes(const std::string &s)
775 std::string s2 = lowercase(trim(s));
776 if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
781 inline s32 stoi(const std::string &s, s32 min, s32 max)
783 s32 i = atoi(s.c_str());
791 inline s32 stoi(std::string s)
793 return atoi(s.c_str());
796 inline float stof(std::string s)
799 std::istringstream ss(s);
804 inline std::string itos(s32 i)
806 std::ostringstream o;
811 inline std::string ftos(float f)
813 std::ostringstream o;
818 inline void str_replace(std::string & str, std::string const & pattern,
819 std::string const & replacement)
821 std::string::size_type start = str.find(pattern, 0);
822 while(start != str.npos)
824 str.replace(start, pattern.size(), replacement);
825 start = str.find(pattern, start+replacement.size());
829 inline void str_replace_char(std::string & str, char from, char to)
831 for(unsigned int i=0; i<str.size(); i++)
839 A base class for simple background thread implementation
842 class SimpleThread : public JThread
856 virtual ~SimpleThread()
859 virtual void * Thread() = 0;
863 JMutexAutoLock lock(run_mutex);
866 void setRun(bool a_run)
868 JMutexAutoLock lock(run_mutex);
887 VALUETYPE_FLAG // Doesn't take any arguments
892 ValueSpec(ValueType a_type, const char *a_help=NULL)
909 void writeLines(std::ostream &os)
911 JMutexAutoLock lock(m_mutex);
913 for(core::map<std::string, std::string>::Iterator
914 i = m_settings.getIterator();
915 i.atEnd() == false; i++)
917 std::string name = i.getNode()->getKey();
918 std::string value = i.getNode()->getValue();
919 os<<name<<" = "<<value<<"\n";
923 bool parseConfigLine(const std::string &line)
925 JMutexAutoLock lock(m_mutex);
927 std::string trimmedline = trim(line);
930 if(trimmedline[0] == '#')
933 //dstream<<"trimmedline=\""<<trimmedline<<"\""<<std::endl;
935 Strfnd sf(trim(line));
937 std::string name = sf.next("=");
943 std::string value = sf.next("\n");
946 /*dstream<<"Config name=\""<<name<<"\" value=\""
947 <<value<<"\""<<std::endl;*/
949 m_settings[name] = value;
954 // Returns false on EOF
955 bool parseConfigObject(std::istream &is)
961 NOTE: This function might be expanded to allow multi-line
965 std::getline(is, line);
966 //dstream<<"got line: \""<<line<<"\""<<std::endl;
968 return parseConfigLine(line);
972 Read configuration file
974 Returns true on success
976 bool readConfigFile(const char *filename)
978 std::ifstream is(filename);
979 if(is.good() == false)
981 dstream<<"Error opening configuration file \""
982 <<filename<<"\""<<std::endl;
986 dstream<<"Parsing configuration file: \""
987 <<filename<<"\""<<std::endl;
989 while(parseConfigObject(is));
995 Reads a configuration object from stream (usually a single line)
998 Preserves comments and empty lines.
1000 Settings that were added to dst are also added to updated.
1001 key of updated is setting name, value of updated is dummy.
1003 Returns false on EOF
1005 bool getUpdatedConfigObject(std::istream &is,
1006 core::list<std::string> &dst,
1007 core::map<std::string, bool> &updated)
1009 JMutexAutoLock lock(m_mutex);
1014 // NOTE: This function will be expanded to allow multi-line settings
1016 std::getline(is, line);
1018 std::string trimmedline = trim(line);
1020 std::string line_end = "";
1021 if(is.eof() == false)
1025 if(trimmedline[0] == '#')
1027 dst.push_back(line+line_end);
1031 Strfnd sf(trim(line));
1033 std::string name = sf.next("=");
1038 dst.push_back(line+line_end);
1042 std::string value = sf.next("\n");
1043 value = trim(value);
1045 if(m_settings.find(name))
1047 std::string newvalue = m_settings[name];
1049 if(newvalue != value)
1051 dstream<<"Changing value of \""<<name<<"\" = \""
1052 <<value<<"\" -> \""<<newvalue<<"\""
1056 dst.push_back(name + " = " + newvalue + line_end);
1058 updated[name] = true;
1065 Updates configuration file
1067 Returns true on success
1069 bool updateConfigFile(const char *filename)
1071 dstream<<"Updating configuration file: \""
1072 <<filename<<"\""<<std::endl;
1074 core::list<std::string> objects;
1075 core::map<std::string, bool> updated;
1077 // Read and modify stuff
1079 std::ifstream is(filename);
1080 if(is.good() == false)
1082 dstream<<"INFO: updateConfigFile():"
1083 " Error opening configuration file"
1085 <<filename<<"\""<<std::endl;
1089 while(getUpdatedConfigObject(is, objects, updated));
1093 JMutexAutoLock lock(m_mutex);
1097 std::ofstream os(filename);
1098 if(os.good() == false)
1100 dstream<<"Error opening configuration file"
1102 <<filename<<"\""<<std::endl;
1109 for(core::list<std::string>::Iterator
1110 i = objects.begin();
1111 i != objects.end(); i++)
1117 Write stuff that was not already in the file
1119 for(core::map<std::string, std::string>::Iterator
1120 i = m_settings.getIterator();
1121 i.atEnd() == false; i++)
1123 if(updated.find(i.getNode()->getKey()))
1125 std::string name = i.getNode()->getKey();
1126 std::string value = i.getNode()->getValue();
1127 dstream<<"Adding \""<<name<<"\" = \""<<value<<"\""
1129 os<<name<<" = "<<value<<"\n";
1137 NOTE: Types of allowed_options are ignored
1139 returns true on success
1141 bool parseCommandLine(int argc, char *argv[],
1142 core::map<std::string, ValueSpec> &allowed_options)
1149 std::string argname = argv[i];
1150 if(argname.substr(0, 2) != "--")
1152 dstream<<"Invalid command-line parameter \""
1153 <<argname<<"\": --<option> expected."<<std::endl;
1158 std::string name = argname.substr(2);
1160 core::map<std::string, ValueSpec>::Node *n;
1161 n = allowed_options.find(name);
1164 dstream<<"Unknown command-line parameter \""
1165 <<argname<<"\""<<std::endl;
1169 ValueType type = n->getValue().type;
1171 std::string value = "";
1173 if(type == VALUETYPE_FLAG)
1181 dstream<<"Invalid command-line parameter \""
1182 <<name<<"\": missing value"<<std::endl;
1190 dstream<<"Valid command-line parameter: \""
1191 <<name<<"\" = \""<<value<<"\""
1199 void set(std::string name, std::string value)
1201 JMutexAutoLock lock(m_mutex);
1203 m_settings[name] = value;
1206 void setDefault(std::string name, std::string value)
1208 JMutexAutoLock lock(m_mutex);
1210 m_defaults[name] = value;
1213 bool exists(std::string name)
1215 JMutexAutoLock lock(m_mutex);
1217 return (m_settings.find(name) || m_defaults.find(name));
1220 std::string get(std::string name)
1222 JMutexAutoLock lock(m_mutex);
1224 core::map<std::string, std::string>::Node *n;
1225 n = m_settings.find(name);
1228 n = m_defaults.find(name);
1231 dstream<<"INFO: Settings: Setting not found: \""
1232 <<name<<"\""<<std::endl;
1233 throw SettingNotFoundException("Setting not found");
1237 return n->getValue();
1240 bool getBool(std::string name)
1242 return is_yes(get(name));
1245 bool getFlag(std::string name)
1249 return getBool(name);
1251 catch(SettingNotFoundException &e)
1258 bool getBoolAsk(std::string name, std::string question, bool def)
1260 // If it is in settings
1262 return getBool(name);
1266 std::cout<<question<<" [y/N]: ";
1267 std::cin.getline(templine, 10);
1276 float getFloat(std::string name)
1278 return stof(get(name));
1281 u16 getU16(std::string name)
1283 return stoi(get(name), 0, 65535);
1286 u16 getU16Ask(std::string name, std::string question, u16 def)
1288 // If it is in settings
1290 return getU16(name);
1294 std::cout<<question<<" ["<<def<<"]: ";
1295 std::cin.getline(templine, 10);
1301 return stoi(s, 0, 65535);
1304 s16 getS16(std::string name)
1306 return stoi(get(name), -32768, 32767);
1309 s32 getS32(std::string name)
1311 return stoi(get(name));
1314 v3f getV3F(std::string name)
1317 Strfnd f(get(name));
1319 value.X = stof(f.next(","));
1320 value.Y = stof(f.next(","));
1321 value.Z = stof(f.next(")"));
1325 u64 getU64(std::string name)
1328 std::string s = get(name);
1329 std::istringstream ss(s);
1334 void setS32(std::string name, s32 value)
1336 set(name, itos(value));
1339 void setFloat(std::string name, float value)
1341 set(name, ftos(value));
1344 void setV3F(std::string name, v3f value)
1346 std::ostringstream os;
1347 os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
1348 set(name, os.str());
1351 void setU64(std::string name, u64 value)
1353 std::ostringstream os;
1355 set(name, os.str());
1360 JMutexAutoLock lock(m_mutex);
1366 Settings & operator+=(Settings &other)
1368 JMutexAutoLock lock(m_mutex);
1369 JMutexAutoLock lock2(other.m_mutex);
1374 for(core::map<std::string, std::string>::Iterator
1375 i = other.m_settings.getIterator();
1376 i.atEnd() == false; i++)
1378 m_settings.insert(i.getNode()->getKey(),
1379 i.getNode()->getValue());
1382 for(core::map<std::string, std::string>::Iterator
1383 i = other.m_defaults.getIterator();
1384 i.atEnd() == false; i++)
1386 m_defaults.insert(i.getNode()->getKey(),
1387 i.getNode()->getValue());
1392 Settings & operator=(Settings &other)
1394 JMutexAutoLock lock(m_mutex);
1395 JMutexAutoLock lock2(other.m_mutex);
1407 core::map<std::string, std::string> m_settings;
1408 core::map<std::string, std::string> m_defaults;
1409 // All methods that access m_settings/m_defaults directly should lock this.
1414 FIFO queue (well, actually a FILO also)
1416 template<typename T>
1422 m_list.push_back(t);
1427 if(m_list.size() == 0)
1428 throw ItemNotFoundException("Queue: queue is empty");
1430 typename core::list<T>::Iterator begin = m_list.begin();
1432 m_list.erase(begin);
1437 if(m_list.size() == 0)
1438 throw ItemNotFoundException("Queue: queue is empty");
1440 typename core::list<T>::Iterator last = m_list.getLast();
1448 return m_list.size();
1452 core::list<T> m_list;
1456 Thread-safe FIFO queue (well, actually a FILO also)
1459 template<typename T>
1469 JMutexAutoLock lock(m_mutex);
1470 return m_list.size();
1474 JMutexAutoLock lock(m_mutex);
1475 m_list.push_back(t);
1477 T pop_front(u32 wait_time_max_ms=0)
1479 u32 wait_time_ms = 0;
1484 JMutexAutoLock lock(m_mutex);
1486 if(m_list.size() > 0)
1488 typename core::list<T>::Iterator begin = m_list.begin();
1490 m_list.erase(begin);
1494 if(wait_time_ms >= wait_time_max_ms)
1495 throw ItemNotFoundException("MutexedQueue: queue is empty");
1498 // Wait a while before trying again
1503 T pop_back(u32 wait_time_max_ms=0)
1505 u32 wait_time_ms = 0;
1510 JMutexAutoLock lock(m_mutex);
1512 if(m_list.size() > 0)
1514 typename core::list<T>::Iterator last = m_list.getLast();
1520 if(wait_time_ms >= wait_time_max_ms)
1521 throw ItemNotFoundException("MutexedQueue: queue is empty");
1524 // Wait a while before trying again
1535 core::list<T> & getList()
1542 core::list<T> m_list;
1546 A single worker thread - multiple client threads queue framework.
1549 template<typename Caller, typename Data>
1557 template<typename Key, typename T, typename Caller, typename CallerData>
1563 core::list<CallerInfo<Caller, CallerData> > callers;
1566 template<typename Key, typename T, typename Caller, typename CallerData>
1567 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1571 template<typename Key, typename T, typename Caller, typename CallerData>
1579 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1583 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1594 ResultQueue<Key, T, Caller, CallerData> *dest;
1595 core::list<CallerInfo<Caller, CallerData> > callers;
1598 template<typename Key, typename T, typename Caller, typename CallerData>
1604 return m_queue.size();
1607 void add(Key key, Caller caller, CallerData callerdata,
1608 ResultQueue<Key, T, Caller, CallerData> *dest)
1610 JMutexAutoLock lock(m_queue.getMutex());
1613 If the caller is already on the list, only update CallerData
1615 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1616 i = m_queue.getList().begin();
1617 i != m_queue.getList().end(); i++)
1619 GetRequest<Key, T, Caller, CallerData> &request = *i;
1621 if(request.key == key)
1623 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1624 i = request.callers.begin();
1625 i != request.callers.end(); i++)
1627 CallerInfo<Caller, CallerData> &ca = *i;
1628 if(ca.caller == caller)
1630 ca.data = callerdata;
1634 CallerInfo<Caller, CallerData> ca;
1636 ca.data = callerdata;
1637 request.callers.push_back(ca);
1643 Else add a new request to the queue
1646 GetRequest<Key, T, Caller, CallerData> request;
1648 CallerInfo<Caller, CallerData> ca;
1650 ca.data = callerdata;
1651 request.callers.push_back(ca);
1652 request.dest = dest;
1654 m_queue.getList().push_back(request);
1657 GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1659 return m_queue.pop_front(wait_if_empty);
1663 MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1667 Pseudo-random (VC++ rand() sucks)
1670 void mysrand(unsigned seed);
1671 #define MYRAND_MAX 32767
1673 inline int myrand_range(int min, int max)
1680 return (myrand()%(max-min+1))+min;
1684 Miscellaneous functions
1687 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
1688 f32 *distance_ptr=NULL);
1691 Queue with unique values with fast checking of value existence
1694 template<typename Value>
1700 Does nothing if value is already queued.
1703 false: value already exists
1705 bool push_back(Value value)
1707 // Check if already exists
1708 if(m_map.find(value) != NULL)
1712 m_map.insert(value, 0);
1713 m_list.push_back(value);
1720 typename core::list<Value>::Iterator i = m_list.begin();
1722 m_map.remove(value);
1729 assert(m_list.size() == m_map.size());
1730 return m_list.size();
1734 core::map<Value, u8> m_map;
1735 core::list<Value> m_list;
1739 template<typename Key, typename Value>
1746 assert(m_mutex.IsInitialized());
1749 void set(const Key &name, const Value &value)
1751 JMutexAutoLock lock(m_mutex);
1753 m_values[name] = value;
1756 bool get(const Key &name, Value *result)
1758 JMutexAutoLock lock(m_mutex);
1760 typename core::map<Key, Value>::Node *n;
1761 n = m_values.find(name);
1766 *result = n->getValue();
1771 core::map<Key, Value> m_values;
1777 Generates ids for comparable values.
1778 Id=0 is reserved for "no value".
1781 - Returning value by id (very fast)
1782 - Returning id by value
1783 - Generating a new id for a value
1786 - Remove an id/value pair (is possible to implement but slow)
1788 template<typename T>
1789 class MutexedIdGenerator
1792 MutexedIdGenerator()
1795 assert(m_mutex.IsInitialized());
1798 // Returns true if found
1799 bool getValue(u32 id, T &value)
1803 JMutexAutoLock lock(m_mutex);
1804 if(m_id_to_value.size() < id)
1806 value = m_id_to_value[id-1];
1810 // If id exists for value, returns the id.
1811 // Otherwise generates an id for the value.
1812 u32 getId(const T &value)
1814 JMutexAutoLock lock(m_mutex);
1815 typename core::map<T, u32>::Node *n;
1816 n = m_value_to_id.find(value);
1818 return n->getValue();
1819 m_id_to_value.push_back(value);
1820 u32 new_id = m_id_to_value.size();
1821 m_value_to_id.insert(value, new_id);
1827 // Values are stored here at id-1 position (id 1 = [0])
1828 core::array<T> m_id_to_value;
1829 core::map<T, u32> m_value_to_id;
1833 Checks if a string contains only supplied characters
1835 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1837 for(u32 i=0; i<s.size(); i++)
1839 bool confirmed = false;
1840 for(u32 j=0; j<allowed_chars.size(); j++)
1842 if(s[i] == allowed_chars[j])
1848 if(confirmed == false)
1855 Forcefully wraps string into rows using \n
1856 (no word wrap, used for showing paths in gui)
1858 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1861 for(u32 i=0; i<from.size(); i++)
1863 if(i != 0 && i%rowlen == 0)
1873 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1874 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1877 Returns integer position of node in given floating point position
1879 inline v3s16 floatToInt(v3f p, f32 d)
1882 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1883 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1884 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1889 Returns floating point position of node in given integer position
1891 inline v3f intToFloat(v3s16 p, f32 d)
1902 More serialization stuff
1905 // Creates a string with the length as the first two bytes
1906 inline std::string serializeString(const std::string &plain)
1908 assert(plain.size() <= 65535);
1910 writeU16((u8*)&buf[0], plain.size());
1917 /*// Reads a string with the length as the first two bytes
1918 inline std::string deSerializeString(const std::string encoded)
1920 u16 s_size = readU16((u8*)&encoded.c_str()[0]);
1921 if(s_size > encoded.length() - 2)
1925 s.append(&encoded.c_str()[2], s_size);
1929 // Reads a string with the length as the first two bytes
1930 inline std::string deSerializeString(std::istream &is)
1934 if(is.gcount() != 2)
1935 throw SerializationError("deSerializeString: size not read");
1936 u16 s_size = readU16((u8*)buf);
1939 Buffer<char> buf2(s_size);
1940 is.read(&buf2[0], s_size);
1943 s.append(&buf2[0], s_size);
1947 // Creates a string with the length as the first four bytes
1948 inline std::string serializeLongString(const std::string &plain)
1951 writeU32((u8*)&buf[0], plain.size());
1958 /*// Reads a string with the length as the first four bytes
1959 inline std::string deSerializeLongString(const std::string encoded)
1961 u32 s_size = readU32((u8*)&encoded.c_str()[0]);
1962 if(s_size > encoded.length() - 4)
1966 s.append(&encoded.c_str()[4], s_size);
1970 // Reads a string with the length as the first four bytes
1971 inline std::string deSerializeLongString(std::istream &is)
1975 if(is.gcount() != 4)
1976 throw SerializationError("deSerializeLongString: size not read");
1977 u32 s_size = readU32((u8*)buf);
1980 Buffer<char> buf2(s_size);
1981 is.read(&buf2[0], s_size);
1984 s.append(&buf2[0], s_size);
1990 inline u32 time_to_daynight_ratio(u32 time_of_day)
1992 const s32 daylength = 16;
1993 const s32 nightlength = 6;
1994 const s32 daytimelength = 8;
1996 s32 t = (((time_of_day)%24000)/(24000/d));
1997 if(t < nightlength/2 || t >= d - nightlength/2)
1999 else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
2005 // Random helper. Usually d=BS
2006 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
2008 return core::aabbox3d<f32>(
2009 (float)p.X * d - 0.5*d,
2010 (float)p.Y * d - 0.5*d,
2011 (float)p.Z * d - 0.5*d,
2012 (float)p.X * d + 0.5*d,
2013 (float)p.Y * d + 0.5*d,
2014 (float)p.Z * d + 0.5*d
2018 class IntervalLimiter
2026 dtime: time from last call to this method
2027 wanted_interval: interval wanted
2029 true: action should be skipped
2030 false: action should be done
2032 bool step(float dtime, float wanted_interval)
2034 m_accumulator += dtime;
2035 if(m_accumulator < wanted_interval)
2037 m_accumulator -= wanted_interval;
2041 float m_accumulator;