]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/utility.h
Goddamn MSVC pow overload ambiguities
[dragonfireclient.git] / src / utility.h
index cc8891a0797c1345d0325460c8a4821c373528c9..07216a27decfb89a84762e5768c7eab70d351ba7 100644 (file)
@@ -28,12 +28,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <jthread.h>
 #include <jmutex.h>
 #include <jmutexautolock.h>
+#include <cstring>
 
 #include "common_irrlicht.h"
 #include "debug.h"
-#include "strfnd.h"
 #include "exceptions.h"
 #include "porting.h"
+#include "strfnd.h" // For trim()
 
 extern const v3s16 g_6dirs[6];
 
@@ -103,13 +104,6 @@ inline s32 readS32(u8 *data){
        return (s32)readU32(data);
 }
 
-inline void writeF1000(u8 *data, f32 i){
-       writeS32(data, i*1000);
-}
-inline f32 readF1000(u8 *data){
-       return (f32)readS32(data)/1000.;
-}
-
 inline void writeS16(u8 *data, s16 i){
        writeU16(data, (u16)i);
 }
@@ -117,6 +111,20 @@ inline s16 readS16(u8 *data){
        return (s16)readU16(data);
 }
 
+inline void writeS8(u8 *data, s8 i){
+       writeU8(data, (u8)i);
+}
+inline s8 readS8(u8 *data){
+       return (s8)readU8(data);
+}
+
+inline void writeF1000(u8 *data, f32 i){
+       writeS32(data, i*1000);
+}
+inline f32 readF1000(u8 *data){
+       return (f32)readS32(data)/1000.;
+}
+
 inline void writeV3S32(u8 *data, v3s32 p)
 {
        writeS32(&data[0], p.X);
@@ -147,6 +155,19 @@ inline v3f readV3F1000(u8 *data)
        return p;
 }
 
+inline void writeV2F1000(u8 *data, v2f p)
+{
+       writeF1000(&data[0], p.X);
+       writeF1000(&data[4], p.Y);
+}
+inline v2f readV2F1000(u8 *data)
+{
+       v2f p;
+       p.X = (float)readF1000(&data[0]);
+       p.Y = (float)readF1000(&data[4]);
+       return p;
+}
+
 inline void writeV2S16(u8 *data, v2s16 p)
 {
        writeS16(&data[0], p.X);
@@ -221,16 +242,68 @@ inline u16 readU16(std::istream &is)
        return readU16((u8*)buf);
 }
 
-inline void writeF1000(std::ostream &os, f32 p)
+inline void writeU32(std::ostream &os, u32 p)
+{
+       char buf[4];
+       writeU32((u8*)buf, p);
+       os.write(buf, 4);
+}
+inline u32 readU32(std::istream &is)
+{
+       char buf[4];
+       is.read(buf, 4);
+       return readU32((u8*)buf);
+}
+
+inline void writeS32(std::ostream &os, s32 p)
+{
+       char buf[4];
+       writeS32((u8*)buf, p);
+       os.write(buf, 4);
+}
+inline s32 readS32(std::istream &is)
+{
+       char buf[4];
+       is.read(buf, 4);
+       return readS32((u8*)buf);
+}
+
+inline void writeS16(std::ostream &os, s16 p)
 {
        char buf[2];
-       writeF1000((u8*)buf, p);
+       writeS16((u8*)buf, p);
        os.write(buf, 2);
 }
-inline f32 readF1000(std::istream &is)
+inline s16 readS16(std::istream &is)
 {
        char buf[2];
        is.read(buf, 2);
+       return readS16((u8*)buf);
+}
+
+inline void writeS8(std::ostream &os, s8 p)
+{
+       char buf[1];
+       writeS8((u8*)buf, p);
+       os.write(buf, 1);
+}
+inline s8 readS8(std::istream &is)
+{
+       char buf[1];
+       is.read(buf, 1);
+       return readS8((u8*)buf);
+}
+
+inline void writeF1000(std::ostream &os, f32 p)
+{
+       char buf[4];
+       writeF1000((u8*)buf, p);
+       os.write(buf, 4);
+}
+inline f32 readF1000(std::istream &is)
+{
+       char buf[4];
+       is.read(buf, 4);
        return readF1000((u8*)buf);
 }
 
