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 // Calculates the borders of a "d-radius" cube
557 inline void getFacePositions(core::list<v3s16> &list, u16 d)
561 list.push_back(v3s16(0,0,0));
567 This is an optimized sequence of coordinates.
569 list.push_back(v3s16( 0, 1, 0)); // top
570 list.push_back(v3s16( 0, 0, 1)); // back
571 list.push_back(v3s16(-1, 0, 0)); // left
572 list.push_back(v3s16( 1, 0, 0)); // right
573 list.push_back(v3s16( 0, 0,-1)); // front
574 list.push_back(v3s16( 0,-1, 0)); // bottom
576 list.push_back(v3s16(-1, 0, 1)); // back left
577 list.push_back(v3s16( 1, 0, 1)); // back right
578 list.push_back(v3s16(-1, 0,-1)); // front left
579 list.push_back(v3s16( 1, 0,-1)); // front right
580 list.push_back(v3s16(-1,-1, 0)); // bottom left
581 list.push_back(v3s16( 1,-1, 0)); // bottom right
582 list.push_back(v3s16( 0,-1, 1)); // bottom back
583 list.push_back(v3s16( 0,-1,-1)); // bottom front
584 list.push_back(v3s16(-1, 1, 0)); // top left
585 list.push_back(v3s16( 1, 1, 0)); // top right
586 list.push_back(v3s16( 0, 1, 1)); // top back
587 list.push_back(v3s16( 0, 1,-1)); // top front
589 list.push_back(v3s16(-1, 1, 1)); // top back-left
590 list.push_back(v3s16( 1, 1, 1)); // top back-right
591 list.push_back(v3s16(-1, 1,-1)); // top front-left
592 list.push_back(v3s16( 1, 1,-1)); // top front-right
593 list.push_back(v3s16(-1,-1, 1)); // bottom back-left
594 list.push_back(v3s16( 1,-1, 1)); // bottom back-right
595 list.push_back(v3s16(-1,-1,-1)); // bottom front-left
596 list.push_back(v3s16( 1,-1,-1)); // bottom front-right
601 // Take blocks in all sides, starting from y=0 and going +-y
602 for(s16 y=0; y<=d-1; y++)
604 // Left and right side, including borders
605 for(s16 z=-d; z<=d; z++)
607 list.push_back(v3s16(d,y,z));
608 list.push_back(v3s16(-d,y,z));
611 list.push_back(v3s16(d,-y,z));
612 list.push_back(v3s16(-d,-y,z));
615 // Back and front side, excluding borders
616 for(s16 x=-d+1; x<=d-1; x++)
618 list.push_back(v3s16(x,y,d));
619 list.push_back(v3s16(x,y,-d));
622 list.push_back(v3s16(x,-y,d));
623 list.push_back(v3s16(x,-y,-d));
628 // Take the bottom and top face with borders
629 // -d<x<d, y=+-d, -d<z<d
630 for(s16 x=-d; x<=d; x++)
631 for(s16 z=-d; z<=d; z++)
633 list.push_back(v3s16(x,-d,z));
634 list.push_back(v3s16(x,d,z));
638 class IndentationRaiser
641 IndentationRaiser(u16 *indentation)
643 m_indentation = indentation;
654 inline s16 getContainerPos(s16 p, s16 d)
656 return (p>=0 ? p : p-d+1) / d;
659 inline v2s16 getContainerPos(v2s16 p, s16 d)
662 getContainerPos(p.X, d),
663 getContainerPos(p.Y, d)
667 inline v3s16 getContainerPos(v3s16 p, s16 d)
670 getContainerPos(p.X, d),
671 getContainerPos(p.Y, d),
672 getContainerPos(p.Z, d)
676 inline v2s16 getContainerPos(v2s16 p, v2s16 d)
679 getContainerPos(p.X, d.X),
680 getContainerPos(p.Y, d.Y)
684 inline v3s16 getContainerPos(v3s16 p, v3s16 d)
687 getContainerPos(p.X, d.X),
688 getContainerPos(p.Y, d.Y),
689 getContainerPos(p.Z, d.Z)
693 inline bool isInArea(v3s16 p, s16 d)
696 p.X >= 0 && p.X < d &&
697 p.Y >= 0 && p.Y < d &&
702 inline bool isInArea(v2s16 p, s16 d)
705 p.X >= 0 && p.X < d &&
710 inline bool isInArea(v3s16 p, v3s16 d)
713 p.X >= 0 && p.X < d.X &&
714 p.Y >= 0 && p.Y < d.Y &&
715 p.Z >= 0 && p.Z < d.Z
719 inline s16 rangelim(s16 i, s16 max)
728 #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
730 inline v3s16 arealim(v3s16 p, s16 d)
747 inline std::wstring narrow_to_wide(const std::string& mbs)
749 size_t wcl = mbs.size();
750 Buffer<wchar_t> wcs(wcl+1);
751 size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
752 if(l == (size_t)(-1))
753 return L"<invalid multibyte string>";
758 inline std::string wide_to_narrow(const std::wstring& wcs)
760 size_t mbl = wcs.size()*4;
761 SharedBuffer<char> mbs(mbl+1);
762 size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
763 if(l == (size_t)(-1))
770 // Split a string using the given delimiter. Returns a vector containing
771 // the component parts.
772 inline std::vector<std::wstring> str_split(const std::wstring &str, wchar_t delimiter)
774 std::vector<std::wstring> parts;
775 std::wstringstream sstr(str);
777 while(std::getline(sstr, part, delimiter))
778 parts.push_back(part);
784 See test.cpp for example cases.
785 wraps degrees to the range of -360...360
786 NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
788 inline float wrapDegrees(float f)
790 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
796 // NOTE: This would be used for wrapping to 0...360
802 // 10, 0.5, -0.5, -0.5
807 inline std::string lowercase(const std::string &s)
810 for(size_t i=0; i<s.size(); i++)
813 if(c >= 'A' && c <= 'Z')
820 inline bool is_yes(const std::string &s)
822 std::string s2 = lowercase(trim(s));
823 if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
828 inline s32 stoi(const std::string &s, s32 min, s32 max)
830 s32 i = atoi(s.c_str());
839 // MSVC2010 includes it's own versions of these
840 #if !defined(_MSC_VER) || _MSC_VER < 1600
842 inline s32 stoi(std::string s)
844 return atoi(s.c_str());
847 inline s32 stoi(std::wstring s)
849 return atoi(wide_to_narrow(s).c_str());
852 inline float stof(std::string s)
855 std::istringstream ss(s);
862 inline std::string itos(s32 i)
864 std::ostringstream o;
869 inline std::string ftos(float f)
871 std::ostringstream o;
876 inline void str_replace(std::string & str, std::string const & pattern,
877 std::string const & replacement)
879 std::string::size_type start = str.find(pattern, 0);
880 while(start != str.npos)
882 str.replace(start, pattern.size(), replacement);
883 start = str.find(pattern, start+replacement.size());
887 inline void str_replace_char(std::string & str, char from, char to)
889 for(unsigned int i=0; i<str.size(); i++)
897 A base class for simple background thread implementation
900 class SimpleThread : public JThread
914 virtual ~SimpleThread()
917 virtual void * Thread() = 0;
921 JMutexAutoLock lock(run_mutex);
924 void setRun(bool a_run)
926 JMutexAutoLock lock(run_mutex);
945 VALUETYPE_FLAG // Doesn't take any arguments
950 ValueSpec(ValueType a_type, const char *a_help=NULL)
967 void writeLines(std::ostream &os)
969 JMutexAutoLock lock(m_mutex);
971 for(core::map<std::string, std::string>::Iterator
972 i = m_settings.getIterator();
973 i.atEnd() == false; i++)
975 std::string name = i.getNode()->getKey();
976 std::string value = i.getNode()->getValue();
977 os<<name<<" = "<<value<<"\n";
981 bool parseConfigLine(const std::string &line)
983 JMutexAutoLock lock(m_mutex);
985 std::string trimmedline = trim(line);
988 if(trimmedline[0] == '#')
991 //dstream<<"trimmedline=\""<<trimmedline<<"\""<<std::endl;
993 Strfnd sf(trim(line));
995 std::string name = sf.next("=");
1001 std::string value = sf.next("\n");
1002 value = trim(value);
1004 /*dstream<<"Config name=\""<<name<<"\" value=\""
1005 <<value<<"\""<<std::endl;*/
1007 m_settings[name] = value;
1012 // Returns false on EOF
1013 bool parseConfigObject(std::istream &is)
1019 NOTE: This function might be expanded to allow multi-line
1023 std::getline(is, line);
1024 //dstream<<"got line: \""<<line<<"\""<<std::endl;
1026 return parseConfigLine(line);
1030 Read configuration file
1032 Returns true on success
1034 bool readConfigFile(const char *filename)
1036 std::ifstream is(filename);
1037 if(is.good() == false)
1039 dstream<<"Error opening configuration file \""
1040 <<filename<<"\""<<std::endl;
1044 dstream<<"Parsing configuration file: \""
1045 <<filename<<"\""<<std::endl;
1047 while(parseConfigObject(is));
1053 Reads a configuration object from stream (usually a single line)
1056 Preserves comments and empty lines.
1058 Settings that were added to dst are also added to updated.
1059 key of updated is setting name, value of updated is dummy.
1061 Returns false on EOF
1063 bool getUpdatedConfigObject(std::istream &is,
1064 core::list<std::string> &dst,
1065 core::map<std::string, bool> &updated)
1067 JMutexAutoLock lock(m_mutex);
1072 // NOTE: This function will be expanded to allow multi-line settings
1074 std::getline(is, line);
1076 std::string trimmedline = trim(line);
1078 std::string line_end = "";
1079 if(is.eof() == false)
1083 if(trimmedline[0] == '#')
1085 dst.push_back(line+line_end);
1089 Strfnd sf(trim(line));
1091 std::string name = sf.next("=");
1096 dst.push_back(line+line_end);
1100 std::string value = sf.next("\n");
1101 value = trim(value);
1103 if(m_settings.find(name))
1105 std::string newvalue = m_settings[name];
1107 if(newvalue != value)
1109 dstream<<"Changing value of \""<<name<<"\" = \""
1110 <<value<<"\" -> \""<<newvalue<<"\""
1114 dst.push_back(name + " = " + newvalue + line_end);
1116 updated[name] = true;
1123 Updates configuration file
1125 Returns true on success
1127 bool updateConfigFile(const char *filename)
1129 dstream<<"Updating configuration file: \""
1130 <<filename<<"\""<<std::endl;
1132 core::list<std::string> objects;
1133 core::map<std::string, bool> updated;
1135 // Read and modify stuff
1137 std::ifstream is(filename);
1138 if(is.good() == false)
1140 dstream<<"INFO: updateConfigFile():"
1141 " Error opening configuration file"
1143 <<filename<<"\""<<std::endl;
1147 while(getUpdatedConfigObject(is, objects, updated));
1151 JMutexAutoLock lock(m_mutex);
1155 std::ofstream os(filename);
1156 if(os.good() == false)
1158 dstream<<"Error opening configuration file"
1160 <<filename<<"\""<<std::endl;
1167 for(core::list<std::string>::Iterator
1168 i = objects.begin();
1169 i != objects.end(); i++)
1175 Write stuff that was not already in the file
1177 for(core::map<std::string, std::string>::Iterator
1178 i = m_settings.getIterator();
1179 i.atEnd() == false; i++)
1181 if(updated.find(i.getNode()->getKey()))
1183 std::string name = i.getNode()->getKey();
1184 std::string value = i.getNode()->getValue();
1185 dstream<<"Adding \""<<name<<"\" = \""<<value<<"\""
1187 os<<name<<" = "<<value<<"\n";
1195 NOTE: Types of allowed_options are ignored
1197 returns true on success
1199 bool parseCommandLine(int argc, char *argv[],
1200 core::map<std::string, ValueSpec> &allowed_options)
1207 std::string argname = argv[i];
1208 if(argname.substr(0, 2) != "--")
1210 dstream<<"Invalid command-line parameter \""
1211 <<argname<<"\": --<option> expected."<<std::endl;
1216 std::string name = argname.substr(2);
1218 core::map<std::string, ValueSpec>::Node *n;
1219 n = allowed_options.find(name);
1222 dstream<<"Unknown command-line parameter \""
1223 <<argname<<"\""<<std::endl;
1227 ValueType type = n->getValue().type;
1229 std::string value = "";
1231 if(type == VALUETYPE_FLAG)
1239 dstream<<"Invalid command-line parameter \""
1240 <<name<<"\": missing value"<<std::endl;
1248 dstream<<"Valid command-line parameter: \""
1249 <<name<<"\" = \""<<value<<"\""
1257 void set(std::string name, std::string value)
1259 JMutexAutoLock lock(m_mutex);
1261 m_settings[name] = value;
1264 void set(std::string name, const char *value)
1266 JMutexAutoLock lock(m_mutex);
1268 m_settings[name] = value;
1272 void setDefault(std::string name, std::string value)
1274 JMutexAutoLock lock(m_mutex);
1276 m_defaults[name] = value;
1279 bool exists(std::string name)
1281 JMutexAutoLock lock(m_mutex);
1283 return (m_settings.find(name) || m_defaults.find(name));
1286 std::string get(std::string name)
1288 JMutexAutoLock lock(m_mutex);
1290 core::map<std::string, std::string>::Node *n;
1291 n = m_settings.find(name);
1294 n = m_defaults.find(name);
1297 dstream<<"INFO: Settings: Setting not found: \""
1298 <<name<<"\""<<std::endl;
1299 throw SettingNotFoundException("Setting not found");
1303 return n->getValue();
1306 bool getBool(std::string name)
1308 return is_yes(get(name));
1311 bool getFlag(std::string name)
1315 return getBool(name);
1317 catch(SettingNotFoundException &e)
1324 bool getBoolAsk(std::string name, std::string question, bool def)
1326 // If it is in settings
1328 return getBool(name);
1332 std::cout<<question<<" [y/N]: ";
1333 std::cin.getline(templine, 10);
1342 float getFloat(std::string name)
1344 return stof(get(name));
1347 u16 getU16(std::string name)
1349 return stoi(get(name), 0, 65535);
1352 u16 getU16Ask(std::string name, std::string question, u16 def)
1354 // If it is in settings
1356 return getU16(name);
1360 std::cout<<question<<" ["<<def<<"]: ";
1361 std::cin.getline(templine, 10);
1367 return stoi(s, 0, 65535);
1370 s16 getS16(std::string name)
1372 return stoi(get(name), -32768, 32767);
1375 s32 getS32(std::string name)
1377 return stoi(get(name));
1380 v3f getV3F(std::string name)
1383 Strfnd f(get(name));
1385 value.X = stof(f.next(","));
1386 value.Y = stof(f.next(","));
1387 value.Z = stof(f.next(")"));
1391 u64 getU64(std::string name)
1394 std::string s = get(name);
1395 std::istringstream ss(s);
1400 void setBool(std::string name, bool value)
1408 void setS32(std::string name, s32 value)
1410 set(name, itos(value));
1413 void setFloat(std::string name, float value)
1415 set(name, ftos(value));
1418 void setV3F(std::string name, v3f value)
1420 std::ostringstream os;
1421 os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
1422 set(name, os.str());
1425 void setU64(std::string name, u64 value)
1427 std::ostringstream os;
1429 set(name, os.str());
1434 JMutexAutoLock lock(m_mutex);
1440 Settings & operator+=(Settings &other)
1442 JMutexAutoLock lock(m_mutex);
1443 JMutexAutoLock lock2(other.m_mutex);
1448 for(core::map<std::string, std::string>::Iterator
1449 i = other.m_settings.getIterator();
1450 i.atEnd() == false; i++)
1452 m_settings.insert(i.getNode()->getKey(),
1453 i.getNode()->getValue());
1456 for(core::map<std::string, std::string>::Iterator
1457 i = other.m_defaults.getIterator();
1458 i.atEnd() == false; i++)
1460 m_defaults.insert(i.getNode()->getKey(),
1461 i.getNode()->getValue());
1468 Settings & operator=(Settings &other)
1470 JMutexAutoLock lock(m_mutex);
1471 JMutexAutoLock lock2(other.m_mutex);
1483 core::map<std::string, std::string> m_settings;
1484 core::map<std::string, std::string> m_defaults;
1485 // All methods that access m_settings/m_defaults directly should lock this.
1490 FIFO queue (well, actually a FILO also)
1492 template<typename T>
1498 m_list.push_back(t);
1503 if(m_list.size() == 0)
1504 throw ItemNotFoundException("Queue: queue is empty");
1506 typename core::list<T>::Iterator begin = m_list.begin();
1508 m_list.erase(begin);
1513 if(m_list.size() == 0)
1514 throw ItemNotFoundException("Queue: queue is empty");
1516 typename core::list<T>::Iterator last = m_list.getLast();
1524 return m_list.size();
1528 core::list<T> m_list;
1532 Thread-safe FIFO queue (well, actually a FILO also)
1535 template<typename T>
1545 JMutexAutoLock lock(m_mutex);
1546 return m_list.size();
1550 JMutexAutoLock lock(m_mutex);
1551 m_list.push_back(t);
1553 T pop_front(u32 wait_time_max_ms=0)
1555 u32 wait_time_ms = 0;
1560 JMutexAutoLock lock(m_mutex);
1562 if(m_list.size() > 0)
1564 typename core::list<T>::Iterator begin = m_list.begin();
1566 m_list.erase(begin);
1570 if(wait_time_ms >= wait_time_max_ms)
1571 throw ItemNotFoundException("MutexedQueue: queue is empty");
1574 // Wait a while before trying again
1579 T pop_back(u32 wait_time_max_ms=0)
1581 u32 wait_time_ms = 0;
1586 JMutexAutoLock lock(m_mutex);
1588 if(m_list.size() > 0)
1590 typename core::list<T>::Iterator last = m_list.getLast();
1596 if(wait_time_ms >= wait_time_max_ms)
1597 throw ItemNotFoundException("MutexedQueue: queue is empty");
1600 // Wait a while before trying again
1611 core::list<T> & getList()
1618 core::list<T> m_list;
1622 A single worker thread - multiple client threads queue framework.
1625 template<typename Caller, typename Data>
1633 template<typename Key, typename T, typename Caller, typename CallerData>
1639 core::list<CallerInfo<Caller, CallerData> > callers;
1642 template<typename Key, typename T, typename Caller, typename CallerData>
1643 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1647 template<typename Key, typename T, typename Caller, typename CallerData>
1655 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1659 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1670 ResultQueue<Key, T, Caller, CallerData> *dest;
1671 core::list<CallerInfo<Caller, CallerData> > callers;
1674 template<typename Key, typename T, typename Caller, typename CallerData>
1680 return m_queue.size();
1683 void add(Key key, Caller caller, CallerData callerdata,
1684 ResultQueue<Key, T, Caller, CallerData> *dest)
1686 JMutexAutoLock lock(m_queue.getMutex());
1689 If the caller is already on the list, only update CallerData
1691 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1692 i = m_queue.getList().begin();
1693 i != m_queue.getList().end(); i++)
1695 GetRequest<Key, T, Caller, CallerData> &request = *i;
1697 if(request.key == key)
1699 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1700 i = request.callers.begin();
1701 i != request.callers.end(); i++)
1703 CallerInfo<Caller, CallerData> &ca = *i;
1704 if(ca.caller == caller)
1706 ca.data = callerdata;
1710 CallerInfo<Caller, CallerData> ca;
1712 ca.data = callerdata;
1713 request.callers.push_back(ca);
1719 Else add a new request to the queue
1722 GetRequest<Key, T, Caller, CallerData> request;
1724 CallerInfo<Caller, CallerData> ca;
1726 ca.data = callerdata;
1727 request.callers.push_back(ca);
1728 request.dest = dest;
1730 m_queue.getList().push_back(request);
1733 GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1735 return m_queue.pop_front(wait_if_empty);
1739 MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1743 Pseudo-random (VC++ rand() sucks)
1746 void mysrand(unsigned seed);
1747 #define MYRAND_MAX 32767
1749 inline int myrand_range(int min, int max)
1751 if(max-min > MYRAND_MAX)
1753 dstream<<"WARNING: myrand_range: max-min > MYRAND_MAX"<<std::endl;
1761 return (myrand()%(max-min+1))+min;
1765 Miscellaneous functions
1768 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
1769 f32 *distance_ptr=NULL);
1772 Queue with unique values with fast checking of value existence
1775 template<typename Value>
1781 Does nothing if value is already queued.
1784 false: value already exists
1786 bool push_back(Value value)
1788 // Check if already exists
1789 if(m_map.find(value) != NULL)
1793 m_map.insert(value, 0);
1794 m_list.push_back(value);
1801 typename core::list<Value>::Iterator i = m_list.begin();
1803 m_map.remove(value);
1810 assert(m_list.size() == m_map.size());
1811 return m_list.size();
1815 core::map<Value, u8> m_map;
1816 core::list<Value> m_list;
1820 template<typename Key, typename Value>
1827 assert(m_mutex.IsInitialized());
1830 void set(const Key &name, const Value &value)
1832 JMutexAutoLock lock(m_mutex);
1834 m_values[name] = value;
1837 bool get(const Key &name, Value *result)
1839 JMutexAutoLock lock(m_mutex);
1841 typename core::map<Key, Value>::Node *n;
1842 n = m_values.find(name);
1848 *result = n->getValue();
1854 core::map<Key, Value> m_values;
1860 Generates ids for comparable values.
1861 Id=0 is reserved for "no value".
1864 - Returning value by id (very fast)
1865 - Returning id by value
1866 - Generating a new id for a value
1869 - Remove an id/value pair (is possible to implement but slow)
1871 template<typename T>
1872 class MutexedIdGenerator
1875 MutexedIdGenerator()
1878 assert(m_mutex.IsInitialized());
1881 // Returns true if found
1882 bool getValue(u32 id, T &value)
1886 JMutexAutoLock lock(m_mutex);
1887 if(m_id_to_value.size() < id)
1889 value = m_id_to_value[id-1];
1893 // If id exists for value, returns the id.
1894 // Otherwise generates an id for the value.
1895 u32 getId(const T &value)
1897 JMutexAutoLock lock(m_mutex);
1898 typename core::map<T, u32>::Node *n;
1899 n = m_value_to_id.find(value);
1901 return n->getValue();
1902 m_id_to_value.push_back(value);
1903 u32 new_id = m_id_to_value.size();
1904 m_value_to_id.insert(value, new_id);
1910 // Values are stored here at id-1 position (id 1 = [0])
1911 core::array<T> m_id_to_value;
1912 core::map<T, u32> m_value_to_id;
1916 Checks if a string contains only supplied characters
1918 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1920 for(u32 i=0; i<s.size(); i++)
1922 bool confirmed = false;
1923 for(u32 j=0; j<allowed_chars.size(); j++)
1925 if(s[i] == allowed_chars[j])
1931 if(confirmed == false)
1938 Forcefully wraps string into rows using \n
1939 (no word wrap, used for showing paths in gui)
1941 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1944 for(u32 i=0; i<from.size(); i++)
1946 if(i != 0 && i%rowlen == 0)
1956 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1957 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1960 Returns integer position of node in given floating point position
1962 inline v3s16 floatToInt(v3f p, f32 d)
1965 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1966 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1967 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1972 Returns floating point position of node in given integer position
1974 inline v3f intToFloat(v3s16 p, f32 d)
1985 More serialization stuff
1988 // Creates a string with the length as the first two bytes
1989 inline std::string serializeString(const std::string &plain)
1991 //assert(plain.size() <= 65535);
1992 if(plain.size() > 65535)
1993 throw SerializationError("String too long for serializeString");
1995 writeU16((u8*)&buf[0], plain.size());
2002 // Creates a string with the length as the first two bytes from wide string
2003 inline std::string serializeWideString(const std::wstring &plain)
2005 //assert(plain.size() <= 65535);
2006 if(plain.size() > 65535)
2007 throw SerializationError("String too long for serializeString");
2009 writeU16((u8*)buf, plain.size());
2012 for(u32 i=0; i<plain.size(); i++)
2014 writeU16((u8*)buf, plain[i]);
2020 // Reads a string with the length as the first two bytes
2021 inline std::string deSerializeString(std::istream &is)
2025 if(is.gcount() != 2)
2026 throw SerializationError("deSerializeString: size not read");
2027 u16 s_size = readU16((u8*)buf);
2030 Buffer<char> buf2(s_size);
2031 is.read(&buf2[0], s_size);
2034 s.append(&buf2[0], s_size);
2038 // Reads a wide string with the length as the first two bytes
2039 inline std::wstring deSerializeWideString(std::istream &is)
2043 if(is.gcount() != 2)
2044 throw SerializationError("deSerializeString: size not read");
2045 u16 s_size = readU16((u8*)buf);
2050 for(u32 i=0; i<s_size; i++)
2052 is.read(&buf[0], 2);
2053 wchar_t c16 = readU16((u8*)buf);
2059 // Creates a string with the length as the first four bytes
2060 inline std::string serializeLongString(const std::string &plain)
2063 writeU32((u8*)&buf[0], plain.size());
2070 // Reads a string with the length as the first four bytes
2071 inline std::string deSerializeLongString(std::istream &is)
2075 if(is.gcount() != 4)
2076 throw SerializationError("deSerializeLongString: size not read");
2077 u32 s_size = readU32((u8*)buf);
2080 Buffer<char> buf2(s_size);
2081 is.read(&buf2[0], s_size);
2084 s.append(&buf2[0], s_size);
2090 inline u32 time_to_daynight_ratio(u32 time_of_day)
2092 const s32 daylength = 16;
2093 const s32 nightlength = 6;
2094 const s32 daytimelength = 8;
2096 s32 t = (((time_of_day)%24000)/(24000/d));
2097 if(t < nightlength/2 || t >= d - nightlength/2)
2100 else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
2106 // Random helper. Usually d=BS
2107 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
2109 return core::aabbox3d<f32>(
2110 (float)p.X * d - 0.5*d,
2111 (float)p.Y * d - 0.5*d,
2112 (float)p.Z * d - 0.5*d,
2113 (float)p.X * d + 0.5*d,
2114 (float)p.Y * d + 0.5*d,
2115 (float)p.Z * d + 0.5*d
2119 class IntervalLimiter
2127 dtime: time from last call to this method
2128 wanted_interval: interval wanted
2130 true: action should be skipped
2131 false: action should be done
2133 bool step(float dtime, float wanted_interval)
2135 m_accumulator += dtime;
2136 if(m_accumulator < wanted_interval)
2138 m_accumulator -= wanted_interval;
2142 float m_accumulator;
2145 std::string translatePassword(std::string playername, std::wstring password);