#include <fstream>
#include <string>
#include <sstream>
+#include <vector>
#include <jthread.h>
#include <jmutex.h>
#include <jmutexautolock.h>
+#include <cstring>
#include "common_irrlicht.h"
#include "debug.h"
return readU16((u8*)buf);
}
+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 writeF1000(std::ostream &os, f32 p)
{
- char buf[2];
+ char buf[4];
writeF1000((u8*)buf, p);
- os.write(buf, 2);
+ os.write(buf, 4);
}
inline f32 readF1000(std::istream &is)
{
- char buf[2];
- is.read(buf, 2);
+ char buf[4];
+ is.read(buf, 4);
return readF1000((u8*)buf);
}
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
{
return m_size;
}
private:
+ void drop()
+ {
+ if(data)
+ delete[] data;
+ }
T *data;
unsigned int m_size;
};
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
{
return m_size;
}
+ operator Buffer<T>() const
+ {
+ return Buffer<T>(data, m_size);
+ }
private:
void drop()
{
(*refcount)--;
if(*refcount == 0)
{
- delete[] data;
+ if(data)
+ delete[] data;
delete refcount;
}
}
u32 *m_result;
};
+#ifndef SERVER
+// Sets the color of all vertices in the mesh
+void setMeshVerticesColor(scene::IMesh* mesh, video::SColor& color);
+#endif
+
// Calculates the borders of a "d-radius" cube
inline void getFacePositions(core::list<v3s16> &list, u16 d)
{
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 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;
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;
}
};
-/*
- 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)
*/
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
core::list<Value> m_list;
};
-#if 0
+#if 1
template<typename Key, typename Value>
-class MutexedCache
+class MutexedMap
{
public:
- MutexedCache()
+ MutexedMap()
{
m_mutex.Init();
assert(m_mutex.IsInitialized());
if(n == NULL)
return false;
-
- *result = n->getValue();
+
+ if(result != NULL)
+ *result = n->getValue();
+
return true;
}
// Creates a string with the length as the first two bytes
inline std::string serializeString(const std::string &plain)
{
- assert(plain.size() <= 65535);
+ //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;
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)
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)
{
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)
{
s32 d = daylength;
s32 t = (((time_of_day)%24000)/(24000/d));
if(t < nightlength/2 || t >= d - nightlength/2)
- return 300;
+ //return 300;
+ return 350;
else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
return 1000;
else
float m_accumulator;
};
+std::string translatePassword(std::string playername, std::wstring password);
#endif