@@ -247,6 +320,45 @@ inline v3f readV3F1000(std::istream &is)
        return readV3F1000((u8*)buf);
 }
 
+inline void writeV2F1000(std::ostream &os, v2f p)
+{
+       char buf[8];
+       writeV2F1000((u8*)buf, p);
+       os.write(buf, 8);
+}
+inline v2f readV2F1000(std::istream &is)
+{
+       char buf[8];
+       is.read(buf, 8);
+       return readV2F1000((u8*)buf);
+}
+
+inline void writeV2S16(std::ostream &os, v2s16 p)
+{
+       char buf[4];
+       writeV2S16((u8*)buf, p);
+       os.write(buf, 4);
+}
+inline v2s16 readV2S16(std::istream &is)
+{
+       char buf[4];
+       is.read(buf, 4);
+       return readV2S16((u8*)buf);
+}
+
+inline void writeV3S16(std::ostream &os, v3s16 p)
+{
+       char buf[6];
+       writeV3S16((u8*)buf, p);
+       os.write(buf, 6);
+}
+inline v3s16 readV3S16(std::istream &is)
+{
+       char buf[6];
+       is.read(buf, 6);
+       return readV3S16((u8*)buf);
+}
+
 /*
        None of these are used at the moment
 */
@@ -329,26 +441,59 @@ template <typename T>
 class Buffer
 {
 public:
+       Buffer()
+       {
+               m_size = 0;
+               data = NULL;
+       }
        Buffer(unsigned int size)
        {
                m_size = size;
-               data = new T[size];
+               if(size != 0)
+                       data = new T[size];
+               else
+                       data = NULL;
        }
        Buffer(const Buffer &buffer)
        {
                m_size = buffer.m_size;
-               data = new T[buffer.m_size];
-               memcpy(data, buffer.data, buffer.m_size);
+               if(m_size != 0)
+               {
+                       data = new T[buffer.m_size];
+                       memcpy(data, buffer.data, buffer.m_size);
+               }
+               else
+                       data = NULL;
        }
-       Buffer(T *t, unsigned int size)
+       Buffer(const T *t, unsigned int size)
        {
                m_size = size;
-               data = new T[size];
-               memcpy(data, t, size);
+               if(size != 0)
+               {
+                       data = new T[size];
+                       memcpy(data, t, size);
+               }
+               else
+                       data = NULL;
        }
        ~Buffer()
        {
-               delete[] data;
+               drop();
+       }
+       Buffer& operator=(const Buffer &buffer)
+       {
+               if(this == &buffer)
+                       return *this;
+               drop();
+               m_size = buffer.m_size;
+               if(m_size != 0)
+               {
+                       data = new T[buffer.m_size];
+                       memcpy(data, buffer.data, buffer.m_size);
+               }
+               else
+                       data = NULL;
+               return *this;
        }
        T & operator[](unsigned int i) const
        {
@@ -363,6 +508,11 @@ class Buffer
                return m_size;
        }
 private:
+       void drop()
+       {
+               if(data)
+                       delete[] data;
+       }
        T *data;
        unsigned int m_size;
 };
@@ -371,10 +521,20 @@ template <typename T>
 class SharedBuffer
 {
 public:
+       SharedBuffer()
+       {
+               m_size = 0;
+               data = NULL;
+               refcount = new unsigned int;
+               (*refcount) = 1;
+       }
        SharedBuffer(unsigned int size)
        {
                m_size = size;
-               data = new T[size];
+               if(m_size != 0)
+                       data = new T[m_size];
+               else
+                       data = NULL;
                refcount = new unsigned int;
                (*refcount) = 1;
        }
@@ -404,8 +564,13 @@ class SharedBuffer
        SharedBuffer(T *t, unsigned int size)
        {
                m_size = size;
-               data = new T[size];
-               memcpy(data, t, size);
+               if(m_size != 0)
+               {
+                       data = new T[m_size];
+                       memcpy(data, t, m_size);
+               }
+               else
+                       data = NULL;
                refcount = new unsigned int;
                (*refcount) = 1;
        }
@@ -414,9 +579,14 @@ class SharedBuffer
        */
        SharedBuffer(const Buffer<T> &buffer)
        {
-               m_size = buffer.m_size;
-               data = new T[buffer.getSize()];
-               memcpy(data, *buffer, buffer.getSize());
+               m_size = buffer.getSize();
+               if(m_size != 0)
+               {
+                       data = new T[m_size];
+                       memcpy(data, *buffer, buffer.getSize());
+               }
+               else
+                       data = NULL;
                refcount = new unsigned int;
                (*refcount) = 1;
        }
@@ -426,6 +596,7 @@ class SharedBuffer
        }
        T & operator[](unsigned int i) const
        {
+               //assert(i < m_size)
                return data[i];
        }
        T * operator*() const
