minetest-mapper-cpp/BlockPos.cpp

135 lines
3.1 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <BlockPos.h>
void BlockPos::operator=(const std::string &s)
{
m_id = INT64_MIN;
std::istringstream is(s);
if (isdigit(is.peek()) || is.peek() == '-' || is.peek() == '+') {
int64_t ipos;
is >> ipos;
if (is.fail() || !is.eof()) {
throw std::runtime_error(std::string("Failed to decode i64 (minetest) coordinate string from database (") + s + ")" );
}
operator=(ipos);
m_strFormat = I64;
}
else if (is.peek() == 'a') {
// Freeminer new format (a<x>,<y>,<z>)
char c1, c2;
is >> c1;
is >> x();
is >> c1;
is >> y();
is >> c2;
is >> z();
if (is.fail() || !is.eof() || c1 != ',' || c2 != ',') {
throw std::runtime_error(std::string("Failed to decode axyz (freeminer) coordinate string from database (") + s + ")" );
}
m_strFormat = AXYZ;
}
else {
throw std::runtime_error(std::string("Failed to detect format of coordinate string from database (") + s + ")" );
}
}
std::string BlockPos::databasePosStrFmt(StrFormat format) const
{
std::ostringstream os;
switch(format) {
case Unknown:
throw std::runtime_error(std::string("Internal error: Converting BlockPos to unknown string type"));
break;
case I64:
os << databasePosI64();
break;
case XYZ:
os << x() << ',' << y() << ',' << z();
break;
case AXYZ:
os << 'a' << x() << ',' << y() << ',' << z();
break;
case STRFORMAT_MAX:
break;
}
return os.str();
}
void BlockPosIterator::printState(const char *message, FILE *file)
{
fprintf(file, "[%s] Value: %d,%d,%d; Range: %d,%d,%d .. %d,%d,%d; State: %d\n",
message,
m_value.x(), m_value.y(), m_value.z(),
m_start.x(), m_start.y(), m_start.z(),
m_end.x(), m_end.y(), m_end.z(),
m_state);
}
void BlockPosIterator::breakDim(int i, int step)
{
if (!step) return;
if (i == 0) {
m_value.dimension[1] = step < 0 ? m_start.dimension[1] : m_end.dimension[1];
m_value.dimension[0] = step < 0 ? m_start.dimension[0] : m_end.dimension[0];
}
else if (i == 1) {
m_value.dimension[1] = step < 0 ? m_start.dimension[1] : m_end.dimension[1];
}
else if (i == 2) {
m_value.dimension[1] = step < 0 ? m_start.dimension[1] : m_end.dimension[1];
m_value.dimension[0] = step < 0 ? m_start.dimension[0] : m_end.dimension[0];
m_value.dimension[2] = step < 2 ? m_start.dimension[2] : m_end.dimension[2];
}
}
void BlockPosIterator::stepForward(void)
{
switch (m_state) {
case Start:
m_state = Middle;
m_value = m_start;
break;
case End:
break;
case Middle:
stepDim(1, 1)
|| stepDim(0, 1)
|| stepDim(2, 1)
|| (m_state = End);
break;
default:
throw std::runtime_error("Internal error: BlockPosIterator: unexpected state");
}
}
void BlockPosIterator::stepReverse(void)
{
switch (m_state) {
case Start:
break;
case End:
m_state = Middle;
m_value = m_end;
break;
case Middle:
stepDim(1, -1)
|| stepDim(0, -1)
|| stepDim(2, -1)
|| (m_state = Start);
break;
default:
throw std::runtime_error("Internal error: BlockPosIterator: unexpected state");
}
}
size_t NodeCoord::hash(void) const
{
size_t hash = 0xd3adb33f;
for (int i=0; i<3; i++)
// Nothing too fancy...
hash = ((hash << 8) | (hash >> 24)) ^ (dimension[i] ^ (isBlock[i] ? 0x50000000 : 0));
return hash;
}