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 setDefault(std::string name, std::string value)
1266 JMutexAutoLock lock(m_mutex);
1268 m_defaults[name] = value;
1271 bool exists(std::string name)
1273 JMutexAutoLock lock(m_mutex);
1275 return (m_settings.find(name) || m_defaults.find(name));
1278 std::string get(std::string name)
1280 JMutexAutoLock lock(m_mutex);
1282 core::map<std::string, std::string>::Node *n;
1283 n = m_settings.find(name);
1286 n = m_defaults.find(name);
1289 dstream<<"INFO: Settings: Setting not found: \""
1290 <<name<<"\""<<std::endl;
1291 throw SettingNotFoundException("Setting not found");
1295 return n->getValue();
1298 bool getBool(std::string name)
1300 return is_yes(get(name));
1303 bool getFlag(std::string name)
1307 return getBool(name);
1309 catch(SettingNotFoundException &e)
1316 bool getBoolAsk(std::string name, std::string question, bool def)
1318 // If it is in settings
1320 return getBool(name);
1324 std::cout<<question<<" [y/N]: ";
1325 std::cin.getline(templine, 10);
1334 float getFloat(std::string name)
1336 return stof(get(name));
1339 u16 getU16(std::string name)
1341 return stoi(get(name), 0, 65535);
1344 u16 getU16Ask(std::string name, std::string question, u16 def)
1346 // If it is in settings
1348 return getU16(name);
1352 std::cout<<question<<" ["<<def<<"]: ";
1353 std::cin.getline(templine, 10);
1359 return stoi(s, 0, 65535);
1362 s16 getS16(std::string name)
1364 return stoi(get(name), -32768, 32767);
1367 s32 getS32(std::string name)
1369 return stoi(get(name));
1372 v3f getV3F(std::string name)
1375 Strfnd f(get(name));
1377 value.X = stof(f.next(","));
1378 value.Y = stof(f.next(","));
1379 value.Z = stof(f.next(")"));
1383 u64 getU64(std::string name)
1386 std::string s = get(name);
1387 std::istringstream ss(s);
1392 void setBool(std::string name, bool value)
1400 void setS32(std::string name, s32 value)
1402 set(name, itos(value));
1405 void setFloat(std::string name, float value)
1407 set(name, ftos(value));
1410 void setV3F(std::string name, v3f value)
1412 std::ostringstream os;
1413 os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
1414 set(name, os.str());
1417 void setU64(std::string name, u64 value)
1419 std::ostringstream os;
1421 set(name, os.str());
1426 JMutexAutoLock lock(m_mutex);
1432 Settings & operator+=(Settings &other)
1434 JMutexAutoLock lock(m_mutex);
1435 JMutexAutoLock lock2(other.m_mutex);
1440 for(core::map<std::string, std::string>::Iterator
1441 i = other.m_settings.getIterator();
1442 i.atEnd() == false; i++)
1444 m_settings.insert(i.getNode()->getKey(),
1445 i.getNode()->getValue());
1448 for(core::map<std::string, std::string>::Iterator
1449 i = other.m_defaults.getIterator();
1450 i.atEnd() == false; i++)
1452 m_defaults.insert(i.getNode()->getKey(),
1453 i.getNode()->getValue());
1458 Settings & operator=(Settings &other)
1460 JMutexAutoLock lock(m_mutex);
1461 JMutexAutoLock lock2(other.m_mutex);
1473 core::map<std::string, std::string> m_settings;
1474 core::map<std::string, std::string> m_defaults;
1475 // All methods that access m_settings/m_defaults directly should lock this.
1480 FIFO queue (well, actually a FILO also)
1482 template<typename T>
1488 m_list.push_back(t);
1493 if(m_list.size() == 0)
1494 throw ItemNotFoundException("Queue: queue is empty");
1496 typename core::list<T>::Iterator begin = m_list.begin();
1498 m_list.erase(begin);
1503 if(m_list.size() == 0)
1504 throw ItemNotFoundException("Queue: queue is empty");
1506 typename core::list<T>::Iterator last = m_list.getLast();
1514 return m_list.size();
1518 core::list<T> m_list;
1522 Thread-safe FIFO queue (well, actually a FILO also)
1525 template<typename T>
1535 JMutexAutoLock lock(m_mutex);
1536 return m_list.size();
1540 JMutexAutoLock lock(m_mutex);
1541 m_list.push_back(t);
1543 T pop_front(u32 wait_time_max_ms=0)
1545 u32 wait_time_ms = 0;
1550 JMutexAutoLock lock(m_mutex);
1552 if(m_list.size() > 0)
1554 typename core::list<T>::Iterator begin = m_list.begin();
1556 m_list.erase(begin);
1560 if(wait_time_ms >= wait_time_max_ms)
1561 throw ItemNotFoundException("MutexedQueue: queue is empty");
1564 // Wait a while before trying again
1569 T pop_back(u32 wait_time_max_ms=0)
1571 u32 wait_time_ms = 0;
1576 JMutexAutoLock lock(m_mutex);
1578 if(m_list.size() > 0)
1580 typename core::list<T>::Iterator last = m_list.getLast();
1586 if(wait_time_ms >= wait_time_max_ms)
1587 throw ItemNotFoundException("MutexedQueue: queue is empty");
1590 // Wait a while before trying again
1601 core::list<T> & getList()
1608 core::list<T> m_list;
1612 A single worker thread - multiple client threads queue framework.
1615 template<typename Caller, typename Data>
1623 template<typename Key, typename T, typename Caller, typename CallerData>
1629 core::list<CallerInfo<Caller, CallerData> > callers;
1632 template<typename Key, typename T, typename Caller, typename CallerData>
1633 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1637 template<typename Key, typename T, typename Caller, typename CallerData>
1645 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1649 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1660 ResultQueue<Key, T, Caller, CallerData> *dest;
1661 core::list<CallerInfo<Caller, CallerData> > callers;
1664 template<typename Key, typename T, typename Caller, typename CallerData>
1670 return m_queue.size();
1673 void add(Key key, Caller caller, CallerData callerdata,
1674 ResultQueue<Key, T, Caller, CallerData> *dest)
1676 JMutexAutoLock lock(m_queue.getMutex());
1679 If the caller is already on the list, only update CallerData
1681 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1682 i = m_queue.getList().begin();
1683 i != m_queue.getList().end(); i++)
1685 GetRequest<Key, T, Caller, CallerData> &request = *i;
1687 if(request.key == key)
1689 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1690 i = request.callers.begin();
1691 i != request.callers.end(); i++)
1693 CallerInfo<Caller, CallerData> &ca = *i;
1694 if(ca.caller == caller)
1696 ca.data = callerdata;
1700 CallerInfo<Caller, CallerData> ca;
1702 ca.data = callerdata;
1703 request.callers.push_back(ca);
1709 Else add a new request to the queue
1712 GetRequest<Key, T, Caller, CallerData> request;
1714 CallerInfo<Caller, CallerData> ca;
1716 ca.data = callerdata;
1717 request.callers.push_back(ca);
1718 request.dest = dest;
1720 m_queue.getList().push_back(request);
1723 GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1725 return m_queue.pop_front(wait_if_empty);
1729 MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1733 Pseudo-random (VC++ rand() sucks)
1736 void mysrand(unsigned seed);
1737 #define MYRAND_MAX 32767
1739 inline int myrand_range(int min, int max)
1746 return (myrand()%(max-min+1))+min;
1750 Miscellaneous functions
1753 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
1754 f32 *distance_ptr=NULL);
1757 Queue with unique values with fast checking of value existence
1760 template<typename Value>
1766 Does nothing if value is already queued.
1769 false: value already exists
1771 bool push_back(Value value)
1773 // Check if already exists
1774 if(m_map.find(value) != NULL)
1778 m_map.insert(value, 0);
1779 m_list.push_back(value);
1786 typename core::list<Value>::Iterator i = m_list.begin();
1788 m_map.remove(value);
1795 assert(m_list.size() == m_map.size());
1796 return m_list.size();
1800 core::map<Value, u8> m_map;
1801 core::list<Value> m_list;
1805 template<typename Key, typename Value>
1812 assert(m_mutex.IsInitialized());
1815 void set(const Key &name, const Value &value)
1817 JMutexAutoLock lock(m_mutex);
1819 m_values[name] = value;
1822 bool get(const Key &name, Value *result)
1824 JMutexAutoLock lock(m_mutex);
1826 typename core::map<Key, Value>::Node *n;
1827 n = m_values.find(name);
1833 *result = n->getValue();
1839 core::map<Key, Value> m_values;
1845 Generates ids for comparable values.
1846 Id=0 is reserved for "no value".
1849 - Returning value by id (very fast)
1850 - Returning id by value
1851 - Generating a new id for a value
1854 - Remove an id/value pair (is possible to implement but slow)
1856 template<typename T>
1857 class MutexedIdGenerator
1860 MutexedIdGenerator()
1863 assert(m_mutex.IsInitialized());
1866 // Returns true if found
1867 bool getValue(u32 id, T &value)
1871 JMutexAutoLock lock(m_mutex);
1872 if(m_id_to_value.size() < id)
1874 value = m_id_to_value[id-1];
1878 // If id exists for value, returns the id.
1879 // Otherwise generates an id for the value.
1880 u32 getId(const T &value)
1882 JMutexAutoLock lock(m_mutex);
1883 typename core::map<T, u32>::Node *n;
1884 n = m_value_to_id.find(value);
1886 return n->getValue();
1887 m_id_to_value.push_back(value);
1888 u32 new_id = m_id_to_value.size();
1889 m_value_to_id.insert(value, new_id);
1895 // Values are stored here at id-1 position (id 1 = [0])
1896 core::array<T> m_id_to_value;
1897 core::map<T, u32> m_value_to_id;
1901 Checks if a string contains only supplied characters
1903 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1905 for(u32 i=0; i<s.size(); i++)
1907 bool confirmed = false;
1908 for(u32 j=0; j<allowed_chars.size(); j++)
1910 if(s[i] == allowed_chars[j])
1916 if(confirmed == false)
1923 Forcefully wraps string into rows using \n
1924 (no word wrap, used for showing paths in gui)
1926 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1929 for(u32 i=0; i<from.size(); i++)
1931 if(i != 0 && i%rowlen == 0)
1941 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1942 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1945 Returns integer position of node in given floating point position
1947 inline v3s16 floatToInt(v3f p, f32 d)
1950 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1951 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1952 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1957 Returns floating point position of node in given integer position
1959 inline v3f intToFloat(v3s16 p, f32 d)
1970 More serialization stuff
1973 // Creates a string with the length as the first two bytes
1974 inline std::string serializeString(const std::string &plain)
1976 //assert(plain.size() <= 65535);
1977 if(plain.size() > 65535)
1978 throw SerializationError("String too long for serializeString");
1980 writeU16((u8*)&buf[0], plain.size());
1987 /*// Reads a string with the length as the first two bytes
1988 inline std::string deSerializeString(const std::string encoded)
1990 u16 s_size = readU16((u8*)&encoded.c_str()[0]);
1991 if(s_size > encoded.length() - 2)
1995 s.append(&encoded.c_str()[2], s_size);
1999 // Reads a string with the length as the first two bytes
2000 inline std::string deSerializeString(std::istream &is)
2004 if(is.gcount() != 2)
2005 throw SerializationError("deSerializeString: size not read");
2006 u16 s_size = readU16((u8*)buf);
2009 Buffer<char> buf2(s_size);
2010 is.read(&buf2[0], s_size);
2013 s.append(&buf2[0], s_size);
2017 // Creates a string with the length as the first four bytes
2018 inline std::string serializeLongString(const std::string &plain)
2021 writeU32((u8*)&buf[0], plain.size());
2028 /*// Reads a string with the length as the first four bytes
2029 inline std::string deSerializeLongString(const std::string encoded)
2031 u32 s_size = readU32((u8*)&encoded.c_str()[0]);
2032 if(s_size > encoded.length() - 4)
2036 s.append(&encoded.c_str()[4], s_size);
2040 // Reads a string with the length as the first four bytes
2041 inline std::string deSerializeLongString(std::istream &is)
2045 if(is.gcount() != 4)
2046 throw SerializationError("deSerializeLongString: size not read");
2047 u32 s_size = readU32((u8*)buf);
2050 Buffer<char> buf2(s_size);
2051 is.read(&buf2[0], s_size);
2054 s.append(&buf2[0], s_size);
2060 inline u32 time_to_daynight_ratio(u32 time_of_day)
2062 const s32 daylength = 16;
2063 const s32 nightlength = 6;
2064 const s32 daytimelength = 8;
2066 s32 t = (((time_of_day)%24000)/(24000/d));
2067 if(t < nightlength/2 || t >= d - nightlength/2)
2070 else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
2076 // Random helper. Usually d=BS
2077 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
2079 return core::aabbox3d<f32>(
2080 (float)p.X * d - 0.5*d,
2081 (float)p.Y * d - 0.5*d,
2082 (float)p.Z * d - 0.5*d,
2083 (float)p.X * d + 0.5*d,
2084 (float)p.Y * d + 0.5*d,
2085 (float)p.Z * d + 0.5*d
2089 class IntervalLimiter
2097 dtime: time from last call to this method
2098 wanted_interval: interval wanted
2100 true: action should be skipped
2101 false: action should be done
2103 bool step(float dtime, float wanted_interval)
2105 m_accumulator += dtime;
2106 if(m_accumulator < wanted_interval)
2108 m_accumulator -= wanted_interval;
2112 float m_accumulator;
2115 std::string translatePassword(std::string playername, std::wstring password);