@@ -436,6 +607,10 @@ class SharedBuffer
        {
                return m_size;
        }
+       operator Buffer<T>() const
+       {
+               return Buffer<T>(data, m_size);
+       }
 private:
        void drop()
        {
@@ -443,7 +618,8 @@ class SharedBuffer
                (*refcount)--;
                if(*refcount == 0)
                {
-                       delete[] data;
+                       if(data)
+                               delete[] data;
                        delete refcount;
                }
        }
@@ -518,6 +694,46 @@ class TimeTaker
        u32 *m_result;
 };
 
+// Tests if two strings are equal, optionally case insensitive
+inline bool str_equal(const std::wstring& s1, const std::wstring& s2,
+               bool case_insensitive = false)
+{
+       if(case_insensitive)
+       {
+               if(s1.size() != s2.size())
+                       return false;
+               for(size_t i = 0; i < s1.size(); ++i)
+                       if(tolower(s1[i]) != tolower(s2[i]))
+                               return false;
+               return true;
+       }
+       else
+       {
+               return s1 == s2;
+       }
+}
+
+// Tests if the second string is a prefix of the first, optionally case insensitive
+inline bool str_starts_with(const std::wstring& str, const std::wstring& prefix,
+               bool case_insensitive = false)
+{
+       if(str.size() < prefix.size())
+               return false;
+       if(case_insensitive)
+       {
+               for(size_t i = 0; i < prefix.size(); ++i)
+                       if(tolower(str[i]) != tolower(prefix[i]))
+                               return false;
+       }
+       else
+       {
+               for(size_t i = 0; i < prefix.size(); ++i)
+                       if(str[i] != prefix[i])
+                               return false;
+       }
+       return true;
+}
+
 // Calculates the borders of a "d-radius" cube
 inline void getFacePositions(core::list<v3s16> &list, u16 d)
 {
@@ -769,6 +985,35 @@ inline float wrapDegrees(float f)
        return f;
 }
 
+/* Wrap to 0...360 */
+inline float wrapDegrees_0_360(float f)
+{
+       // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
+       // This results in
+       // 10, 720, -1, -361
+       int i = floor(f);
+       // 0, 2, 0, -1
+       int l = i / 360;
+       // Wrap to 0...360
+       // 0, 2, -1, -2
+       if(i < 0)
+               l -= 1;
+       // 0, 720, 0, -360
+       int k = l * 360;
+       // 10, 0.5, -0.5, -0.5
+       f -= float(k);
+       return f;
+}
+
+/* Wrap to -180...180 */
+inline float wrapDegrees_180(float f)
+{
+       f += 180;
+       f = wrapDegrees_0_360(f);
+       f -= 180;
+       return f;
+}
+
 inline std::string lowercase(const std::string &s)
 {
        std::string s2;
@@ -790,7 +1035,7 @@ inline bool is_yes(const std::string &s)
        return false;
 }
 
