some tweaking
[oweals/minetest.git] / src / utility.h
index 28cc95ddd7b0eb847ca6f6b5ac3be51daf818373..cc69099b43abeee1f47bc78734a6d9b8391cabab 100644 (file)
@@ -36,6 +36,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 extern const v3s16 g_26dirs[26];
 
+// 26th is (0,0,0)
+extern const v3s16 g_27dirs[27];
+
 inline void writeU32(u8 *data, u32 i)
 {
        data[0] = ((i>>24)&0xff);
@@ -204,6 +207,10 @@ public:
        {
                return ptr == t;
        }
+       T & operator[](unsigned int i)
+       {
+               return ptr[i];
+       }
 private:
        void drop()
        {
@@ -406,6 +413,8 @@ public:
 
        u32 stop(bool quiet=false);
 
+       u32 getTime();
+
 private:
        const char *m_name;
        u32 m_time1;
@@ -533,6 +542,23 @@ inline v3s16 getContainerPos(v3s16 p, s16 d)
        );
 }
 
+inline v2s16 getContainerPos(v2s16 p, v2s16 d)
+{
+       return v2s16(
+               getContainerPos(p.X, d.X),
+               getContainerPos(p.Y, d.Y)
+       );
+}
+
+inline v3s16 getContainerPos(v3s16 p, v3s16 d)
+{
+       return v3s16(
+               getContainerPos(p.X, d.X),
+               getContainerPos(p.Y, d.Y),
+               getContainerPos(p.Z, d.Z)
+       );
+}
+
 inline bool isInArea(v3s16 p, s16 d)
 {
        return (
@@ -550,6 +576,15 @@ inline bool isInArea(v2s16 p, s16 d)
        );
 }
 
+inline bool isInArea(v3s16 p, v3s16 d)
+{
+       return (
+               p.X >= 0 && p.X < d.X &&
+               p.Y >= 0 && p.Y < d.Y &&
+               p.Z >= 0 && p.Z < d.Z
+       );
+}
+
 inline s16 rangelim(s16 i, s16 min, s16 max)
 {
        if(i < min)
@@ -646,7 +681,7 @@ inline std::string lowercase(const std::string &s)
 inline bool is_yes(const std::string &s)
 {
        std::string s2 = lowercase(trim(s));
-       if(s2 == "y" || s2 == "yes" || s2 == "true")
+       if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
                return true;
        return false;
 }
@@ -666,6 +701,14 @@ inline s32 stoi(std::string s)
        return atoi(s.c_str());
 }
 
