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>
32 #include "common_irrlicht.h"
35 #include "exceptions.h"
38 extern const v3s16 g_6dirs[6];
40 extern const v3s16 g_26dirs[26];
43 extern const v3s16 g_27dirs[27];
45 inline void writeU64(u8 *data, u64 i)
47 data[0] = ((i>>56)&0xff);
48 data[1] = ((i>>48)&0xff);
49 data[2] = ((i>>40)&0xff);
50 data[3] = ((i>>32)&0xff);
51 data[4] = ((i>>24)&0xff);
52 data[5] = ((i>>16)&0xff);
53 data[6] = ((i>> 8)&0xff);
54 data[7] = ((i>> 0)&0xff);
57 inline void writeU32(u8 *data, u32 i)
59 data[0] = ((i>>24)&0xff);
60 data[1] = ((i>>16)&0xff);
61 data[2] = ((i>> 8)&0xff);
62 data[3] = ((i>> 0)&0xff);
65 inline void writeU16(u8 *data, u16 i)
67 data[0] = ((i>> 8)&0xff);
68 data[1] = ((i>> 0)&0xff);
71 inline void writeU8(u8 *data, u8 i)
73 data[0] = ((i>> 0)&0xff);
76 inline u64 readU64(u8 *data)
78 return ((u64)data[0]<<56) | ((u64)data[1]<<48)
79 | ((u64)data[2]<<40) | ((u64)data[3]<<32)
80 | ((u64)data[4]<<24) | ((u64)data[5]<<16)
81 | ((u64)data[6]<<8) | ((u64)data[7]<<0);
84 inline u32 readU32(u8 *data)
86 return (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | (data[3]<<0);
89 inline u16 readU16(u8 *data)
91 return (data[0]<<8) | (data[1]<<0);
94 inline u8 readU8(u8 *data)
99 inline void writeS32(u8 *data, s32 i){
100 writeU32(data, (u32)i);
102 inline s32 readS32(u8 *data){
103 return (s32)readU32(data);
106 inline void writeF1000(u8 *data, f32 i){
107 writeS32(data, i*1000);
109 inline f32 readF1000(u8 *data){
110 return (f32)readS32(data)/1000.;
113 inline void writeS16(u8 *data, s16 i){
114 writeU16(data, (u16)i);
116 inline s16 readS16(u8 *data){
117 return (s16)readU16(data);
120 inline void writeV3S32(u8 *data, v3s32 p)
122 writeS32(&data[0], p.X);
123 writeS32(&data[4], p.Y);
124 writeS32(&data[8], p.Z);
126 inline v3s32 readV3S32(u8 *data)
129 p.X = readS32(&data[0]);
130 p.Y = readS32(&data[4]);
131 p.Z = readS32(&data[8]);
135 inline void writeV3F1000(u8 *data, v3f p)
137 writeF1000(&data[0], p.X);
138 writeF1000(&data[4], p.Y);
139 writeF1000(&data[8], p.Z);
141 inline v3f readV3F1000(u8 *data)
144 p.X = (float)readF1000(&data[0]);
145 p.Y = (float)readF1000(&data[4]);
146 p.Z = (float)readF1000(&data[8]);
150 inline void writeV2S16(u8 *data, v2s16 p)
152 writeS16(&data[0], p.X);
153 writeS16(&data[2], p.Y);
156 inline v2s16 readV2S16(u8 *data)
159 p.X = readS16(&data[0]);
160 p.Y = readS16(&data[2]);
164 inline void writeV2S32(u8 *data, v2s32 p)
166 writeS32(&data[0], p.X);
167 writeS32(&data[2], p.Y);
170 inline v2s32 readV2S32(u8 *data)
173 p.X = readS32(&data[0]);
174 p.Y = readS32(&data[2]);
178 inline void writeV3S16(u8 *data, v3s16 p)
180 writeS16(&data[0], p.X);
181 writeS16(&data[2], p.Y);
182 writeS16(&data[4], p.Z);
185 inline v3s16 readV3S16(u8 *data)
188 p.X = readS16(&data[0]);
189 p.Y = readS16(&data[2]);
190 p.Z = readS16(&data[4]);
195 The above stuff directly interfaced to iostream
198 inline void writeU8(std::ostream &os, u8 p)
201 writeU8((u8*)buf, p);
204 inline u8 readU8(std::istream &is)
208 return readU8((u8*)buf);
211 inline void writeU16(std::ostream &os, u16 p)
214 writeU16((u8*)buf, p);
217 inline u16 readU16(std::istream &is)
221 return readU16((u8*)buf);
224 inline void writeU32(std::ostream &os, u16 p)
227 writeU16((u8*)buf, p);
230 inline u16 readU32(std::istream &is)
234 return readU32((u8*)buf);
237 inline void writeF1000(std::ostream &os, f32 p)
240 writeF1000((u8*)buf, p);
243 inline f32 readF1000(std::istream &is)
247 return readF1000((u8*)buf);
250 inline void writeV3F1000(std::ostream &os, v3f p)
253 writeV3F1000((u8*)buf, p);
256 inline v3f readV3F1000(std::istream &is)
260 return readV3F1000((u8*)buf);
264 None of these are used at the moment
267 template <typename T>
277 SharedPtr(SharedPtr<T> &t)
281 refcount = t.refcount;
289 SharedPtr<T> & operator=(T *t)
297 SharedPtr<T> & operator=(SharedPtr<T> &t)
300 refcount = t.refcount;
313 bool operator!=(T *t)
317 bool operator==(T *t)
321 T & operator[](unsigned int i)
328 assert((*refcount) > 0);
341 template <typename T>
345 Buffer(unsigned int size)
350 Buffer(const Buffer &buffer)
352 m_size = buffer.m_size;
353 data = new T[buffer.m_size];
354 memcpy(data, buffer.data, buffer.m_size);
356 Buffer(T *t, unsigned int size)
360 memcpy(data, t, size);
366 T & operator[](unsigned int i) const
370 T * operator*() const
374 unsigned int getSize() const
383 template <typename T>
391 refcount = new unsigned int;
394 SharedBuffer(unsigned int size)
398 data = new T[m_size];
401 refcount = new unsigned int;
404 SharedBuffer(const SharedBuffer &buffer)
406 //std::cout<<"SharedBuffer(const SharedBuffer &buffer)"<<std::endl;
407 m_size = buffer.m_size;
409 refcount = buffer.refcount;
412 SharedBuffer & operator=(const SharedBuffer & buffer)
414 //std::cout<<"SharedBuffer & operator=(const SharedBuffer & buffer)"<<std::endl;
418 m_size = buffer.m_size;
420 refcount = buffer.refcount;
427 SharedBuffer(T *t, unsigned int size)
432 data = new T[m_size];
433 memcpy(data, t, m_size);
437 refcount = new unsigned int;
443 SharedBuffer(const Buffer<T> &buffer)
445 m_size = buffer.getSize();
448 data = new T[m_size];
449 memcpy(data, *buffer, buffer.getSize());
453 refcount = new unsigned int;
460 T & operator[](unsigned int i) const
465 T * operator*() const
469 unsigned int getSize() const
476 assert((*refcount) > 0);
487 unsigned int *refcount;
490 inline SharedBuffer<u8> SharedBufferFromString(const char *string)
492 SharedBuffer<u8> b((u8*)string, strlen(string)+1);
497 class MutexedVariable
500 MutexedVariable(T value):
508 JMutexAutoLock lock(m_mutex);
514 JMutexAutoLock lock(m_mutex);
518 // You'll want to grab this in a SharedPtr
519 JMutexAutoLock * getLock()
521 return new JMutexAutoLock(m_mutex);
524 // You pretty surely want to grab the lock when accessing this
538 TimeTaker(const char *name, u32 *result=NULL);
545 u32 stop(bool quiet=false);
556 // Sets the color of all vertices in the mesh
557 void setMeshVerticesColor(scene::IMesh* mesh, video::SColor& color);
559 // Calculates the borders of a "d-radius" cube
560 inline void getFacePositions(core::list<v3s16> &list, u16 d)
564 list.push_back(v3s16(0,0,0));
570 This is an optimized sequence of coordinates.
572 list.push_back(v3s16( 0, 1, 0)); // top
573 list.push_back(v3s16( 0, 0, 1)); // back
574 list.push_back(v3s16(-1, 0, 0)); // left
575 list.push_back(v3s16( 1, 0, 0)); // right
576 list.push_back(v3s16( 0, 0,-1)); // front
577 list.push_back(v3s16( 0,-1, 0)); // bottom
579 list.push_back(v3s16(-1, 0, 1)); // back left
580 list.push_back(v3s16( 1, 0, 1)); // back right
581 list.push_back(v3s16(-1, 0,-1)); // front left
582 list.push_back(v3s16( 1, 0,-1)); // front right
583 list.push_back(v3s16(-1,-1, 0)); // bottom left
584 list.push_back(v3s16( 1,-1, 0)); // bottom right
585 list.push_back(v3s16( 0,-1, 1)); // bottom back
586 list.push_back(v3s16( 0,-1,-1)); // bottom front
587 list.push_back(v3s16(-1, 1, 0)); // top left
588 list.push_back(v3s16( 1, 1, 0)); // top right
589 list.push_back(v3s16( 0, 1, 1)); // top back
590 list.push_back(v3s16( 0, 1,-1)); // top front
592 list.push_back(v3s16(-1, 1, 1)); // top back-left
593 list.push_back(v3s16( 1, 1, 1)); // top back-right
594 list.push_back(v3s16(-1, 1,-1)); // top front-left
595 list.push_back(v3s16( 1, 1,-1)); // top front-right
596 list.push_back(v3s16(-1,-1, 1)); // bottom back-left
597 list.push_back(v3s16( 1,-1, 1)); // bottom back-right
598 list.push_back(v3s16(-1,-1,-1)); // bottom front-left
599 list.push_back(v3s16( 1,-1,-1)); // bottom front-right
604 // Take blocks in all sides, starting from y=0 and going +-y
605 for(s16 y=0; y<=d-1; y++)
607 // Left and right side, including borders
608 for(s16 z=-d; z<=d; z++)
610 list.push_back(v3s16(d,y,z));
611 list.push_back(v3s16(-d,y,z));
614 list.push_back(v3s16(d,-y,z));
615 list.push_back(v3s16(-d,-y,z));
618 // Back and front side, excluding borders
619 for(s16 x=-d+1; x<=d-1; x++)
621 list.push_back(v3s16(x,y,d));
622 list.push_back(v3s16(x,y,-d));
625 list.push_back(v3s16(x,-y,d));
626 list.push_back(v3s16(x,-y,-d));
631 // Take the bottom and top face with borders
632 // -d<x<d, y=+-d, -d<z<d
633 for(s16 x=-d; x<=d; x++)
634 for(s16 z=-d; z<=d; z++)
636 list.push_back(v3s16(x,-d,z));
637 list.push_back(v3s16(x,d,z));
641 class IndentationRaiser
644 IndentationRaiser(u16 *indentation)
646 m_indentation = indentation;
657 inline s16 getContainerPos(s16 p, s16 d)
659 return (p>=0 ? p : p-d+1) / d;
662 inline v2s16 getContainerPos(v2s16 p, s16 d)
665 getContainerPos(p.X, d),
666 getContainerPos(p.Y, d)
670 inline v3s16 getContainerPos(v3s16 p, s16 d)
673 getContainerPos(p.X, d),
674 getContainerPos(p.Y, d),
675 getContainerPos(p.Z, d)
679 inline v2s16 getContainerPos(v2s16 p, v2s16 d)
682 getContainerPos(p.X, d.X),
683 getContainerPos(p.Y, d.Y)
687 inline v3s16 getContainerPos(v3s16 p, v3s16 d)
690 getContainerPos(p.X, d.X),
691 getContainerPos(p.Y, d.Y),
692 getContainerPos(p.Z, d.Z)
696 inline bool isInArea(v3s16 p, s16 d)
699 p.X >= 0 && p.X < d &&
700 p.Y >= 0 && p.Y < d &&
705 inline bool isInArea(v2s16 p, s16 d)
708 p.X >= 0 && p.X < d &&
713 inline bool isInArea(v3s16 p, v3s16 d)
716 p.X >= 0 && p.X < d.X &&
717 p.Y >= 0 && p.Y < d.Y &&
718 p.Z >= 0 && p.Z < d.Z
722 inline s16 rangelim(s16 i, s16 max)
731 #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
733 inline v3s16 arealim(v3s16 p, s16 d)
750 inline std::wstring narrow_to_wide(const std::string& mbs)
752 size_t wcl = mbs.size();
753 Buffer<wchar_t> wcs(wcl+1);
754 size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
755 if(l == (size_t)(-1))
756 return L"<invalid multibyte string>";
761 inline std::string wide_to_narrow(const std::wstring& wcs)
763 size_t mbl = wcs.size()*4;
764 SharedBuffer<char> mbs(mbl+1);
765 size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
766 if(l == (size_t)(-1))
773 // Split a string using the given delimiter. Returns a vector containing
774 // the component parts.
775 inline std::vector<std::wstring> str_split(const std::wstring &str, wchar_t delimiter)
777 std::vector<std::wstring> parts;
778 std::wstringstream sstr(str);
780 while(std::getline(sstr, part, delimiter))
781 parts.push_back(part);
787 See test.cpp for example cases.
788 wraps degrees to the range of -360...360
789 NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
791 inline float wrapDegrees(float f)
793 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
799 // NOTE: This would be used for wrapping to 0...360
805 // 10, 0.5, -0.5, -0.5
810 inline std::string lowercase(const std::string &s)
813 for(size_t i=0; i<s.size(); i++)
816 if(c >= 'A' && c <= 'Z')
823 inline bool is_yes(const std::string &s)
825 std::string s2 = lowercase(trim(s));
826 if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
831 inline s32 stoi(const std::string &s, s32 min, s32 max)
833 s32 i = atoi(s.c_str());
842 // MSVC2010 includes it's own versions of these
843 #if !defined(_MSC_VER) || _MSC_VER < 1600
845 inline s32 stoi(std::string s)
847 return atoi(s.c_str());
850 inline s32 stoi(std::wstring s)
852 return atoi(wide_to_narrow(s).c_str());
855 inline float stof(std::string s)
858 std::istringstream ss(s);
865 inline std::string itos(s32 i)
867 std::ostringstream o;
872 inline std::string ftos(float f)
874 std::ostringstream o;
879 inline void str_replace(std::string & str, std::string const & pattern,
880 std::string const & replacement)
882 std::string::size_type start = str.find(pattern, 0);
883 while(start != str.npos)
885 str.replace(start, pattern.size(), replacement);
886 start = str.find(pattern, start+replacement.size());
890 inline void str_replace_char(std::string & str, char from, char to)
892 for(unsigned int i=0; i<str.size(); i++)
900 A base class for simple background thread implementation
903 class SimpleThread : public JThread
917 virtual ~SimpleThread()
920 virtual void * Thread() = 0;
924 JMutexAutoLock lock(run_mutex);
927 void setRun(bool a_run)
929 JMutexAutoLock lock(run_mutex);
948 VALUETYPE_FLAG // Doesn't take any arguments
953 ValueSpec(ValueType a_type, const char *a_help=NULL)
970 void writeLines(std::ostream &os)
972 JMutexAutoLock lock(m_mutex);
974 for(core::map<std::string, std::string>::Iterator
975 i = m_settings.getIterator();
976 i.atEnd() == false; i++)
978 std::string name = i.getNode()->getKey();
979 std::string value = i.getNode()->getValue();
980 os<<name<<" = "<<value<<"\n";
984 bool parseConfigLine(const std::string &line)
986 JMutexAutoLock lock(m_mutex);
988 std::string trimmedline = trim(line);
991 if(trimmedline[0] == '#')
994 //dstream<<"trimmedline=\""<<trimmedline<<"\""<<std::endl;
996 Strfnd sf(trim(line));
998 std::string name = sf.next("=");
1004 std::string value = sf.next("\n");
1005 value = trim(value);
1007 /*dstream<<"Config name=\""<<name<<"\" value=\""
1008 <<value<<"\""<<std::endl;*/
1010 m_settings[name] = value;
1015 // Returns false on EOF
1016 bool parseConfigObject(std::istream &is)
1022 NOTE: This function might be expanded to allow multi-line
1026 std::getline(is, line);
1027 //dstream<<"got line: \""<<line<<"\""<<std::endl;
1029 return parseConfigLine(line);
1033 Read configuration file
1035 Returns true on success
1037 bool readConfigFile(const char *filename)
1039 std::ifstream is(filename);
1040 if(is.good() == false)
1042 dstream<<"Error opening configuration file \""
1043 <<filename<<"\""<<std::endl;
1047 dstream<<"Parsing configuration file: \""
1048 <<filename<<"\""<<std::endl;
1050 while(parseConfigObject(is));
1056 Reads a configuration object from stream (usually a single line)
1059 Preserves comments and empty lines.
1061 Settings that were added to dst are also added to updated.
1062 key of updated is setting name, value of updated is dummy.
1064 Returns false on EOF
1066 bool getUpdatedConfigObject(std::istream &is,
1067 core::list<std::string> &dst,
1068 core::map<std::string, bool> &updated)
1070 JMutexAutoLock lock(m_mutex);
1075 // NOTE: This function will be expanded to allow multi-line settings
1077 std::getline(is, line);
1079 std::string trimmedline = trim(line);
1081 std::string line_end = "";
1082 if(is.eof() == false)
1086 if(trimmedline[0] == '#')
1088 dst.push_back(line+line_end);
1092 Strfnd sf(trim(line));
1094 std::string name = sf.next("=");
1099 dst.push_back(line+line_end);
1103 std::string value = sf.next("\n");
1104 value = trim(value);
1106 if(m_settings.find(name))
1108 std::string newvalue = m_settings[name];
1110 if(newvalue != value)
1112 dstream<<"Changing value of \""<<name<<"\" = \""
1113 <<value<<"\" -> \""<<newvalue<<"\""
1117 dst.push_back(name + " = " + newvalue + line_end);
1119 updated[name] = true;
1126 Updates configuration file
1128 Returns true on success
1130 bool updateConfigFile(const char *filename)
1132 dstream<<"Updating configuration file: \""
1133 <<filename<<"\""<<std::endl;
1135 core::list<std::string> objects;
1136 core::map<std::string, bool> updated;
1138 // Read and modify stuff
1140 std::ifstream is(filename);
1141 if(is.good() == false)
1143 dstream<<"INFO: updateConfigFile():"
1144 " Error opening configuration file"
1146 <<filename<<"\""<<std::endl;
1150 while(getUpdatedConfigObject(is, objects, updated));
1154 JMutexAutoLock lock(m_mutex);
1158 std::ofstream os(filename);
1159 if(os.good() == false)
1161 dstream<<"Error opening configuration file"
1163 <<filename<<"\""<<std::endl;
1170 for(core::list<std::string>::Iterator
1171 i = objects.begin();
1172 i != objects.end(); i++)
1178 Write stuff that was not already in the file
1180 for(core::map<std::string, std::string>::Iterator
1181 i = m_settings.getIterator();
1182 i.atEnd() == false; i++)
1184 if(updated.find(i.getNode()->getKey()))
1186 std::string name = i.getNode()->getKey();
1187 std::string value = i.getNode()->getValue();
1188 dstream<<"Adding \""<<name<<"\" = \""<<value<<"\""
1190 os<<name<<" = "<<value<<"\n";
1198 NOTE: Types of allowed_options are ignored
1200 returns true on success
1202 bool parseCommandLine(int argc, char *argv[],
1203 core::map<std::string, ValueSpec> &allowed_options)
1210 std::string argname = argv[i];
1211 if(argname.substr(0, 2) != "--")
1213 dstream<<"Invalid command-line parameter \""
1214 <<argname<<"\": --<option> expected."<<std::endl;
1219 std::string name = argname.substr(2);
1221 core::map<std::string, ValueSpec>::Node *n;
1222 n = allowed_options.find(name);
1225 dstream<<"Unknown command-line parameter \""
1226 <<argname<<"\""<<std::endl;
1230 ValueType type = n->getValue().type;
1232 std::string value = "";
1234 if(type == VALUETYPE_FLAG)
1242 dstream<<"Invalid command-line parameter \""
1243 <<name<<"\": missing value"<<std::endl;
1251 dstream<<"Valid command-line parameter: \""
1252 <<name<<"\" = \""<<value<<"\""
1260 void set(std::string name, std::string value)
1262 JMutexAutoLock lock(m_mutex);
1264 m_settings[name] = value;
1267 void set(std::string name, const char *value)
1269 JMutexAutoLock lock(m_mutex);
1271 m_settings[name] = value;
1275 void setDefault(std::string name, std::string value)
1277 JMutexAutoLock lock(m_mutex);
1279 m_defaults[name] = value;
1282 bool exists(std::string name)
1284 JMutexAutoLock lock(m_mutex);
1286 return (m_settings.find(name) || m_defaults.find(name));
1289 std::string get(std::string name)
1291 JMutexAutoLock lock(m_mutex);
1293 core::map<std::string, std::string>::Node *n;
1294 n = m_settings.find(name);
1297 n = m_defaults.find(name);
1300 dstream<<"INFO: Settings: Setting not found: \""
1301 <<name<<"\""<<std::endl;
1302 throw SettingNotFoundException("Setting not found");
1306 return n->getValue();
1309 bool getBool(std::string name)
1311 return is_yes(get(name));
1314 bool getFlag(std::string name)
1318 return getBool(name);
1320 catch(SettingNotFoundException &e)
1327 bool getBoolAsk(std::string name, std::string question, bool def)
1329 // If it is in settings
1331 return getBool(name);
1335 std::cout<<question<<" [y/N]: ";
1336 std::cin.getline(templine, 10);
1345 float getFloat(std::string name)
1347 return stof(get(name));
1350 u16 getU16(std::string name)
1352 return stoi(get(name), 0, 65535);
1355 u16 getU16Ask(std::string name, std::string question, u16 def)
1357 // If it is in settings
1359 return getU16(name);
1363 std::cout<<question<<" ["<<def<<"]: ";
1364 std::cin.getline(templine, 10);
1370 return stoi(s, 0, 65535);
1373 s16 getS16(std::string name)
1375 return stoi(get(name), -32768, 32767);
1378 s32 getS32(std::string name)
1380 return stoi(get(name));
1383 v3f getV3F(std::string name)
1386 Strfnd f(get(name));
1388 value.X = stof(f.next(","));
1389 value.Y = stof(f.next(","));
1390 value.Z = stof(f.next(")"));
1394 u64 getU64(std::string name)
1397 std::string s = get(name);
1398 std::istringstream ss(s);
1403 void setBool(std::string name, bool value)
1411 void setS32(std::string name, s32 value)
1413 set(name, itos(value));
1416 void setFloat(std::string name, float value)
1418 set(name, ftos(value));
1421 void setV3F(std::string name, v3f value)
1423 std::ostringstream os;
1424 os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
1425 set(name, os.str());
1428 void setU64(std::string name, u64 value)
1430 std::ostringstream os;
1432 set(name, os.str());
1437 JMutexAutoLock lock(m_mutex);
1443 Settings & operator+=(Settings &other)
1445 JMutexAutoLock lock(m_mutex);
1446 JMutexAutoLock lock2(other.m_mutex);
1451 for(core::map<std::string, std::string>::Iterator
1452 i = other.m_settings.getIterator();
1453 i.atEnd() == false; i++)
1455 m_settings.insert(i.getNode()->getKey(),
1456 i.getNode()->getValue());
1459 for(core::map<std::string, std::string>::Iterator
1460 i = other.m_defaults.getIterator();
1461 i.atEnd() == false; i++)
1463 m_defaults.insert(i.getNode()->getKey(),
1464 i.getNode()->getValue());
1471 Settings & operator=(Settings &other)
1473 JMutexAutoLock lock(m_mutex);
1474 JMutexAutoLock lock2(other.m_mutex);
1486 core::map<std::string, std::string> m_settings;
1487 core::map<std::string, std::string> m_defaults;
1488 // All methods that access m_settings/m_defaults directly should lock this.
1493 FIFO queue (well, actually a FILO also)
1495 template<typename T>
1501 m_list.push_back(t);
1506 if(m_list.size() == 0)
1507 throw ItemNotFoundException("Queue: queue is empty");
1509 typename core::list<T>::Iterator begin = m_list.begin();
1511 m_list.erase(begin);
1516 if(m_list.size() == 0)
1517 throw ItemNotFoundException("Queue: queue is empty");
1519 typename core::list<T>::Iterator last = m_list.getLast();
1527 return m_list.size();
1531 core::list<T> m_list;
1535 Thread-safe FIFO queue (well, actually a FILO also)
1538 template<typename T>
1548 JMutexAutoLock lock(m_mutex);
1549 return m_list.size();
1553 JMutexAutoLock lock(m_mutex);
1554 m_list.push_back(t);
1556 T pop_front(u32 wait_time_max_ms=0)
1558 u32 wait_time_ms = 0;
1563 JMutexAutoLock lock(m_mutex);
1565 if(m_list.size() > 0)
1567 typename core::list<T>::Iterator begin = m_list.begin();
1569 m_list.erase(begin);
1573 if(wait_time_ms >= wait_time_max_ms)
1574 throw ItemNotFoundException("MutexedQueue: queue is empty");
1577 // Wait a while before trying again
1582 T pop_back(u32 wait_time_max_ms=0)
1584 u32 wait_time_ms = 0;
1589 JMutexAutoLock lock(m_mutex);
1591 if(m_list.size() > 0)
1593 typename core::list<T>::Iterator last = m_list.getLast();
1599 if(wait_time_ms >= wait_time_max_ms)
1600 throw ItemNotFoundException("MutexedQueue: queue is empty");
1603 // Wait a while before trying again
1614 core::list<T> & getList()
1621 core::list<T> m_list;
1625 A single worker thread - multiple client threads queue framework.
1628 template<typename Caller, typename Data>
1636 template<typename Key, typename T, typename Caller, typename CallerData>
1642 core::list<CallerInfo<Caller, CallerData> > callers;
1645 template<typename Key, typename T, typename Caller, typename CallerData>
1646 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1650 template<typename Key, typename T, typename Caller, typename CallerData>
1658 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1662 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1673 ResultQueue<Key, T, Caller, CallerData> *dest;
1674 core::list<CallerInfo<Caller, CallerData> > callers;
1677 template<typename Key, typename T, typename Caller, typename CallerData>
1683 return m_queue.size();
1686 void add(Key key, Caller caller, CallerData callerdata,
1687 ResultQueue<Key, T, Caller, CallerData> *dest)
1689 JMutexAutoLock lock(m_queue.getMutex());
1692 If the caller is already on the list, only update CallerData
1694 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1695 i = m_queue.getList().begin();
1696 i != m_queue.getList().end(); i++)
1698 GetRequest<Key, T, Caller, CallerData> &request = *i;
1700 if(request.key == key)
1702 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1703 i = request.callers.begin();
1704 i != request.callers.end(); i++)
1706 CallerInfo<Caller, CallerData> &ca = *i;
1707 if(ca.caller == caller)
1709 ca.data = callerdata;
1713 CallerInfo<Caller, CallerData> ca;
1715 ca.data = callerdata;
1716 request.callers.push_back(ca);
1722 Else add a new request to the queue
1725 GetRequest<Key, T, Caller, CallerData> request;
1727 CallerInfo<Caller, CallerData> ca;
1729 ca.data = callerdata;
1730 request.callers.push_back(ca);
1731 request.dest = dest;
1733 m_queue.getList().push_back(request);
1736 GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1738 return m_queue.pop_front(wait_if_empty);
1742 MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1746 Pseudo-random (VC++ rand() sucks)
1749 void mysrand(unsigned seed);
1750 #define MYRAND_MAX 32767
1752 inline int myrand_range(int min, int max)
1754 if(max-min > MYRAND_MAX)
1756 dstream<<"WARNING: myrand_range: max-min > MYRAND_MAX"<<std::endl;
1764 return (myrand()%(max-min+1))+min;
1768 Miscellaneous functions
1771 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
1772 f32 camera_fov, f32 range, f32 *distance_ptr=NULL);
1775 Queue with unique values with fast checking of value existence
1778 template<typename Value>
1784 Does nothing if value is already queued.
1787 false: value already exists
1789 bool push_back(Value value)
1791 // Check if already exists
1792 if(m_map.find(value) != NULL)
1796 m_map.insert(value, 0);
1797 m_list.push_back(value);
1804 typename core::list<Value>::Iterator i = m_list.begin();
1806 m_map.remove(value);
1813 assert(m_list.size() == m_map.size());
1814 return m_list.size();
1818 core::map<Value, u8> m_map;
1819 core::list<Value> m_list;
1823 template<typename Key, typename Value>
1830 assert(m_mutex.IsInitialized());
1833 void set(const Key &name, const Value &value)
1835 JMutexAutoLock lock(m_mutex);
1837 m_values[name] = value;
1840 bool get(const Key &name, Value *result)
1842 JMutexAutoLock lock(m_mutex);
1844 typename core::map<Key, Value>::Node *n;
1845 n = m_values.find(name);
1851 *result = n->getValue();
1857 core::map<Key, Value> m_values;
1863 Generates ids for comparable values.
1864 Id=0 is reserved for "no value".
1867 - Returning value by id (very fast)
1868 - Returning id by value
1869 - Generating a new id for a value
1872 - Remove an id/value pair (is possible to implement but slow)
1874 template<typename T>
1875 class MutexedIdGenerator
1878 MutexedIdGenerator()
1881 assert(m_mutex.IsInitialized());
1884 // Returns true if found
1885 bool getValue(u32 id, T &value)
1889 JMutexAutoLock lock(m_mutex);
1890 if(m_id_to_value.size() < id)
1892 value = m_id_to_value[id-1];
1896 // If id exists for value, returns the id.
1897 // Otherwise generates an id for the value.
1898 u32 getId(const T &value)
1900 JMutexAutoLock lock(m_mutex);
1901 typename core::map<T, u32>::Node *n;
1902 n = m_value_to_id.find(value);
1904 return n->getValue();
1905 m_id_to_value.push_back(value);
1906 u32 new_id = m_id_to_value.size();
1907 m_value_to_id.insert(value, new_id);
1913 // Values are stored here at id-1 position (id 1 = [0])
1914 core::array<T> m_id_to_value;
1915 core::map<T, u32> m_value_to_id;
1919 Checks if a string contains only supplied characters
1921 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1923 for(u32 i=0; i<s.size(); i++)
1925 bool confirmed = false;
1926 for(u32 j=0; j<allowed_chars.size(); j++)
1928 if(s[i] == allowed_chars[j])
1934 if(confirmed == false)
1941 Forcefully wraps string into rows using \n
1942 (no word wrap, used for showing paths in gui)
1944 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1947 for(u32 i=0; i<from.size(); i++)
1949 if(i != 0 && i%rowlen == 0)
1959 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1960 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1963 Returns integer position of node in given floating point position
1965 inline v3s16 floatToInt(v3f p, f32 d)
1968 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1969 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1970 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1975 Returns floating point position of node in given integer position
1977 inline v3f intToFloat(v3s16 p, f32 d)
1988 More serialization stuff
1991 // Creates a string with the length as the first two bytes
1992 inline std::string serializeString(const std::string &plain)
1994 //assert(plain.size() <= 65535);
1995 if(plain.size() > 65535)
1996 throw SerializationError("String too long for serializeString");
1998 writeU16((u8*)&buf[0], plain.size());
2005 // Creates a string with the length as the first two bytes from wide string
2006 inline std::string serializeWideString(const std::wstring &plain)
2008 //assert(plain.size() <= 65535);
2009 if(plain.size() > 65535)
2010 throw SerializationError("String too long for serializeString");
2012 writeU16((u8*)buf, plain.size());
2015 for(u32 i=0; i<plain.size(); i++)
2017 writeU16((u8*)buf, plain[i]);
2023 // Reads a string with the length as the first two bytes
2024 inline std::string deSerializeString(std::istream &is)
2028 if(is.gcount() != 2)
2029 throw SerializationError("deSerializeString: size not read");
2030 u16 s_size = readU16((u8*)buf);
2033 Buffer<char> buf2(s_size);
2034 is.read(&buf2[0], s_size);
2037 s.append(&buf2[0], s_size);
2041 // Reads a wide string with the length as the first two bytes
2042 inline std::wstring deSerializeWideString(std::istream &is)
2046 if(is.gcount() != 2)
2047 throw SerializationError("deSerializeString: size not read");
2048 u16 s_size = readU16((u8*)buf);
2053 for(u32 i=0; i<s_size; i++)
2055 is.read(&buf[0], 2);
2056 wchar_t c16 = readU16((u8*)buf);
2062 // Creates a string with the length as the first four bytes
2063 inline std::string serializeLongString(const std::string &plain)
2066 writeU32((u8*)&buf[0], plain.size());
2073 // Reads a string with the length as the first four bytes
2074 inline std::string deSerializeLongString(std::istream &is)
2078 if(is.gcount() != 4)
2079 throw SerializationError("deSerializeLongString: size not read");
2080 u32 s_size = readU32((u8*)buf);
2083 Buffer<char> buf2(s_size);
2084 is.read(&buf2[0], s_size);
2087 s.append(&buf2[0], s_size);
2093 inline u32 time_to_daynight_ratio(u32 time_of_day)
2095 const s32 daylength = 16;
2096 const s32 nightlength = 6;
2097 const s32 daytimelength = 8;
2099 s32 t = (((time_of_day)%24000)/(24000/d));
2100 if(t < nightlength/2 || t >= d - nightlength/2)
2103 else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
2109 // Random helper. Usually d=BS
2110 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
2112 return core::aabbox3d<f32>(
2113 (float)p.X * d - 0.5*d,
2114 (float)p.Y * d - 0.5*d,
2115 (float)p.Z * d - 0.5*d,
2116 (float)p.X * d + 0.5*d,
2117 (float)p.Y * d + 0.5*d,
2118 (float)p.Z * d + 0.5*d
2122 class IntervalLimiter
2130 dtime: time from last call to this method
2131 wanted_interval: interval wanted
2133 true: action should be skipped
2134 false: action should be done
2136 bool step(float dtime, float wanted_interval)
2138 m_accumulator += dtime;
2139 if(m_accumulator < wanted_interval)
2141 m_accumulator -= wanted_interval;
2145 float m_accumulator;
2148 std::string translatePassword(std::string playername, std::wstring password);