-inline s32 stoi(const std::string &s, s32 min, s32 max)
+inline s32 mystoi(const std::string &s, s32 min, s32 max)
 {
        s32 i = atoi(s.c_str());
        if(i < min)
@@ -802,27 +1047,33 @@ inline s32 stoi(const std::string &s, s32 min, s32 max)
 
 
 // MSVC2010 includes it's own versions of these
-#if !defined(_MSC_VER) || _MSC_VER < 1600
+//#if !defined(_MSC_VER) || _MSC_VER < 1600
 
-inline s32 stoi(std::string s)
+inline s32 mystoi(const std::string &s)
 {
        return atoi(s.c_str());
 }
 
-inline s32 stoi(std::wstring s)
+inline s32 mystoi(const std::wstring &s)
 {
        return atoi(wide_to_narrow(s).c_str());
 }
 
-inline float stof(std::string s)
+inline float mystof(const std::string &s)
 {
-       float f;
+       // This crap causes a segfault in certain cases on MinGW
+       /*float f;
        std::istringstream ss(s);
        ss>>f;
-       return f;
+       return f;*/
+       // This works in that case
+       return atof(s.c_str());
 }
 
-#endif
+//#endif
+
+#define stoi mystoi
+#define stof mystof
 
 inline std::string itos(s32 i)
 {
@@ -900,547 +1151,6 @@ class SimpleThread : public JThread
        }
 };
 