+inline float stof(std::string s)
+{
+       float f;
+       std::istringstream ss(s);
+       ss>>f;
+       return f;
+}
+
 inline std::string itos(s32 i)
 {
        std::ostringstream o;
@@ -747,17 +790,20 @@ class Settings
 {
 public:
 
-       // Returns false on EOF
-       bool parseConfigObject(std::istream &is)
+       void writeLines(std::ostream &os)
        {
-               if(is.eof())
-                       return false;
-               
-               // NOTE: This function will be expanded to allow multi-line settings
-               std::string line;
-               std::getline(is, line);
-               //dstream<<"got line: \""<<line<<"\""<<std::endl;
+               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)
+       {
                std::string trimmedline = trim(line);
                
                // Ignore comments
@@ -777,14 +823,31 @@ public:
                std::string value = sf.next("\n");
                value = trim(value);
 
-               dstream<<"Config name=\""<<name<<"\" value=\""
-                               <<value<<"\""<<std::endl;
+               /*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
 
@@ -1076,10 +1139,7 @@ public:
 
        float getFloat(std::string name)
        {
-               float f;
-               std::istringstream vis(get(name));
-               vis>>f;
-               return f;
+               return stof(get(name));
        }
 
        u16 getU16(std::string name)
@@ -1115,6 +1175,34 @@ public:
                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;
+       }
+
+       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 clear()
        {
                m_settings.clear();
@@ -1384,6 +1472,16 @@ 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;
+}
+
 /*
        Some kind of a thing that stores attributes related to
        coordinate points
@@ -1450,23 +1548,16 @@ class PointAttributeList
 {
        struct PointWithAttr
        {
-               v3s16 p;
+               v2s16 p;
                Attribute attr;
        };
 
 public:
        ~PointAttributeList()
        {
-               /*for(core::list<PointWithAttr>::Iterator
-                               i = m_points.begin();
-                               i != m_points.end(); i++)
-               {
-                       PointWithAttr &pwa = *i;
-                       //delete pwa.attr;
-               }*/
        }
 
-       Attribute getNearAttr(v3s16 p)
+       Attribute getNearAttr(v2s16 p)
        {
                core::list<PointWithAttr>::Iterator
                                nearest_i = m_points.end();
@@ -1490,9 +1581,9 @@ public:
                return nearest_i->attr;
        }
        
-       Attribute getNearAttr(v2s16 p)
+       Attribute getNearAttr(v3s16 p)
        {
-               return getNearAttr(v3s16(p.X, 0, p.Y));
+               return getNearAttr(v2s16(p.X, p.Z));
        }
 
        bool empty()
@@ -1504,20 +1595,14 @@ public:
                Take all points in range, or at least the nearest point,
                and interpolate the values as floats
        */
-       float getInterpolatedFloat(v3s16 p);
+       float getInterpolatedFloat(v2s16 p);
        
-       float getInterpolatedFloat(v2s16 p)
+       float getInterpolatedFloat(v3s16 p)
        {
-               return getInterpolatedFloat(v3s16(p.X, 0, p.Y));
+               return getInterpolatedFloat(v2s16(p.X, p.Z));
        }
        
-       //float getInterpolatedFloat(v3s16 p, s32 range);
-       /*float getInterpolatedFloat(v2s16 p, s32 range)
-       {
-               return getInterpolatedFloat(v3s16(p.X, 0, p.Y), range);
-       }*/
-       
-       void addPoint(v3s16 p, const Attribute &attr)
+       void addPoint(v2s16 p, const Attribute &attr)
        {
                PointWithAttr pattr;
                pattr.p = p;
@@ -1525,9 +1610,9 @@ public:
                m_points.push_back(pattr);
        }
 
-       void addPoint(v2s16 p, const Attribute &attr)
+       void addPoint(v3s16 p, const Attribute &attr)
        {
-               addPoint(v3s16(p.X, 0, p.Y), attr);
+               addPoint(v2s16(p.X, p.Z), attr);
        }
 
 private:
@@ -1574,5 +1659,175 @@ private:
        core::map<std::string, PointAttributeList*> m_lists;
 };
 
+/*
+       Miscellaneous functions
+*/
+
+bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range);
+
+/*
+       Queue with unique values with fast checking of value existence
+*/
+
+template<typename Value>
+class UniqueQueue
+{
+public:
+       
+       /*
+               Does nothing if value is already queued.
+               Return value:
+                       true: value added
+                       false: value already exists
+       */
+       bool push_back(Value value)
+       {
+               // Check if already exists
+               if(m_map.find(value) != NULL)
+                       return false;
+
+               // Add
+               m_map.insert(value, 0);
+               m_list.push_back(value);
+               
+               return true;
+       }
+
+       Value pop_front()
+       {
+               typename core::list<Value>::Iterator i = m_list.begin();
+               Value value = *i;
+               m_map.remove(value);
+               m_list.erase(i);
+               return value;
+       }
+
+       u32 size()
+       {
+               assert(m_list.size() == m_map.size());
+               return m_list.size();
+       }
+
+private:
+       core::map<Value, u8> m_map;
+       core::list<Value> m_list;
+};
+
+#if 0
+template<typename Key, typename Value>
+class MutexedCache
+{
+public:
+       MutexedCache()
+       {
+               m_mutex.Init();
+               assert(m_mutex.IsInitialized());
+       }
+       
+       void set(const Key &name, const Value &value)
+       {
+               JMutexAutoLock lock(m_mutex);
+
+               m_values[name] = value;
+       }
+       
+       bool get(const Key &name, Value *result)
+       {
+               JMutexAutoLock lock(m_mutex);
+
+               typename core::map<Key, Value>::Node *n;
+               n = m_values.find(name);
+
+               if(n == NULL)
+                       return false;
+
+               *result = n->getValue();
+               return true;
+       }
+
+private:
+       core::map<Key, Value> m_values;
+       JMutex m_mutex;
+};
+#endif
+
+/*
+       Generates ids for comparable values.
+       Id=0 is reserved for "no value".
+
+       Is fast at:
+       - Returning value by id (very fast)
+       - Returning id by value
+       - Generating a new id for a value
+
+       Is not able to:
+       - Remove an id/value pair (is possible to implement but slow)
+*/
+template<typename T>
+class MutexedIdGenerator
+{
+public:
+       MutexedIdGenerator()
+       {
+               m_mutex.Init();
+               assert(m_mutex.IsInitialized());
+       }
+       
+       // Returns true if found
+       bool getValue(u32 id, T &value)
+       {
+               if(id == 0)
+                       return false;
+               JMutexAutoLock lock(m_mutex);
+               if(m_id_to_value.size() < id)
+                       return false;
+               value = m_id_to_value[id-1];
+               return true;
+       }
+       
+       // If id exists for value, returns the id.
+       // Otherwise generates an id for the value.
+       u32 getId(const T &value)
+       {
+               JMutexAutoLock lock(m_mutex);
+               typename core::map<T, u32>::Node *n;
+               n = m_value_to_id.find(value);
+               if(n != NULL)
+                       return n->getValue();
+               m_id_to_value.push_back(value);
+               u32 new_id = m_id_to_value.size();
+               m_value_to_id.insert(value, new_id);
+               return new_id;
+       }
+
+private:
+       JMutex m_mutex;
+       // Values are stored here at id-1 position (id 1 = [0])
+       core::array<T> m_id_to_value;
+       core::map<T, u32> m_value_to_id;
+};
+
+/*
+       Checks if a string contains only supplied characters
+*/
+inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
+{
+       for(u32 i=0; i<s.size(); i++)
+       {
+               bool confirmed = false;
+               for(u32 j=0; j<allowed_chars.size(); j++)
+               {
+                       if(s[i] == allowed_chars[j])
+                       {
+                               confirmed = true;
+                               break;
+                       }
+               }
+               if(confirmed == false)
+                       return false;
+       }
+       return true;
+}
+
 #endif