#include <fstream>
#include <string>
#include <sstream>
+#include <vector>
#include <jthread.h>
#include <jmutex.h>
#include <jmutexautolock.h>
#include "exceptions.h"
#include "porting.h"
+extern const v3s16 g_6dirs[6];
+
extern const v3s16 g_26dirs[26];
// 26th is (0,0,0)
extern const v3s16 g_27dirs[27];
+inline void writeU64(u8 *data, u64 i)
+{
+ data[0] = ((i>>56)&0xff);
+ data[1] = ((i>>48)&0xff);
+ data[2] = ((i>>40)&0xff);
+ data[3] = ((i>>32)&0xff);
+ data[4] = ((i>>24)&0xff);
+ data[5] = ((i>>16)&0xff);
+ data[6] = ((i>> 8)&0xff);
+ data[7] = ((i>> 0)&0xff);
+}
+
inline void writeU32(u8 *data, u32 i)
{
data[0] = ((i>>24)&0xff);
data[0] = ((i>> 0)&0xff);
}
+inline u64 readU64(u8 *data)
+{
+ return ((u64)data[0]<<56) | ((u64)data[1]<<48)
+ | ((u64)data[2]<<40) | ((u64)data[3]<<32)
+ | ((u64)data[4]<<24) | ((u64)data[5]<<16)
+ | ((u64)data[6]<<8) | ((u64)data[7]<<0);
+}
+
inline u32 readU32(u8 *data)
{
return (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | (data[3]<<0);
return (data[0]<<0);
}
-// Signed variants of the above
-
inline void writeS32(u8 *data, s32 i){
writeU32(data, (u32)i);
}
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);
}
writeS32(&data[4], p.Y);
writeS32(&data[8], p.Z);
}
-
inline v3s32 readV3S32(u8 *data)
{
v3s32 p;
return p;
}
+inline void writeV3F1000(u8 *data, v3f p)
+{
+ writeF1000(&data[0], p.X);
+ writeF1000(&data[4], p.Y);
+ writeF1000(&data[8], p.Z);
+}
+inline v3f readV3F1000(u8 *data)
+{
+ v3f p;
+ p.X = (float)readF1000(&data[0]);
+ p.Y = (float)readF1000(&data[4]);
+ p.Z = (float)readF1000(&data[8]);
+ return p;
+}
+
inline void writeV2S16(u8 *data, v2s16 p)
{
writeS16(&data[0], p.X);
return p;
}
+/*
+ The above stuff directly interfaced to iostream
+*/
+
+inline void writeU8(std::ostream &os, u8 p)
+{
+ char buf[1];
+ writeU8((u8*)buf, p);
+ os.write(buf, 1);
+}
+inline u8 readU8(std::istream &is)
+{
+ char buf[1];
+ is.read(buf, 1);
+ return readU8((u8*)buf);
+}
+
+inline void writeU16(std::ostream &os, u16 p)
+{
+ char buf[2];
+ writeU16((u8*)buf, p);
+ os.write(buf, 2);
+}
+inline u16 readU16(std::istream &is)
+{
+ char buf[2];
+ is.read(buf, 2);
+ return readU16((u8*)buf);
+}
+
+inline void writeU32(std::ostream &os, u16 p)
+{
+ char buf[4];
+ writeU16((u8*)buf, p);
+ os.write(buf, 4);
+}
+inline u16 readU32(std::istream &is)
+{
+ char buf[4];
+ is.read(buf, 4);
+ return readU32((u8*)buf);
+}
+
+inline void writeF1000(std::ostream &os, f32 p)
+{
+ char buf[2];
+ writeF1000((u8*)buf, p);
+ os.write(buf, 2);
+}
+inline f32 readF1000(std::istream &is)
+{
+ char buf[2];
+ is.read(buf, 2);
+ // TODO: verify if this gets rid of the valgrind warning
+ //if(is.gcount() != 2)
+ // return 0;
+ return readF1000((u8*)buf);
+}
+
+inline void writeV3F1000(std::ostream &os, v3f p)
+{
+ char buf[12];
+ writeV3F1000((u8*)buf, p);
+ os.write(buf, 12);
+}
+inline v3f readV3F1000(std::istream &is)
+{
+ char buf[12];
+ is.read(buf, 12);
+ return readV3F1000((u8*)buf);
+}
+
/*
None of these are used at the moment
*/
{
return ptr == t;
}
+ T & operator[](unsigned int i)
+ {
+ return ptr[i];
+ }
private:
void drop()
{
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;
}
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;
}
*/
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;
}
}
T & operator[](unsigned int i) const
{
+ //assert(i < m_size)
return data[i];
}
T * operator*() const
(*refcount)--;
if(*refcount == 0)
{
- delete[] data;
+ if(data)
+ delete[] data;
delete refcount;
}
}
TimeTaker
*/
-class IrrlichtWrapper;
-
class TimeTaker
{
public:
u32 stop(bool quiet=false);
+ u32 getTime();
+
private:
const char *m_name;
u32 m_time1;
);
}
+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 (
);
}
-inline s16 rangelim(s16 i, s16 min, s16 max)
+inline bool isInArea(v3s16 p, v3s16 d)
{
- if(i < min)
- return min;
- if(i > max)
- return max;
- return i;
+ 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 max)
return i;
}
+#define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
+
inline v3s16 arealim(v3s16 p, s16 d)
{
if(p.X < 0)
inline std::wstring narrow_to_wide(const std::string& mbs)
{
size_t wcl = mbs.size();
- SharedBuffer<wchar_t> wcs(wcl+1);
+ Buffer<wchar_t> wcs(wcl+1);
size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
+ if(l == (size_t)(-1))
+ return L"<invalid multibyte string>";
wcs[l] = 0;
return *wcs;
}
size_t mbl = wcs.size()*4;
SharedBuffer<char> mbs(mbl+1);
size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
- if((int)l == -1)
+ if(l == (size_t)(-1))
mbs[0] = 0;
else
mbs[l] = 0;
return *mbs;
}
+// Split a string using the given delimiter. Returns a vector containing
+// the component parts.
+inline std::vector<std::wstring> str_split(const std::wstring &str, wchar_t delimiter)
+{
+ std::vector<std::wstring> parts;
+ std::wstringstream sstr(str);
+ std::wstring part;
+ while(std::getline(sstr, part, delimiter))
+ parts.push_back(part);
+ return parts;
+}
+
+
/*
See test.cpp for example cases.
wraps degrees to the range of -360...360
return i;
}
+
+// MSVC2010 includes it's own versions of these
+#if !defined(_MSC_VER) || _MSC_VER < 1600
+
inline s32 stoi(std::string s)
{
return atoi(s.c_str());
}
+inline s32 stoi(std::wstring s)
+{
+ return atoi(wide_to_narrow(s).c_str());
+}
+
inline float stof(std::string s)
{
float f;
return f;
}
+#endif
+
inline std::string itos(s32 i)
{
std::ostringstream o;
return o.str();
}
+inline void str_replace(std::string & str, std::string const & pattern,
+ std::string const & replacement)
+{
+ std::string::size_type start = str.find(pattern, 0);
+ while(start != str.npos)
+ {
+ str.replace(start, pattern.size(), replacement);
+ start = str.find(pattern, start+replacement.size());
+ }
+}
+
+inline void str_replace_char(std::string & str, char from, char to)
+{
+ for(unsigned int i=0; i<str.size(); i++)
+ {
+ if(str[i] == from)
+ str[i] = to;
+ }
+}
+
/*
A base class for simple background thread implementation
*/
class Settings
{
public:
+ Settings()
+ {
+ m_mutex.Init();
+ }
- // Returns false on EOF
- bool parseConfigObject(std::istream &is)
+ void writeLines(std::ostream &os)
{
- if(is.eof())
- return false;
+ JMutexAutoLock lock(m_mutex);
- // 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)
+ {
+ JMutexAutoLock lock(m_mutex);
+
std::string trimmedline = trim(line);
// Ignore comments
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
core::list<std::string> &dst,
core::map<std::string, bool> &updated)
{
+ JMutexAutoLock lock(m_mutex);
+
if(is.eof())
return false;
std::ifstream is(filename);
if(is.good() == false)
{
- dstream<<"Error opening configuration file"
+ dstream<<"INFO: updateConfigFile():"
+ " Error opening configuration file"
" for reading: \""
<<filename<<"\""<<std::endl;
- return false;
}
-
- while(getUpdatedConfigObject(is, objects, updated));
+ else
+ {
+ while(getUpdatedConfigObject(is, objects, updated));
+ }
}
+ JMutexAutoLock lock(m_mutex);
+
// Write stuff back
{
std::ofstream os(filename);
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");
}
}
bool getBoolAsk(std::string name, std::string question, bool def)
{
// If it is in settings
- if(m_settings.find(name))
+ if(exists(name))
return getBool(name);
std::string s;
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)
u16 getU16Ask(std::string name, std::string question, u16 def)
{
// If it is in settings
- if(m_settings.find(name))
+ if(exists(name))
return getU16(name);
std::string s;
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;
Settings & operator=(Settings &other)
{
+ JMutexAutoLock lock(m_mutex);
+ JMutexAutoLock lock2(other.m_mutex);
+
if(&other == this)
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
+ FIFO queue (well, actually a FILO also)
*/
template<typename T>
class Queue
T pop_front()
{
if(m_list.size() == 0)
- throw ItemNotFoundException("MutexedQueue: queue is empty");
+ throw ItemNotFoundException("Queue: queue is empty");
typename core::list<T>::Iterator begin = m_list.begin();
T t = *begin;
m_list.erase(begin);
return t;
}
+ T pop_back()
+ {
+ if(m_list.size() == 0)
+ throw ItemNotFoundException("Queue: queue is empty");
+
+ typename core::list<T>::Iterator last = m_list.getLast();
+ T t = *last;
+ m_list.erase(last);
+ return t;
+ }
u32 size()
{
};
/*
- Thread-safe FIFO queue
+ Thread-safe FIFO queue (well, actually a FILO also)
*/
template<typename T>
}
u32 size()
{
+ JMutexAutoLock lock(m_mutex);
return m_list.size();
}
void push_back(T t)
wait_time_ms += 10;
}
}
+ T pop_back(u32 wait_time_max_ms=0)
+ {
+ u32 wait_time_ms = 0;
+
+ for(;;)
+ {
+ {
+ JMutexAutoLock lock(m_mutex);
+
+ if(m_list.size() > 0)
+ {
+ typename core::list<T>::Iterator last = m_list.getLast();
+ T t = *last;
+ m_list.erase(last);
+ return t;
+ }
+
+ if(wait_time_ms >= wait_time_max_ms)
+ throw ItemNotFoundException("MutexedQueue: queue is empty");
+ }
+
+ // Wait a while before trying again
+ sleep_ms(10);
+ wait_time_ms += 10;
+ }
+ }
JMutex & getMutex()
{
core::list<T> m_list;
};
+/*
+ A single worker thread - multiple client threads queue framework.
+*/
+
template<typename Caller, typename Data>
class CallerInfo
{
core::list<CallerInfo<Caller, CallerData> > callers;
};
-/*
- Quickhands for typical request-result queues.
- Used for distributing work between threads.
-*/
-
template<typename Key, typename T, typename Caller, typename CallerData>
class RequestQueue
{
void mysrand(unsigned seed);
#define MYRAND_MAX 32767
-/*
- Some kind of a thing that stores attributes related to
- coordinate points
-*/
-
-struct Attribute
+inline int myrand_range(int min, int max)
{
- Attribute()
+ if(max-min > MYRAND_MAX)
{
+ dstream<<"WARNING: myrand_range: max-min > MYRAND_MAX"<<std::endl;
+ assert(0);
}
-
- Attribute(const std::string &value):
- m_value(value)
+ if(min > max)
{
+ assert(0);
+ return max;
}
+ return (myrand()%(max-min+1))+min;
+}
- Attribute(float value)
- {
- m_value = ftos(value);
- }
+/*
+ Miscellaneous functions
+*/
- void set(const std::string &value)
- {
- m_value = value;
- }
-
- std::string get()
- {
- return m_value;
- }
-
- bool getBool()
- {
- return is_yes(get());
- }
+bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
+ f32 *distance_ptr=NULL);
+
+/*
+ Queue with unique values with fast checking of value existence
+*/
+
+template<typename Value>
+class UniqueQueue
+{
+public:
- float getFloat()
+ /*
+ Does nothing if value is already queued.
+ Return value:
+ true: value added
+ false: value already exists
+ */
+ bool push_back(Value value)
{
- float f;
- std::istringstream vis(get());
- vis>>f;
- return f;
- }
+ // Check if already exists
+ if(m_map.find(value) != NULL)
+ return false;
- u16 getU16()
- {
- return stoi(get(), 0, 65535);
+ // Add
+ m_map.insert(value, 0);
+ m_list.push_back(value);
+
+ return true;
}
- s16 getS16()
+ Value pop_front()
{
- return stoi(get(), -32768, 32767);
+ typename core::list<Value>::Iterator i = m_list.begin();
+ Value value = *i;
+ m_map.remove(value);
+ m_list.erase(i);
+ return value;
}
- s32 getS32()
+ u32 size()
{
- return stoi(get());
+ assert(m_list.size() == m_map.size());
+ return m_list.size();
}
- std::string m_value;
+private:
+ core::map<Value, u8> m_map;
+ core::list<Value> m_list;
};
-class PointAttributeList
+#if 1
+template<typename Key, typename Value>
+class MutexedMap
{
- struct PointWithAttr
- {
- v2s16 p;
- Attribute attr;
- };
-
public:
- ~PointAttributeList()
+ MutexedMap()
{
+ m_mutex.Init();
+ assert(m_mutex.IsInitialized());
}
-
- Attribute getNearAttr(v2s16 p)
+
+ void set(const Key &name, const Value &value)
{
- core::list<PointWithAttr>::Iterator
- nearest_i = m_points.end();
- s16 nearest_d = 32767;
- for(core::list<PointWithAttr>::Iterator
- i = m_points.begin();
- i != m_points.end(); i++)
- {
- PointWithAttr &pwa = *i;
- s16 d = pwa.p.getDistanceFrom(p);
- if(d < nearest_d)
- {
- nearest_i = i;
- nearest_d = d;
- }
- }
-
- if(nearest_i == m_points.end())
- Attribute();
+ JMutexAutoLock lock(m_mutex);
- return nearest_i->attr;
+ m_values[name] = value;
}
- Attribute getNearAttr(v3s16 p)
+ bool get(const Key &name, Value *result)
{
- return getNearAttr(v2s16(p.X, p.Z));
+ JMutexAutoLock lock(m_mutex);
+
+ typename core::map<Key, Value>::Node *n;
+ n = m_values.find(name);
+
+ if(n == NULL)
+ return false;
+
+ if(result != NULL)
+ *result = n->getValue();
+
+ return true;
}
- bool empty()
+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()
{
- return (m_points.size() == 0);
+ m_mutex.Init();
+ assert(m_mutex.IsInitialized());
}
- /*
- Take all points in range, or at least the nearest point,
- and interpolate the values as floats
- */
- float getInterpolatedFloat(v2s16 p);
-
- float getInterpolatedFloat(v3s16 p)
+ // Returns true if found
+ bool getValue(u32 id, T &value)
{
- return getInterpolatedFloat(v2s16(p.X, p.Z));
+ 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;
}
- void addPoint(v2s16 p, const Attribute &attr)
- {
- PointWithAttr pattr;
- pattr.p = p;
- pattr.attr = attr;
- m_points.push_back(pattr);
- }
-
- void addPoint(v3s16 p, const Attribute &attr)
+ // If id exists for value, returns the id.
+ // Otherwise generates an id for the value.
+ u32 getId(const T &value)
{
- addPoint(v2s16(p.X, p.Z), attr);
+ 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:
- core::list<PointWithAttr> m_points;
+ 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;
};
/*
- Basically just a wrapper to core::map<PointAttributeList*>
+ Checks if a string contains only supplied characters
*/
-
-class PointAttributeDatabase
+inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
{
-public:
- ~PointAttributeDatabase()
+ for(u32 i=0; i<s.size(); i++)
{
- for(core::map<std::string, PointAttributeList*>::Iterator
- i = m_lists.getIterator();
- i.atEnd() == false; i++)
+ bool confirmed = false;
+ for(u32 j=0; j<allowed_chars.size(); j++)
{
- delete i.getNode()->getValue();
+ if(s[i] == allowed_chars[j])
+ {
+ confirmed = true;
+ break;
+ }
}
+ if(confirmed == false)
+ return false;
}
+ return true;
+}
- PointAttributeList *getList(const std::string &name)
+/*
+ Forcefully wraps string into rows using \n
+ (no word wrap, used for showing paths in gui)
+*/
+inline std::string wrap_rows(const std::string &from, u32 rowlen)
+{
+ std::string to;
+ for(u32 i=0; i<from.size(); i++)
{
- PointAttributeList *list = NULL;
-
- core::map<std::string, PointAttributeList*>::Node *n;
- n = m_lists.find(name);
-
- if(n == NULL)
- {
- list = new PointAttributeList();
- m_lists.insert(name, list);
- }
- else
- {
- list = n->getValue();
- }
-
- return list;
+ if(i != 0 && i%rowlen == 0)
+ to += '\n';
+ to += from[i];
}
-private:
- core::map<std::string, PointAttributeList*> m_lists;
-};
+ return to;
+}
/*
- Miscellaneous functions
+ Some helper stuff
*/
+#define MYMIN(a,b) ((a)<(b)?(a):(b))
+#define MYMAX(a,b) ((a)>(b)?(a):(b))
-bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range);
+/*
+ Returns integer position of node in given floating point position
+*/
+inline v3s16 floatToInt(v3f p, f32 d)
+{
+ v3s16 p2(
+ (p.X + (p.X>0 ? d/2 : -d/2))/d,
+ (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
+ (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
+ return p2;
+}
/*
- Queue with unique values with fast checking of value existence
+ Returns floating point position of node in given integer position
*/
+inline v3f intToFloat(v3s16 p, f32 d)
+{
+ v3f p2(
+ (f32)p.X * d,
+ (f32)p.Y * d,
+ (f32)p.Z * d
+ );
+ return p2;
+}
-template<typename Value>
-class UniqueQueue
+/*
+ More serialization stuff
+*/
+
+// Creates a string with the length as the first two bytes
+inline std::string serializeString(const std::string &plain)
{
-public:
+ //assert(plain.size() <= 65535);
+ if(plain.size() > 65535)
+ throw SerializationError("String too long for serializeString");
+ char buf[2];
+ writeU16((u8*)&buf[0], plain.size());
+ std::string s;
+ s.append(buf, 2);
+ s.append(plain);
+ return s;
+}
+
+// Creates a string with the length as the first two bytes from wide string
+inline std::string serializeWideString(const std::wstring &plain)
+{
+ //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.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)
+{
+ 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 "";
+ Buffer<char> buf2(s_size);
+ is.read(&buf2[0], s_size);
+ std::string s;
+ s.reserve(s_size);
+ s.append(&buf2[0], s_size);
+ 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)
+{
+ char buf[4];
+ writeU32((u8*)&buf[0], plain.size());
+ std::string s;
+ s.append(buf, 4);
+ s.append(plain);
+ return s;
+}
+
+// Reads a string with the length as the first four bytes
+inline std::string deSerializeLongString(std::istream &is)
+{
+ char buf[4];
+ is.read(buf, 4);
+ if(is.gcount() != 4)
+ throw SerializationError("deSerializeLongString: size not read");
+ u32 s_size = readU32((u8*)buf);
+ if(s_size == 0)
+ return "";
+ Buffer<char> buf2(s_size);
+ is.read(&buf2[0], s_size);
+ std::string s;
+ s.reserve(s_size);
+ s.append(&buf2[0], s_size);
+ return s;
+}
+
+//
+
+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;
+}
+
+// Random helper. Usually d=BS
+inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
+{
+ return core::aabbox3d<f32>(
+ (float)p.X * d - 0.5*d,
+ (float)p.Y * d - 0.5*d,
+ (float)p.Z * d - 0.5*d,
+ (float)p.X * d + 0.5*d,
+ (float)p.Y * d + 0.5*d,
+ (float)p.Z * d + 0.5*d
+ );
+}
+class IntervalLimiter
+{
+public:
+ IntervalLimiter():
+ m_accumulator(0)
+ {
+ }
/*
- Does nothing if value is already queued.
- Return value:
- true: value added
- false: value already exists
+ dtime: time from last call to this method
+ wanted_interval: interval wanted
+ return value:
+ true: action should be skipped
+ false: action should be done
*/
- bool push_back(Value value)
+ bool step(float dtime, float wanted_interval)
{
- // Check if already exists
- if(m_map.find(value) != NULL)
+ m_accumulator += dtime;
+ if(m_accumulator < wanted_interval)
return false;
-
- // Add
- m_map.insert(value, 0);
- m_list.push_back(value);
-
+ m_accumulator -= wanted_interval;
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;
+protected:
+ float m_accumulator;
};
+std::string translatePassword(std::string playername, std::wstring password);
+
#endif