-/*
-       Config stuff
-*/
-
-enum ValueType
-{
-       VALUETYPE_STRING,
-       VALUETYPE_FLAG // Doesn't take any arguments
-};
-
-struct ValueSpec
-{
-       ValueSpec(ValueType a_type, const char *a_help=NULL)
-       {
-               type = a_type;
-               help = a_help;
-       }
-       ValueType type;
-       const char *help;
-};
-
-class Settings
-{
-public:
-       Settings()
-       {
-               m_mutex.Init();
-       }
-
-       void writeLines(std::ostream &os)
-       {
-               JMutexAutoLock lock(m_mutex);
-               
-               for(core::map<std::string, std::string>::Iterator
-                               i = m_settings.getIterator();
-                               i.atEnd() == false; i++)
-               {
-                       std::string name = i.getNode()->getKey();
-                       std::string value = i.getNode()->getValue();
-                       os<<name<<" = "<<value<<"\n";
-               }
-       }
-
-       bool parseConfigLine(const std::string &line)
-       {
-               JMutexAutoLock lock(m_mutex);
-               
-               std::string trimmedline = trim(line);
-               
-               // Ignore comments
-               if(trimmedline[0] == '#')
-                       return true;
-
-               //dstream<<"trimmedline=\""<<trimmedline<<"\""<<std::endl;
-
-               Strfnd sf(trim(line));
-
-               std::string name = sf.next("=");
-               name = trim(name);
-
-               if(name == "")
-                       return true;
-               
-               std::string value = sf.next("\n");
-               value = trim(value);
-
-               /*dstream<<"Config name=\""<<name<<"\" value=\""
-                               <<value<<"\""<<std::endl;*/
-               
-               m_settings[name] = value;
-               
-               return true;
-       }
-
-       // Returns false on EOF
-       bool parseConfigObject(std::istream &is)
-       {
-               if(is.eof())
-                       return false;
-               
-               /*
-                       NOTE: This function might be expanded to allow multi-line
-                             settings.
-               */
-               std::string line;
-               std::getline(is, line);
-               //dstream<<"got line: \""<<line<<"\""<<std::endl;
-
-               return parseConfigLine(line);
-       }
-
-       /*
-               Read configuration file
-
-               Returns true on success
-       */
-       bool readConfigFile(const char *filename)
-       {
-               std::ifstream is(filename);
-               if(is.good() == false)
-               {
-                       dstream<<"Error opening configuration file \""
-                                       <<filename<<"\""<<std::endl;
-                       return false;
-               }
-
-               dstream<<"Parsing configuration file: \""
-                               <<filename<<"\""<<std::endl;
-                               
-               while(parseConfigObject(is));
-               
-               return true;
-       }
-
-       /*
-               Reads a configuration object from stream (usually a single line)
-               and adds it to dst.
-               
-               Preserves comments and empty lines.
-
-               Settings that were added to dst are also added to updated.
-               key of updated is setting name, value of updated is dummy.
-
-               Returns false on EOF
-       */
-       bool getUpdatedConfigObject(std::istream &is,
-                       core::list<std::string> &dst,
-                       core::map<std::string, bool> &updated)
-       {
-               JMutexAutoLock lock(m_mutex);
-               
-               if(is.eof())
-                       return false;
-               
-               // NOTE: This function will be expanded to allow multi-line settings
-               std::string line;
-               std::getline(is, line);
-
-               std::string trimmedline = trim(line);
-
-               std::string line_end = "";
-               if(is.eof() == false)
-                       line_end = "\n";
-               
-               // Ignore comments
-               if(trimmedline[0] == '#')
-               {
-                       dst.push_back(line+line_end);
-                       return true;
-               }
-
-               Strfnd sf(trim(line));
-
-               std::string name = sf.next("=");
-               name = trim(name);
-
-               if(name == "")
-               {
-                       dst.push_back(line+line_end);
-                       return true;
-               }
-               
-               std::string value = sf.next("\n");
-               value = trim(value);
-               
-               if(m_settings.find(name))
-               {
-                       std::string newvalue = m_settings[name];
-                       
-                       if(newvalue != value)
-                       {
-                               dstream<<"Changing value of \""<<name<<"\" = \""
-                                               <<value<<"\" -> \""<<newvalue<<"\""
-                                               <<std::endl;
-                       }
-
-                       dst.push_back(name + " = " + newvalue + line_end);
-
-                       updated[name] = true;
-               }
-               
-               return true;
-       }
-
-       /*
-               Updates configuration file
-
-               Returns true on success
-       */
-       bool updateConfigFile(const char *filename)
-       {
-               dstream<<"Updating configuration file: \""
-                               <<filename<<"\""<<std::endl;
-               
-               core::list<std::string> objects;
-               core::map<std::string, bool> updated;
-               
-               // Read and modify stuff
-               {
-                       std::ifstream is(filename);
-                       if(is.good() == false)
-                       {
-                               dstream<<"INFO: updateConfigFile():"
-                                               " Error opening configuration file"
-                                               " for reading: \""
-                                               <<filename<<"\""<<std::endl;
-                       }
-                       else
-                       {
-                               while(getUpdatedConfigObject(is, objects, updated));
-                       }
-               }
-               
-               JMutexAutoLock lock(m_mutex);
-               
-               // Write stuff back
-               {
-                       std::ofstream os(filename);
-                       if(os.good() == false)
-                       {
-                               dstream<<"Error opening configuration file"
-                                               " for writing: \""
-                                               <<filename<<"\""<<std::endl;
-                               return false;
-                       }
-                       
-                       /*
-                               Write updated stuff
-                       */
-                       for(core::list<std::string>::Iterator
-                                       i = objects.begin();
-                                       i != objects.end(); i++)
-                       {
-                               os<<(*i);
-                       }
-
-                       /*
-                               Write stuff that was not already in the file
-                       */
-                       for(core::map<std::string, std::string>::Iterator
-                                       i = m_settings.getIterator();
-                                       i.atEnd() == false; i++)
-                       {
-                               if(updated.find(i.getNode()->getKey()))
-                                       continue;
-                               std::string name = i.getNode()->getKey();
-                               std::string value = i.getNode()->getValue();
-                               dstream<<"Adding \""<<name<<"\" = \""<<value<<"\""
-                                               <<std::endl;
-                               os<<name<<" = "<<value<<"\n";
-                       }
-               }
-               
-               return true;
-       }
-
-       /*
-               NOTE: Types of allowed_options are ignored
-
-               returns true on success
-       */
-       bool parseCommandLine(int argc, char *argv[],
-                       core::map<std::string, ValueSpec> &allowed_options)
-       {
-               int i=1;
-               for(;;)
-               {
-                       if(i >= argc)
-                               break;
-                       std::string argname = argv[i];
-                       if(argname.substr(0, 2) != "--")
-                       {
-                               dstream<<"Invalid command-line parameter \""
-                                               <<argname<<"\": --<option> expected."<<std::endl;
-                               return false;
-                       }
-                       i++;
-
-                       std::string name = argname.substr(2);
-
-                       core::map<std::string, ValueSpec>::Node *n;
-                       n = allowed_options.find(name);
-                       if(n == NULL)
-                       {
-                               dstream<<"Unknown command-line parameter \""
-                                               <<argname<<"\""<<std::endl;
-                               return false;
-                       }
-
-                       ValueType type = n->getValue().type;
-
-                       std::string value = "";
-                       
-                       if(type == VALUETYPE_FLAG)
-                       {
-                               value = "true";
-                       }
-                       else
-                       {
-                               if(i >= argc)
-                               {
-                                       dstream<<"Invalid command-line parameter \""
-                                                       <<name<<"\": missing value"<<std::endl;
-                                       return false;
-                               }
-                               value = argv[i];
-                               i++;
-                       }
-                       
-
-                       dstream<<"Valid command-line parameter: \""
-                                       <<name<<"\" = \""<<value<<"\""
-                                       <<std::endl;
-                       set(name, value);
-               }
-
-               return true;
-       }
-
-       void set(std::string name, std::string value)
-       {
-               JMutexAutoLock lock(m_mutex);
-               
-               m_settings[name] = value;
-       }
-
-       void setDefault(std::string name, std::string value)
-       {
-               JMutexAutoLock lock(m_mutex);
-               
-               m_defaults[name] = value;
-       }
-
-       bool exists(std::string name)
-       {
-               JMutexAutoLock lock(m_mutex);
-               
-               return (m_settings.find(name) || m_defaults.find(name));
-       }
-
-       std::string get(std::string name)
-       {
-               JMutexAutoLock lock(m_mutex);
-               
-               core::map<std::string, std::string>::Node *n;
-               n = m_settings.find(name);
-               if(n == NULL)
-               {
-                       n = m_defaults.find(name);
-                       if(n == NULL)
-                       {
-                               dstream<<"INFO: Settings: Setting not found: \""
-                                               <<name<<"\""<<std::endl;
-                               throw SettingNotFoundException("Setting not found");
-                       }
-               }
-
-               return n->getValue();
-       }
-
-       bool getBool(std::string name)
-       {
-               return is_yes(get(name));
-       }
-       
-       bool getFlag(std::string name)
-       {
-               try
-               {
-                       return getBool(name);
-               }
-               catch(SettingNotFoundException &e)
-               {
-                       return false;
-               }
-       }
-
-       // Asks if empty
-       bool getBoolAsk(std::string name, std::string question, bool def)
-       {
-               // If it is in settings
-               if(exists(name))
-                       return getBool(name);
-               
-               std::string s;
-               char templine[10];
-               std::cout<<question<<" [y/N]: ";
-               std::cin.getline(templine, 10);
-               s = templine;
-
-               if(s == "")
-                       return def;
-
-               return is_yes(s);
-       }
-
-       float getFloat(std::string name)
-       {
-               return stof(get(name));
-       }
-
-       u16 getU16(std::string name)
-       {
-               return stoi(get(name), 0, 65535);
-       }
-
-       u16 getU16Ask(std::string name, std::string question, u16 def)
-       {
-               // If it is in settings
-               if(exists(name))
-                       return getU16(name);
-               
-               std::string s;
-               char templine[10];
-               std::cout<<question<<" ["<<def<<"]: ";
-               std::cin.getline(templine, 10);
-               s = templine;
-
-               if(s == "")
-                       return def;
-
-               return stoi(s, 0, 65535);
-       }
-
-       s16 getS16(std::string name)
-       {
-               return stoi(get(name), -32768, 32767);
-       }
-
-       s32 getS32(std::string name)
-       {
-               return stoi(get(name));
-       }
-
-       v3f getV3F(std::string name)
-       {
-               v3f value;
-               Strfnd f(get(name));
-               f.next("(");
-               value.X = stof(f.next(","));
-               value.Y = stof(f.next(","));
-               value.Z = stof(f.next(")"));
-               return value;
-       }
-
-       u64 getU64(std::string name)
-       {
-               u64 value = 0;
-               std::string s = get(name);
-               std::istringstream ss(s);
-               ss>>value;
-               return value;
-       }
-
-       void setBool(std::string name, bool value)
-       {
-               if(value)
-                       set(name, "true");
-               else
-                       set(name, "false");
-       }
-
-       void setS32(std::string name, s32 value)
-       {
-               set(name, itos(value));
-       }
-
-       void setFloat(std::string name, float value)
-       {
-               set(name, ftos(value));
-       }
-
-       void setV3F(std::string name, v3f value)
-       {
-               std::ostringstream os;
-               os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
-               set(name, os.str());
-       }
-
-       void setU64(std::string name, u64 value)
-       {
-               std::ostringstream os;
-               os<<value;
-               set(name, os.str());
-       }
-
-       void clear()
-       {
-               JMutexAutoLock lock(m_mutex);
-               
-               m_settings.clear();
-               m_defaults.clear();
-       }
-
-       Settings & operator+=(Settings &other)
-       {
-               JMutexAutoLock lock(m_mutex);
-               JMutexAutoLock lock2(other.m_mutex);
-               
-               if(&other == this)
-                       return *this;
-
-               for(core::map<std::string, std::string>::Iterator
-                               i = other.m_settings.getIterator();
-                               i.atEnd() == false; i++)
-               {
-                       m_settings.insert(i.getNode()->getKey(),
-                                       i.getNode()->getValue());
-               }
-               
-               for(core::map<std::string, std::string>::Iterator
-                               i = other.m_defaults.getIterator();
-                               i.atEnd() == false; i++)
-               {
-                       m_defaults.insert(i.getNode()->getKey(),
-                                       i.getNode()->getValue());
-               }
-
-       }
-
-       Settings & operator=(Settings &other)
-       {
-               JMutexAutoLock lock(m_mutex);
-               JMutexAutoLock lock2(other.m_mutex);
-               
-               if(&other == this)
-                       return *this;
-
-               clear();
-               (*this) += other;
-               
-               return *this;
-       }
-
-private:
-       core::map<std::string, std::string> m_settings;
-       core::map<std::string, std::string> m_defaults;
-       // All methods that access m_settings/m_defaults directly should lock this.
-       JMutex m_mutex;
-};
-
 /*
        FIFO queue (well, actually a FILO also)
 */
