Add BlockPos type and Math.h

This commit is contained in:
DankParrot 2020-08-03 18:39:09 -07:00
parent 5e425e402f
commit 7c5beda081
6 changed files with 93 additions and 1 deletions

View File

@ -1,5 +1,7 @@
#pragma once
#include "util/Math.h"
#include "logging/Logger.h"
constexpr unsigned long long operator"" KB(unsigned long long l)

View File

@ -1,6 +1,7 @@
#pragma once
#include "util/ByteUtil.h"
#include "Types.h"
#include <cstdint>
#include <cstring>
@ -71,6 +72,11 @@ namespace Feather
WriteString(string.c_str(), string.length());
}
inline void WritePosition(BlockPos pos)
{
Write<int64_t>(pos.Encode());
}
inline void Finalize()
{
PrependVarIntSize();

View File

@ -1,5 +1,6 @@
#pragma once
#include "Common.h"
#include "util/ByteUtil.h"
#include <cstdint>
@ -19,4 +20,36 @@ namespace Feather
.data = { ReverseBytes(uuid.data[0]), ReverseBytes(uuid.data[1]) }
};
}
struct BlockPos
{
int32_t x, y, z;
BlockPos(int32_t x, int32_t y, int32_t z) : x(x), y(y), z(z) {}
inline int64_t Encode()
{
int64_t l = 0;
l |= ((long)x & PACKED_X_MASK) << X_OFFSET;
l |= ((long)y & PACKED_Y_MASK) << Y_OFFSET;
l |= ((long)z & PACKED_Z_MASK) << Z_OFFSET;
return l;
}
private:
// X: 26 bits, Z: 26 bits, Y: 12 bits
static const int PACKED_X_LENGTH = 1 + Math::CeilLog2(Math::RoundToPowerOf2(30000000)); // should be 26
static const int PACKED_Z_LENGTH = PACKED_X_LENGTH; // same as X
static const int PACKED_Y_LENGTH = 64 - PACKED_X_LENGTH - PACKED_Z_LENGTH; // should be 12
static const int64_t PACKED_X_MASK = (1 << PACKED_X_LENGTH) - 1;
static const int64_t PACKED_Y_MASK = (1 << PACKED_Y_LENGTH) - 1;
static const int64_t PACKED_Z_MASK = (1 << PACKED_Z_LENGTH) - 1;
// order is X Z Y
static const int Y_OFFSET = 0;
static const int Z_OFFSET = PACKED_Y_LENGTH;
static const int X_OFFSET = PACKED_Y_LENGTH + PACKED_Z_LENGTH;
};
}

View File

@ -45,9 +45,10 @@ def get_type_size(type):
count = extract_array_count(type)
type = extract_array_type(type)
# TODO: encode type sizes in Hjson data
if type == 'varint':
return varint_max_size
elif type == 'int64' or type == 'uint64' or type == 'double':
elif type == 'int64' or type == 'uint64' or type == 'double' or type == 'position':
return 8
elif type == 'int32' or type == 'uint32' or type == 'float':
return 4
@ -81,6 +82,8 @@ def get_rw_func(primitiveType, aliasedType, read):
return '{}VarInt<{}>'.format(prefix, primitiveType)
elif aliasedType == 'string':
return '{}String'.format(prefix)
elif aliasedType == 'position':
return '{}Position'.format(prefix)
else:
return '{}<{}>'.format(prefix, primitiveType)

View File

@ -11,6 +11,7 @@
varint : int32_t
string : std::string
uuid : MinecraftUUID
position: BlockPos
uint64 : uint64_t
int64 : int64_t

47
src/util/Math.h Normal file
View File

@ -0,0 +1,47 @@
#pragma once
#include <cstdint>
namespace Feather::Math
{
// de Bruijn Sequence: B(2, 5) = 00000111011111001011010100110001. Contains all 32 distinct 5-bit strings.
constexpr uint32_t DE_BRUIJN_SEQ = 0x077CB531U;
constexpr int MULTIPLY_DE_BRUIJN_BIT_POSITION[32] = {0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9};
// Is x a power of two?
inline constexpr bool IsPowerOf2(int x)
{
return x != 0 && (x & (x - 1)) == 0;
}
// Smallest number 2^z that is greater than or equal to x
// Precondition: x > 0
inline constexpr int RoundToPowerOf2(int x)
{
x--;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return x + 1;
}
inline constexpr int CeilLog2(int x)
{
// Ensure x is power of 2
x = IsPowerOf2(x) ? x : RoundToPowerOf2(x);
// The de Bruijn sequence contains all 32 distinct 5-bit strings
// 27 is 32 - 5 and 0x1F (31) is the lower 5 bits 0001 1111
return MULTIPLY_DE_BRUIJN_BIT_POSITION[(int)((int64_t)x * DE_BRUIJN_SEQ >> 27) & 0x1F];
}
// log base 2
inline constexpr int Log2(int x)
{
return CeilLog2(x) - (IsPowerOf2(x) ? 0 : 1);
}
}