3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #ifndef UTILITY_HEADER
21 #define UTILITY_HEADER
29 #include <jmutexautolock.h>
31 #include "common_irrlicht.h"
34 #include "exceptions.h"
37 extern const v3s16 g_26dirs[26];
40 extern const v3s16 g_27dirs[27];
42 inline void writeU32(u8 *data, u32 i)
44 data[0] = ((i>>24)&0xff);
45 data[1] = ((i>>16)&0xff);
46 data[2] = ((i>> 8)&0xff);
47 data[3] = ((i>> 0)&0xff);
50 inline void writeU16(u8 *data, u16 i)
52 data[0] = ((i>> 8)&0xff);
53 data[1] = ((i>> 0)&0xff);
56 inline void writeU8(u8 *data, u8 i)
58 data[0] = ((i>> 0)&0xff);
61 inline u32 readU32(u8 *data)
63 return (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | (data[3]<<0);
66 inline u16 readU16(u8 *data)
68 return (data[0]<<8) | (data[1]<<0);
71 inline u8 readU8(u8 *data)
76 // Signed variants of the above
78 inline void writeS32(u8 *data, s32 i){
79 writeU32(data, (u32)i);
81 inline s32 readS32(u8 *data){
82 return (s32)readU32(data);
85 inline void writeS16(u8 *data, s16 i){
86 writeU16(data, (u16)i);
88 inline s16 readS16(u8 *data){
89 return (s16)readU16(data);
92 inline void writeV3S32(u8 *data, v3s32 p)
94 writeS32(&data[0], p.X);
95 writeS32(&data[4], p.Y);
96 writeS32(&data[8], p.Z);
99 inline v3s32 readV3S32(u8 *data)
102 p.X = readS32(&data[0]);
103 p.Y = readS32(&data[4]);
104 p.Z = readS32(&data[8]);
108 inline void writeV2S16(u8 *data, v2s16 p)
110 writeS16(&data[0], p.X);
111 writeS16(&data[2], p.Y);
114 inline v2s16 readV2S16(u8 *data)
117 p.X = readS16(&data[0]);
118 p.Y = readS16(&data[2]);
122 inline void writeV2S32(u8 *data, v2s32 p)
124 writeS32(&data[0], p.X);
125 writeS32(&data[2], p.Y);
128 inline v2s32 readV2S32(u8 *data)
131 p.X = readS32(&data[0]);
132 p.Y = readS32(&data[2]);
136 inline void writeV3S16(u8 *data, v3s16 p)
138 writeS16(&data[0], p.X);
139 writeS16(&data[2], p.Y);
140 writeS16(&data[4], p.Z);
143 inline v3s16 readV3S16(u8 *data)
146 p.X = readS16(&data[0]);
147 p.Y = readS16(&data[2]);
148 p.Z = readS16(&data[4]);
153 None of these are used at the moment
156 template <typename T>
166 SharedPtr(SharedPtr<T> &t)
170 refcount = t.refcount;
178 SharedPtr<T> & operator=(T *t)
186 SharedPtr<T> & operator=(SharedPtr<T> &t)
189 refcount = t.refcount;
202 bool operator!=(T *t)
206 bool operator==(T *t)
210 T & operator[](unsigned int i)
217 assert((*refcount) > 0);
230 template <typename T>
234 Buffer(unsigned int size)
239 Buffer(const Buffer &buffer)
241 m_size = buffer.m_size;
242 data = new T[buffer.m_size];
243 memcpy(data, buffer.data, buffer.m_size);
245 Buffer(T *t, unsigned int size)
249 memcpy(data, t, size);
255 T & operator[](unsigned int i) const
259 T * operator*() const
263 unsigned int getSize() const
272 template <typename T>
276 SharedBuffer(unsigned int size)
280 refcount = new unsigned int;
283 SharedBuffer(const SharedBuffer &buffer)
285 //std::cout<<"SharedBuffer(const SharedBuffer &buffer)"<<std::endl;
286 m_size = buffer.m_size;
288 refcount = buffer.refcount;
291 SharedBuffer & operator=(const SharedBuffer & buffer)
293 //std::cout<<"SharedBuffer & operator=(const SharedBuffer & buffer)"<<std::endl;
297 m_size = buffer.m_size;
299 refcount = buffer.refcount;
306 SharedBuffer(T *t, unsigned int size)
310 memcpy(data, t, size);
311 refcount = new unsigned int;
317 SharedBuffer(const Buffer<T> &buffer)
319 m_size = buffer.m_size;
320 data = new T[buffer.getSize()];
321 memcpy(data, *buffer, buffer.getSize());
322 refcount = new unsigned int;
329 T & operator[](unsigned int i) const
333 T * operator*() const
337 unsigned int getSize() const
344 assert((*refcount) > 0);
354 unsigned int *refcount;
357 inline SharedBuffer<u8> SharedBufferFromString(const char *string)
359 SharedBuffer<u8> b((u8*)string, strlen(string)+1);
364 class MutexedVariable
367 MutexedVariable(T value):
375 JMutexAutoLock lock(m_mutex);
381 JMutexAutoLock lock(m_mutex);
385 // You'll want to grab this in a SharedPtr
386 JMutexAutoLock * getLock()
388 return new JMutexAutoLock(m_mutex);
391 // You pretty surely want to grab the lock when accessing this
402 class IrrlichtWrapper;
407 TimeTaker(const char *name, u32 *result=NULL);
414 u32 stop(bool quiet=false);
425 // Calculates the borders of a "d-radius" cube
426 inline void getFacePositions(core::list<v3s16> &list, u16 d)
430 list.push_back(v3s16(0,0,0));
436 This is an optimized sequence of coordinates.
438 list.push_back(v3s16( 0, 1, 0)); // top
439 list.push_back(v3s16( 0, 0, 1)); // back
440 list.push_back(v3s16(-1, 0, 0)); // left
441 list.push_back(v3s16( 1, 0, 0)); // right
442 list.push_back(v3s16( 0, 0,-1)); // front
443 list.push_back(v3s16( 0,-1, 0)); // bottom
445 list.push_back(v3s16(-1, 0, 1)); // back left
446 list.push_back(v3s16( 1, 0, 1)); // back right
447 list.push_back(v3s16(-1, 0,-1)); // front left
448 list.push_back(v3s16( 1, 0,-1)); // front right
449 list.push_back(v3s16(-1,-1, 0)); // bottom left
450 list.push_back(v3s16( 1,-1, 0)); // bottom right
451 list.push_back(v3s16( 0,-1, 1)); // bottom back
452 list.push_back(v3s16( 0,-1,-1)); // bottom front
453 list.push_back(v3s16(-1, 1, 0)); // top left
454 list.push_back(v3s16( 1, 1, 0)); // top right
455 list.push_back(v3s16( 0, 1, 1)); // top back
456 list.push_back(v3s16( 0, 1,-1)); // top front
458 list.push_back(v3s16(-1, 1, 1)); // top back-left
459 list.push_back(v3s16( 1, 1, 1)); // top back-right
460 list.push_back(v3s16(-1, 1,-1)); // top front-left
461 list.push_back(v3s16( 1, 1,-1)); // top front-right
462 list.push_back(v3s16(-1,-1, 1)); // bottom back-left
463 list.push_back(v3s16( 1,-1, 1)); // bottom back-right
464 list.push_back(v3s16(-1,-1,-1)); // bottom front-left
465 list.push_back(v3s16( 1,-1,-1)); // bottom front-right
470 // Take blocks in all sides, starting from y=0 and going +-y
471 for(s16 y=0; y<=d-1; y++)
473 // Left and right side, including borders
474 for(s16 z=-d; z<=d; z++)
476 list.push_back(v3s16(d,y,z));
477 list.push_back(v3s16(-d,y,z));
480 list.push_back(v3s16(d,-y,z));
481 list.push_back(v3s16(-d,-y,z));
484 // Back and front side, excluding borders
485 for(s16 x=-d+1; x<=d-1; x++)
487 list.push_back(v3s16(x,y,d));
488 list.push_back(v3s16(x,y,-d));
491 list.push_back(v3s16(x,-y,d));
492 list.push_back(v3s16(x,-y,-d));
497 // Take the bottom and top face with borders
498 // -d<x<d, y=+-d, -d<z<d
499 for(s16 x=-d; x<=d; x++)
500 for(s16 z=-d; z<=d; z++)
502 list.push_back(v3s16(x,-d,z));
503 list.push_back(v3s16(x,d,z));
507 class IndentationRaiser
510 IndentationRaiser(u16 *indentation)
512 m_indentation = indentation;
523 inline s16 getContainerPos(s16 p, s16 d)
525 return (p>=0 ? p : p-d+1) / d;
528 inline v2s16 getContainerPos(v2s16 p, s16 d)
531 getContainerPos(p.X, d),
532 getContainerPos(p.Y, d)
536 inline v3s16 getContainerPos(v3s16 p, s16 d)
539 getContainerPos(p.X, d),
540 getContainerPos(p.Y, d),
541 getContainerPos(p.Z, d)
545 inline v2s16 getContainerPos(v2s16 p, v2s16 d)
548 getContainerPos(p.X, d.X),
549 getContainerPos(p.Y, d.Y)
553 inline v3s16 getContainerPos(v3s16 p, v3s16 d)
556 getContainerPos(p.X, d.X),
557 getContainerPos(p.Y, d.Y),
558 getContainerPos(p.Z, d.Z)
562 inline bool isInArea(v3s16 p, s16 d)
565 p.X >= 0 && p.X < d &&
566 p.Y >= 0 && p.Y < d &&
571 inline bool isInArea(v2s16 p, s16 d)
574 p.X >= 0 && p.X < d &&
579 inline bool isInArea(v3s16 p, v3s16 d)
582 p.X >= 0 && p.X < d.X &&
583 p.Y >= 0 && p.Y < d.Y &&
584 p.Z >= 0 && p.Z < d.Z
588 inline s16 rangelim(s16 i, s16 max)
597 #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
599 inline v3s16 arealim(v3s16 p, s16 d)
616 inline std::wstring narrow_to_wide(const std::string& mbs)
618 size_t wcl = mbs.size();
619 Buffer<wchar_t> wcs(wcl+1);
620 size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
621 if(l == (size_t)(-1))
622 return L"<invalid multibyte string>";
627 inline std::string wide_to_narrow(const std::wstring& wcs)
629 size_t mbl = wcs.size()*4;
630 SharedBuffer<char> mbs(mbl+1);
631 size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
632 if(l == (size_t)(-1))
640 See test.cpp for example cases.
641 wraps degrees to the range of -360...360
642 NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
644 inline float wrapDegrees(float f)
646 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
652 // NOTE: This would be used for wrapping to 0...360
658 // 10, 0.5, -0.5, -0.5
663 inline std::string lowercase(const std::string &s)
666 for(size_t i=0; i<s.size(); i++)
669 if(c >= 'A' && c <= 'Z')
676 inline bool is_yes(const std::string &s)
678 std::string s2 = lowercase(trim(s));
679 if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
684 inline s32 stoi(const std::string &s, s32 min, s32 max)
686 s32 i = atoi(s.c_str());
694 inline s32 stoi(std::string s)
696 return atoi(s.c_str());
699 inline float stof(std::string s)
702 std::istringstream ss(s);
707 inline std::string itos(s32 i)
709 std::ostringstream o;
714 inline std::string ftos(float f)
716 std::ostringstream o;
721 inline void str_replace(std::string & str, std::string const & pattern,
722 std::string const & replacement)
724 std::string::size_type start = str.find(pattern, 0);
725 while(start != str.npos)
727 str.replace(start, pattern.size(), replacement);
728 start = str.find(pattern, start+replacement.size());
732 inline void str_replace_char(std::string & str, char from, char to)
734 for(unsigned int i=0; i<str.size(); i++)
742 A base class for simple background thread implementation
745 class SimpleThread : public JThread
759 virtual ~SimpleThread()
762 virtual void * Thread() = 0;
766 JMutexAutoLock lock(run_mutex);
769 void setRun(bool a_run)
771 JMutexAutoLock lock(run_mutex);
790 VALUETYPE_FLAG // Doesn't take any arguments
795 ValueSpec(ValueType a_type, const char *a_help=NULL)
812 void writeLines(std::ostream &os)
814 JMutexAutoLock lock(m_mutex);
816 for(core::map<std::string, std::string>::Iterator
817 i = m_settings.getIterator();
818 i.atEnd() == false; i++)
820 std::string name = i.getNode()->getKey();
821 std::string value = i.getNode()->getValue();
822 os<<name<<" = "<<value<<"\n";
826 bool parseConfigLine(const std::string &line)
828 JMutexAutoLock lock(m_mutex);
830 std::string trimmedline = trim(line);
833 if(trimmedline[0] == '#')
836 //dstream<<"trimmedline=\""<<trimmedline<<"\""<<std::endl;
838 Strfnd sf(trim(line));
840 std::string name = sf.next("=");
846 std::string value = sf.next("\n");
849 /*dstream<<"Config name=\""<<name<<"\" value=\""
850 <<value<<"\""<<std::endl;*/
852 m_settings[name] = value;
857 // Returns false on EOF
858 bool parseConfigObject(std::istream &is)
864 NOTE: This function might be expanded to allow multi-line
868 std::getline(is, line);
869 //dstream<<"got line: \""<<line<<"\""<<std::endl;
871 return parseConfigLine(line);
875 Read configuration file
877 Returns true on success
879 bool readConfigFile(const char *filename)
881 std::ifstream is(filename);
882 if(is.good() == false)
884 dstream<<"Error opening configuration file \""
885 <<filename<<"\""<<std::endl;
889 dstream<<"Parsing configuration file: \""
890 <<filename<<"\""<<std::endl;
892 while(parseConfigObject(is));
898 Reads a configuration object from stream (usually a single line)
901 Preserves comments and empty lines.
903 Settings that were added to dst are also added to updated.
904 key of updated is setting name, value of updated is dummy.
908 bool getUpdatedConfigObject(std::istream &is,
909 core::list<std::string> &dst,
910 core::map<std::string, bool> &updated)
912 JMutexAutoLock lock(m_mutex);
917 // NOTE: This function will be expanded to allow multi-line settings
919 std::getline(is, line);
921 std::string trimmedline = trim(line);
923 std::string line_end = "";
924 if(is.eof() == false)
928 if(trimmedline[0] == '#')
930 dst.push_back(line+line_end);
934 Strfnd sf(trim(line));
936 std::string name = sf.next("=");
941 dst.push_back(line+line_end);
945 std::string value = sf.next("\n");
948 if(m_settings.find(name))
950 std::string newvalue = m_settings[name];
952 if(newvalue != value)
954 dstream<<"Changing value of \""<<name<<"\" = \""
955 <<value<<"\" -> \""<<newvalue<<"\""
959 dst.push_back(name + " = " + newvalue + line_end);
961 updated[name] = true;
968 Updates configuration file
970 Returns true on success
972 bool updateConfigFile(const char *filename)
974 dstream<<"Updating configuration file: \""
975 <<filename<<"\""<<std::endl;
977 core::list<std::string> objects;
978 core::map<std::string, bool> updated;
980 // Read and modify stuff
982 std::ifstream is(filename);
983 if(is.good() == false)
985 dstream<<"INFO: updateConfigFile():"
986 " Error opening configuration file"
988 <<filename<<"\""<<std::endl;
992 while(getUpdatedConfigObject(is, objects, updated));
996 JMutexAutoLock lock(m_mutex);
1000 std::ofstream os(filename);
1001 if(os.good() == false)
1003 dstream<<"Error opening configuration file"
1005 <<filename<<"\""<<std::endl;
1012 for(core::list<std::string>::Iterator
1013 i = objects.begin();
1014 i != objects.end(); i++)
1020 Write stuff that was not already in the file
1022 for(core::map<std::string, std::string>::Iterator
1023 i = m_settings.getIterator();
1024 i.atEnd() == false; i++)
1026 if(updated.find(i.getNode()->getKey()))
1028 std::string name = i.getNode()->getKey();
1029 std::string value = i.getNode()->getValue();
1030 dstream<<"Adding \""<<name<<"\" = \""<<value<<"\""
1032 os<<name<<" = "<<value<<"\n";
1040 NOTE: Types of allowed_options are ignored
1042 returns true on success
1044 bool parseCommandLine(int argc, char *argv[],
1045 core::map<std::string, ValueSpec> &allowed_options)
1052 std::string argname = argv[i];
1053 if(argname.substr(0, 2) != "--")
1055 dstream<<"Invalid command-line parameter \""
1056 <<argname<<"\": --<option> expected."<<std::endl;
1061 std::string name = argname.substr(2);
1063 core::map<std::string, ValueSpec>::Node *n;
1064 n = allowed_options.find(name);
1067 dstream<<"Unknown command-line parameter \""
1068 <<argname<<"\""<<std::endl;
1072 ValueType type = n->getValue().type;
1074 std::string value = "";
1076 if(type == VALUETYPE_FLAG)
1084 dstream<<"Invalid command-line parameter \""
1085 <<name<<"\": missing value"<<std::endl;
1093 dstream<<"Valid command-line parameter: \""
1094 <<name<<"\" = \""<<value<<"\""
1102 void set(std::string name, std::string value)
1104 JMutexAutoLock lock(m_mutex);
1106 m_settings[name] = value;
1109 void setDefault(std::string name, std::string value)
1111 JMutexAutoLock lock(m_mutex);
1113 m_defaults[name] = value;
1116 bool exists(std::string name)
1118 JMutexAutoLock lock(m_mutex);
1120 return (m_settings.find(name) || m_defaults.find(name));
1123 std::string get(std::string name)
1125 JMutexAutoLock lock(m_mutex);
1127 core::map<std::string, std::string>::Node *n;
1128 n = m_settings.find(name);
1131 n = m_defaults.find(name);
1134 dstream<<"INFO: Settings: Setting not found: \""
1135 <<name<<"\""<<std::endl;
1136 throw SettingNotFoundException("Setting not found");
1140 return n->getValue();
1143 bool getBool(std::string name)
1145 return is_yes(get(name));
1148 bool getFlag(std::string name)
1152 return getBool(name);
1154 catch(SettingNotFoundException &e)
1161 bool getBoolAsk(std::string name, std::string question, bool def)
1163 // If it is in settings
1165 return getBool(name);
1169 std::cout<<question<<" [y/N]: ";
1170 std::cin.getline(templine, 10);
1179 float getFloat(std::string name)
1181 return stof(get(name));
1184 u16 getU16(std::string name)
1186 return stoi(get(name), 0, 65535);
1189 u16 getU16Ask(std::string name, std::string question, u16 def)
1191 // If it is in settings
1193 return getU16(name);
1197 std::cout<<question<<" ["<<def<<"]: ";
1198 std::cin.getline(templine, 10);
1204 return stoi(s, 0, 65535);
1207 s16 getS16(std::string name)
1209 return stoi(get(name), -32768, 32767);
1212 s32 getS32(std::string name)
1214 return stoi(get(name));
1217 v3f getV3F(std::string name)
1220 Strfnd f(get(name));
1222 value.X = stof(f.next(","));
1223 value.Y = stof(f.next(","));
1224 value.Z = stof(f.next(")"));
1228 u64 getU64(std::string name)
1231 std::string s = get(name);
1232 std::istringstream ss(s);
1237 void setS32(std::string name, s32 value)
1239 set(name, itos(value));
1242 void setFloat(std::string name, float value)
1244 set(name, ftos(value));
1247 void setV3F(std::string name, v3f value)
1249 std::ostringstream os;
1250 os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
1251 set(name, os.str());
1254 void setU64(std::string name, u64 value)
1256 std::ostringstream os;
1258 set(name, os.str());
1263 JMutexAutoLock lock(m_mutex);
1269 Settings & operator+=(Settings &other)
1271 JMutexAutoLock lock(m_mutex);
1272 JMutexAutoLock lock2(other.m_mutex);
1277 for(core::map<std::string, std::string>::Iterator
1278 i = other.m_settings.getIterator();
1279 i.atEnd() == false; i++)
1281 m_settings.insert(i.getNode()->getKey(),
1282 i.getNode()->getValue());
1285 for(core::map<std::string, std::string>::Iterator
1286 i = other.m_defaults.getIterator();
1287 i.atEnd() == false; i++)
1289 m_defaults.insert(i.getNode()->getKey(),
1290 i.getNode()->getValue());
1295 Settings & operator=(Settings &other)
1297 JMutexAutoLock lock(m_mutex);
1298 JMutexAutoLock lock2(other.m_mutex);
1310 core::map<std::string, std::string> m_settings;
1311 core::map<std::string, std::string> m_defaults;
1312 // All methods that access m_settings/m_defaults directly should lock this.
1317 FIFO queue (well, actually a FILO also)
1319 template<typename T>
1325 m_list.push_back(t);
1330 if(m_list.size() == 0)
1331 throw ItemNotFoundException("Queue: queue is empty");
1333 typename core::list<T>::Iterator begin = m_list.begin();
1335 m_list.erase(begin);
1340 if(m_list.size() == 0)
1341 throw ItemNotFoundException("Queue: queue is empty");
1343 typename core::list<T>::Iterator last = m_list.getLast();
1351 return m_list.size();
1355 core::list<T> m_list;
1359 Thread-safe FIFO queue (well, actually a FILO also)
1362 template<typename T>
1372 return m_list.size();
1376 JMutexAutoLock lock(m_mutex);
1377 m_list.push_back(t);
1379 T pop_front(u32 wait_time_max_ms=0)
1381 u32 wait_time_ms = 0;
1386 JMutexAutoLock lock(m_mutex);
1388 if(m_list.size() > 0)
1390 typename core::list<T>::Iterator begin = m_list.begin();
1392 m_list.erase(begin);
1396 if(wait_time_ms >= wait_time_max_ms)
1397 throw ItemNotFoundException("MutexedQueue: queue is empty");
1400 // Wait a while before trying again
1405 T pop_back(u32 wait_time_max_ms=0)
1407 u32 wait_time_ms = 0;
1412 JMutexAutoLock lock(m_mutex);
1414 if(m_list.size() > 0)
1416 typename core::list<T>::Iterator last = m_list.getLast();
1422 if(wait_time_ms >= wait_time_max_ms)
1423 throw ItemNotFoundException("MutexedQueue: queue is empty");
1426 // Wait a while before trying again
1437 core::list<T> & getList()
1444 core::list<T> m_list;
1447 template<typename Caller, typename Data>
1455 template<typename Key, typename T, typename Caller, typename CallerData>
1461 core::list<CallerInfo<Caller, CallerData> > callers;
1464 template<typename Key, typename T, typename Caller, typename CallerData>
1465 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1469 template<typename Key, typename T, typename Caller, typename CallerData>
1477 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1481 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1492 ResultQueue<Key, T, Caller, CallerData> *dest;
1493 core::list<CallerInfo<Caller, CallerData> > callers;
1497 Quickhands for typical request-result queues.
1498 Used for distributing work between threads.
1501 template<typename Key, typename T, typename Caller, typename CallerData>
1507 return m_queue.size();
1510 void add(Key key, Caller caller, CallerData callerdata,
1511 ResultQueue<Key, T, Caller, CallerData> *dest)
1513 JMutexAutoLock lock(m_queue.getMutex());
1516 If the caller is already on the list, only update CallerData
1518 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1519 i = m_queue.getList().begin();
1520 i != m_queue.getList().end(); i++)
1522 GetRequest<Key, T, Caller, CallerData> &request = *i;
1524 if(request.key == key)
1526 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1527 i = request.callers.begin();
1528 i != request.callers.end(); i++)
1530 CallerInfo<Caller, CallerData> &ca = *i;
1531 if(ca.caller == caller)
1533 ca.data = callerdata;
1537 CallerInfo<Caller, CallerData> ca;
1539 ca.data = callerdata;
1540 request.callers.push_back(ca);
1546 Else add a new request to the queue
1549 GetRequest<Key, T, Caller, CallerData> request;
1551 CallerInfo<Caller, CallerData> ca;
1553 ca.data = callerdata;
1554 request.callers.push_back(ca);
1555 request.dest = dest;
1557 m_queue.getList().push_back(request);
1560 GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1562 return m_queue.pop_front(wait_if_empty);
1566 MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1570 Pseudo-random (VC++ rand() sucks)
1573 void mysrand(unsigned seed);
1574 #define MYRAND_MAX 32767
1576 inline int myrand_range(int min, int max)
1583 return (myrand()%(max-min+1))+min;
1587 Miscellaneous functions
1590 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
1591 f32 *distance_ptr=NULL);
1594 Queue with unique values with fast checking of value existence
1597 template<typename Value>
1603 Does nothing if value is already queued.
1606 false: value already exists
1608 bool push_back(Value value)
1610 // Check if already exists
1611 if(m_map.find(value) != NULL)
1615 m_map.insert(value, 0);
1616 m_list.push_back(value);
1623 typename core::list<Value>::Iterator i = m_list.begin();
1625 m_map.remove(value);
1632 assert(m_list.size() == m_map.size());
1633 return m_list.size();
1637 core::map<Value, u8> m_map;
1638 core::list<Value> m_list;
1642 template<typename Key, typename Value>
1649 assert(m_mutex.IsInitialized());
1652 void set(const Key &name, const Value &value)
1654 JMutexAutoLock lock(m_mutex);
1656 m_values[name] = value;
1659 bool get(const Key &name, Value *result)
1661 JMutexAutoLock lock(m_mutex);
1663 typename core::map<Key, Value>::Node *n;
1664 n = m_values.find(name);
1669 *result = n->getValue();
1674 core::map<Key, Value> m_values;
1680 Generates ids for comparable values.
1681 Id=0 is reserved for "no value".
1684 - Returning value by id (very fast)
1685 - Returning id by value
1686 - Generating a new id for a value
1689 - Remove an id/value pair (is possible to implement but slow)
1691 template<typename T>
1692 class MutexedIdGenerator
1695 MutexedIdGenerator()
1698 assert(m_mutex.IsInitialized());
1701 // Returns true if found
1702 bool getValue(u32 id, T &value)
1706 JMutexAutoLock lock(m_mutex);
1707 if(m_id_to_value.size() < id)
1709 value = m_id_to_value[id-1];
1713 // If id exists for value, returns the id.
1714 // Otherwise generates an id for the value.
1715 u32 getId(const T &value)
1717 JMutexAutoLock lock(m_mutex);
1718 typename core::map<T, u32>::Node *n;
1719 n = m_value_to_id.find(value);
1721 return n->getValue();
1722 m_id_to_value.push_back(value);
1723 u32 new_id = m_id_to_value.size();
1724 m_value_to_id.insert(value, new_id);
1730 // Values are stored here at id-1 position (id 1 = [0])
1731 core::array<T> m_id_to_value;
1732 core::map<T, u32> m_value_to_id;
1736 Checks if a string contains only supplied characters
1738 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1740 for(u32 i=0; i<s.size(); i++)
1742 bool confirmed = false;
1743 for(u32 j=0; j<allowed_chars.size(); j++)
1745 if(s[i] == allowed_chars[j])
1751 if(confirmed == false)
1758 Forcefully wraps string into rows using \n
1759 (no word wrap, used for showing paths in gui)
1761 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1764 for(u32 i=0; i<from.size(); i++)
1766 if(i != 0 && i%rowlen == 0)
1776 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1777 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1780 Returns integer position of node in given floating point position
1782 inline v3s16 floatToInt(v3f p, f32 d)
1785 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1786 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1787 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1792 Returns floating point position of node in given integer position
1794 inline v3f intToFloat(v3s16 p, f32 d)
1805 More serialization stuff
1808 // Creates a string with the length as the first two bytes
1809 inline std::string serializeString(const std::string plain)
1811 assert(plain.size() <= 65535);
1813 writeU16((u8*)&buf[0], plain.size());
1820 // Reads a string with the length as the first two bytes
1821 inline std::string deSerializeString(const std::string encoded)
1823 u16 s_size = readU16((u8*)&encoded.c_str()[0]);
1826 s.append(&encoded.c_str()[2], s_size);
1830 // Reads a string with the length as the first two bytes
1831 inline std::string deSerializeString(std::istream &is)
1835 u16 s_size = readU16((u8*)buf);
1836 Buffer<char> buf2(s_size);
1837 is.read(&buf2[0], s_size);
1840 s.append(&buf2[0], s_size);
1844 // Creates a string with the length as the first four bytes
1845 inline std::string serializeLongString(const std::string plain)
1848 writeU32((u8*)&buf[0], plain.size());
1855 // Reads a string with the length as the first four bytes
1856 inline std::string deSerializeLongString(const std::string encoded)
1858 u32 s_size = readU32((u8*)&encoded.c_str()[0]);
1861 s.append(&encoded.c_str()[2], s_size);
1865 // Reads a string with the length as the first four bytes
1866 inline std::string deSerializeLongString(std::istream &is)
1870 u32 s_size = readU32((u8*)buf);
1871 Buffer<char> buf2(s_size);
1872 is.read(&buf2[0], s_size);
1875 s.append(&buf2[0], s_size);
1881 inline u32 time_to_daynight_ratio(u32 time_of_day)
1883 const s32 daylength = 16;
1884 const s32 nightlength = 6;
1885 const s32 daytimelength = 8;
1887 s32 t = (((time_of_day)%24000)/(24000/d));
1888 if(t < nightlength/2 || t >= d - nightlength/2)
1890 else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
1896 // Random helper. Usually d=BS
1897 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
1899 return core::aabbox3d<f32>(
1900 (float)p.X * d - 0.5*d,
1901 (float)p.Y * d - 0.5*d,
1902 (float)p.Z * d - 0.5*d,
1903 (float)p.X * d + 0.5*d,
1904 (float)p.Y * d + 0.5*d,
1905 (float)p.Z * d + 0.5*d