@@ -1701,22 +1411,14 @@ int myrand(void);
 void mysrand(unsigned seed);
 #define MYRAND_MAX 32767
 
-inline int myrand_range(int min, int max)
-{
-       if(min > max)
-       {
-               assert(0);
-               return max;
-       }
-       return (myrand()%(max-min+1))+min;
-}
+int myrand_range(int min, int max);
 
 /*
        Miscellaneous functions
 */
 
-bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
-               f32 *distance_ptr=NULL);
+bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
+               f32 camera_fov, f32 range, f32 *distance_ptr=NULL);
 
 /*
        Queue with unique values with fast checking of value existence
@@ -1906,6 +1608,15 @@ inline std::string wrap_rows(const std::string &from, u32 rowlen)
 #define MYMIN(a,b) ((a)<(b)?(a):(b))
 #define MYMAX(a,b) ((a)>(b)?(a):(b))
 
+/*
+       Returns nearest 32-bit integer for given floating point number.
+       <cmath> and <math.h> in VC++ don't provide round().
+*/
+inline s32 myround(f32 f)
+{
+       return floor(f + 0.5);
+}
+
 /*
        Returns integer position of node in given floating point position
 */
@@ -1949,17 +1660,23 @@ inline std::string serializeString(const std::string &plain)
        return s;
 }
 
-/*// Reads a string with the length as the first two bytes
-inline std::string deSerializeString(const std::string encoded)
+// Creates a string with the length as the first two bytes from wide string
+inline std::string serializeWideString(const std::wstring &plain)
 {
-       u16 s_size = readU16((u8*)&encoded.c_str()[0]);
-       if(s_size > encoded.length() - 2)
-               return "";
+       //assert(plain.size() <= 65535);
+       if(plain.size() > 65535)
+               throw SerializationError("String too long for serializeString");
+       char buf[2];
+       writeU16((u8*)buf, plain.size());
        std::string s;
-       s.reserve(s_size);
-       s.append(&encoded.c_str()[2], s_size);
+       s.append(buf, 2);
+       for(u32 i=0; i<plain.size(); i++)
+       {
+               writeU16((u8*)buf, plain[i]);
+               s.append(buf, 2);
+       }
        return s;
-}*/
+}
 
 // Reads a string with the length as the first two bytes
 inline std::string deSerializeString(std::istream &is)
@@ -1979,6 +1696,27 @@ inline std::string deSerializeString(std::istream &is)
        return s;
 }
 
+// Reads a wide string with the length as the first two bytes
+inline std::wstring deSerializeWideString(std::istream &is)
+{
+       char buf[2];
+       is.read(buf, 2);
+       if(is.gcount() != 2)
+               throw SerializationError("deSerializeString: size not read");
+       u16 s_size = readU16((u8*)buf);
+       if(s_size == 0)
+               return L"";
+       std::wstring s;
+       s.reserve(s_size);
+       for(u32 i=0; i<s_size; i++)
+       {
+               is.read(&buf[0], 2);
+               wchar_t c16 = readU16((u8*)buf);
+               s.append(&c16, 1);
+       }
+       return s;
+}
+
 // Creates a string with the length as the first four bytes
 inline std::string serializeLongString(const std::string &plain)
 {
@@ -1990,18 +1728,6 @@ inline std::string serializeLongString(const std::string &plain)
        return s;
 }
 
-/*// Reads a string with the length as the first four bytes
-inline std::string deSerializeLongString(const std::string encoded)
-{
-       u32 s_size = readU32((u8*)&encoded.c_str()[0]);
-       if(s_size > encoded.length() - 4)
-               return "";
-       std::string s;
-       s.reserve(s_size);
-       s.append(&encoded.c_str()[4], s_size);
-       return s;
-}*/
-
 // Reads a string with the length as the first four bytes
 inline std::string deSerializeLongString(std::istream &is)
 {
@@ -2020,23 +1746,13 @@ inline std::string deSerializeLongString(std::istream &is)
        return s;
 }
 
-//
+// Creates a string encoded in JSON format (almost equivalent to a C string literal)
+std::string serializeJsonString(const std::string &plain);
 
-inline u32 time_to_daynight_ratio(u32 time_of_day)
-{
-       const s32 daylength = 16;
-       const s32 nightlength = 6;
-       const s32 daytimelength = 8;
-       s32 d = daylength;
-       s32 t = (((time_of_day)%24000)/(24000/d));
-       if(t < nightlength/2 || t >= d - nightlength/2)
-               //return 300;
-               return 350;
-       else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
-               return 1000;
-       else
-               return 750;
-}
+// Reads a string encoded in JSON format
+std::string deSerializeJsonString(std::istream &is);
+
+//
 
 // Random helper. Usually d=BS
 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
@@ -2077,6 +1793,73 @@ class IntervalLimiter
        float m_accumulator;
 };
 
+/*
+       Splits a list into "pages". For example, the list [1,2,3,4,5] split
+       into two pages would be [1,2,3],[4,5]. This function computes the
+       minimum and maximum indices of a single page.
+
+       length: Length of the list that should be split
+       page: Page number, 1 <= page <= pagecount
+       pagecount: The number of pages, >= 1
+       minindex: Receives the minimum index (inclusive).
+       maxindex: Receives the maximum index (exclusive).
+
+       Ensures 0 <= minindex <= maxindex <= length.
+*/
+inline void paging(u32 length, u32 page, u32 pagecount, u32 &minindex, u32 &maxindex)
+{
+       if(length < 1 || pagecount < 1 || page < 1 || page > pagecount)
+       {
+               // Special cases or invalid parameters
+               minindex = maxindex = 0;
+       }
+       else if(pagecount <= length)
+       {
+               // Less pages than entries in the list:
+               // Each page contains at least one entry
+               minindex = (length * (page-1) + (pagecount-1)) / pagecount;
+               maxindex = (length * page + (pagecount-1)) / pagecount;
+       }
+       else
+       {
+               // More pages than entries in the list:
+               // Make sure the empty pages are at the end
+               if(page < length)
+               {
+                       minindex = page-1;
+                       maxindex = page;
+               }
+               else
+               {
+                       minindex = 0;
+                       maxindex = 0;
+               }
+       }
+}
+
+std::string translatePassword(std::string playername, std::wstring password);
+
+enum PointedThingType
+{
+       POINTEDTHING_NOTHING,
+       POINTEDTHING_NODE,
+       POINTEDTHING_OBJECT
+};
+
+struct PointedThing
+{
+       PointedThingType type;
+       v3s16 node_undersurface;
+       v3s16 node_abovesurface;
+       s16 object_id;
+
+       PointedThing();
+       std::string dump() const;
+       void serialize(std::ostream &os) const;
+       void deSerialize(std::istream &is);
+       bool operator==(const PointedThing &pt2) const;
+       bool operator!=(const PointedThing &pt2) const;
+};
 
 #endif