Created
March 31, 2022 21:50
-
-
Save MajsterTynek/388cf80835746d6156e69b5498fff9c6 to your computer and use it in GitHub Desktop.
Unofficial specification of Baritone Cache Region file format. (*.bcr) Check 'BcrFileFormatSpec.txt' as it explains the layout and meaning of values. Included example programs in C++20 that unpack ('bcr-gun') and parse ('bcr-parse') data contained within a single 'bcr' file. I had to port some things to mimic Java and Baritone behaviours. Those …
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Here are stored functions that | |
* mimic Baritone and Java internals | |
* just to simplify the converter*/ | |
// baritone.utils.pathing.PathingBlockType | |
enum PathingBlockType {AIR, WATER, AVOID, SOLID}; | |
// Base values used you need to know: | |
#define CACHED_REGION_MAGIC 0x1B2E5B7E // 456022910 BE! | |
#define CHUNK_NOT_PRESENT 0 | |
#define CHUNK_PRESENT 1 | |
// Bitset size for cache used by single chunk | |
#define BITS_PER_CHUNK 131072 | |
#define BYTES_PER_CHUNK 16384 | |
#define WORDS_PER_CHUNK 2048 | |
/// Returns the raw bitset index of the specified position | |
inline int getPosIdx(int x, int y, int z){ | |
return (x << 1) | (z << 5) | (y << 9); | |
} | |
/// Metadata of 0 for liquids means source | |
inline bool possiblyFlowing(char source){ | |
return source != 0; | |
} | |
/// Check if slab occupies lower block half | |
inline bool isBottomSlab(char slab){ | |
return !(slab & 8); | |
} | |
/* BitSets are packed into arrays of "words." Currently a word is | |
* a long, which consists of 64 bits, requiring 6 address bits. | |
* The choice of word size is determined purely by performance concerns. */ | |
#define ADDRESS_BITS_PER_WORD 6 | |
#define BITS_PER_WORD (1 << ADDRESS_BITS_PER_WORD) | |
#define BIT_INDEX_MASK (BITS_PER_WORD - 1) | |
// Used to shift left or right for a partial word mask */ | |
#define WORD_MASK 0xffffffffffffffffL | |
/// Returns index of long integer that stores our bit | |
inline int wordIndex(int bitIndex){ | |
return bitIndex >> ADDRESS_BITS_PER_WORD; | |
} | |
/// Returns memory chunk that can store specified number of bits | |
inline long long *newBitset(int nbits){ | |
return new long long[wordIndex(nbits - 1) + 1](); | |
} | |
/// Sets a bit in a BitSet mimicking Java way | |
inline void set(long long *bitset, int bitIndex){ | |
bitset[wordIndex(bitIndex)] |= 1L << (077 & bitIndex); | |
} | |
/// Clears a bit in a BitSet mimicking Java way | |
inline void clear(long long *bitset, int bitIndex){ | |
bitset[wordIndex(bitIndex)] &= ~(1L << (077 & bitIndex)); | |
} | |
/// Flips bit value at specified bit position | |
inline void flip(long long *bitset, int bitIndex, bool v){ | |
bitset[wordIndex(bitIndex)] ^= (1L << (077 & bitIndex)); | |
} | |
/// Sets new bit value at specified bit position | |
inline void change(long long *bitset, int bitIndex, bool v){ | |
v ? set(bitset, bitIndex) : clear(bitset, bitIndex); | |
} | |
/// Just in case we need to know a bot value | |
inline bool get(long long *bitset, int bitIndex){ | |
return bitset[wordIndex(bitIndex)] & (1L << (077 & bitIndex)); | |
} | |
/// Interprets block type from a bitset at specified position | |
PathingBlockType readCache(long long *bitset, int x, int y, int z){ | |
int idx = getPosIdx(x, y, z); | |
bool b1 = get(bitset, idx); | |
bool b2 = get(bitset, idx + 1); | |
using enum PathingBlockType; | |
return b1 ? b2 ? SOLID : AVOID : b2 ? WATER : AIR; | |
} | |
/// Writes block type to bitset cache | |
void writeCache( | |
long long *bitset, | |
int x, int y, int z, | |
PathingBlockType type) | |
{ | |
int idx = getPosIdx(x, y, z); | |
change(bitset, idx, type & 1); | |
change(bitset, idx + 1, type & 2); | |
} | |
#include "endianness.hpp" | |
/// x86 works on little endian thus | |
/// we have to change it to big endian | |
void byteswap(long long *bitset, size_t n){ | |
for (size_t i = 0; i < n; i++) | |
bitset[i] = bswap64(bitset[i]); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// g++ bcr-gun.cpp -o bcr-gun.exe ^ | |
// -O2 -Wall -march=native -std=c++20 -ldeflate | |
#include <fstream> | |
#include <iostream> | |
#include <filesystem> | |
namespace fs = std::filesystem; | |
#include <libdeflate.h> | |
const char* code[] = | |
{ | |
"LIBDEFLATE_SUCCESS", | |
"LIBDEFLATE_BAD_DATA", | |
"LIBDEFLATE_SHORT_OUTPUT", | |
"LIBDEFLATE_INSUFFICIENT_SPACE" | |
}; | |
int main(int argc, char *argv[]) | |
{ | |
if (argc != 2) return 1; | |
fs::path path(argv[1]); | |
size_t arsize= fs::file_size(path); | |
char* archive = new char[arsize]; | |
std::ifstream file(path, std::ios::binary); | |
file.read(archive, arsize); | |
size_t bcr_size = *(int*)(archive + arsize - 4); | |
char* bcr = new char[bcr_size]; | |
std::clog << path << ": " << "GZ" << ' ' | |
<< arsize << ' ' << bcr_size << std::endl; | |
size_t consumed = 0, outputted = 0; | |
libdeflate_decompressor *deco = libdeflate_alloc_decompressor(); | |
libdeflate_result r = libdeflate_gzip_decompress_ex( | |
deco, archive, arsize, | |
bcr, bcr_size, &consumed, &outputted ); | |
libdeflate_free_decompressor(deco); | |
std::clog << code[r] | |
<< ": readen " << consumed | |
<< ", written " << outputted; | |
if (r) return 2; | |
std::ofstream bcr_file( | |
path.stem().string() + ".bcr_unpack", | |
std::ios::binary | std::ios::trunc ); | |
bcr_file.write(bcr, outputted); | |
delete[] archive; | |
delete[] bcr; | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// g++ bcr-parse.cpp -o bcr-parse.exe ^ | |
// -O2 -Wall -march=native -std=c++20 -ldeflate | |
#include <ctime> | |
#include <limits> | |
#include <cstdlib> | |
#include <regex> | |
#include <fstream> | |
#include <iostream> | |
#include <filesystem> | |
namespace fs = std::filesystem; | |
#include <libdeflate.h> | |
#include "endianness.hpp" | |
#include "BLOCKS.cxx" | |
#include "BARITONE.cxx" | |
const char* code[] = | |
{ | |
"LIBDEFLATE_SUCCESS", | |
"LIBDEFLATE_BAD_DATA", | |
"LIBDEFLATE_SHORT_OUTPUT", | |
"LIBDEFLATE_INSUFFICIENT_SPACE" | |
}; | |
// making stream from buffer in memory, huh? | |
struct membuf: std::streambuf { | |
membuf(char* base, std::ptrdiff_t n) { | |
this->setg(base, base, base + n); | |
} | |
char * curr() { | |
return this->gptr(); // protected | |
} | |
}; | |
// byte swap template magic | |
template<typename T> | |
inline T bswap(T var){ | |
switch(sizeof(var)){ | |
case 2: return bswap16(var); | |
case 4: return bswap32(var); | |
case 8: return bswap64(var); | |
default: return var; | |
} | |
} | |
// float specialisation | |
template<> | |
inline float bswap(float var){ | |
return bswap_f(var); | |
} | |
// double specialisation | |
template<> | |
inline double bswap(double var){ | |
return bswap_d(var); | |
} | |
// simple macros for stream io | |
#define READ(var) read((char*)&(var),sizeof(var)) | |
#define WRITE(var) write((char*)&(var),sizeof(var)) | |
#define BSWAP(var) (var = bswap(var)) | |
#define LOCATION ' ' << '@' << std::hex \ | |
<< (sbuf.curr() - bcr) << std::dec << std::endl | |
std::string_view readUTF(std::istream& stream){ | |
unsigned short s; | |
stream.READ(s); | |
BSWAP(s); | |
using v = std::string_view; | |
auto p = ((membuf*)(stream.rdbuf()))->curr(); | |
stream.ignore(s); | |
return v(p, s); | |
} | |
union shortpos{ | |
unsigned short packed; | |
struct{ unsigned short y:8, x:4, z:4; }; | |
}; | |
/*union longpos{ | |
long long packed; | |
struct{ int x, z; }; | |
};*/ | |
struct longpos{ int x, z; }; | |
// MAIN | |
int main(int argc, char *argv[]) try | |
{ | |
if (argc != 2) return 1; | |
fs::path path(argv[1]); | |
longpos region; | |
std::smatch match; | |
std::string format = "r.{x}.{z}.bcr"; | |
std::regex re{R"(r\.(-?\d+)\.(-?\d+)\.bcr)"}; | |
std::string filename = path.filename().string(); | |
if ( std::regex_match(filename, match, re) ) | |
{ | |
region.x = std::stoi(match[1]) * 512; | |
region.z = std::stoi(match[2]) * 512; | |
} | |
else | |
{ | |
std::cerr << "File needs to follow format: " | |
<< format << std::endl << "Got: " | |
<< filename << ' ' << "instead!"; | |
return 3; | |
} | |
size_t arsize = fs::file_size(path); | |
char* archive = new char[arsize]; | |
std::ifstream file(path, std::ios::binary); | |
file.read((char*)archive, arsize); | |
size_t bcr_size = *(int*)(archive + arsize - 4); | |
char* bcr = new char[bcr_size]; | |
std::cout << "Loading [x:" << region.x | |
<< ",z:" << region.z << "]" << std::endl; | |
std::cout << path << ": " << "GZ" << ' ' | |
<< arsize << ' ' << bcr_size << std::endl; | |
size_t consumed = 0, outputted = 0; | |
libdeflate_decompressor *deco = libdeflate_alloc_decompressor(); | |
libdeflate_result r = libdeflate_gzip_decompress_ex( | |
deco, archive, arsize, | |
bcr, bcr_size, &consumed, &outputted ); | |
libdeflate_free_decompressor(deco); | |
std::cout << code[r]; | |
if (consumed != arsize || outputted != bcr_size){ | |
std::cout << ": readen " << consumed | |
<< ", written " << outputted; | |
} | |
std::cout << std::endl; | |
if (r) return 2; | |
std::ofstream bcr_file( | |
path.stem().string() + ".bcr_unpack", | |
std::ios::binary | std::ios::trunc ); | |
bcr_file.write(bcr, outputted); | |
membuf sbuf(bcr, outputted); | |
std::istream cache(&sbuf); | |
unsigned int MAGIC; // CACHED_REGION_MAGIC | |
cache.READ(MAGIC); | |
BSWAP(MAGIC); | |
std::cout << "MAGIC " << (MAGIC == 456022910 ? "OK" : "NOK"); | |
std::cout << std::endl << std::endl; | |
std::cout << "Cached chunks" << LOCATION; | |
int chunks = 0; | |
long long type[4]{0}; | |
longpos chunkpos[32 * 32]{0}; | |
for (int x = 0; x < 32; x++){ | |
for (int z = 0; z < 32; z++){ | |
if (cache.get()){ | |
chunkpos[chunks++] = { | |
region.x + x * 16, | |
region.z + z * 16 | |
}; | |
//auto& [a, b] = chunkpos[chunks - 1]; | |
//std::cout << "CHUNK\t" << a << '\t' << b << std::endl; | |
long long* ptr = (long long*) sbuf.curr(); | |
cache.ignore(BYTES_PER_CHUNK); | |
for (int by = 0; by < 256; by++){ | |
for (int bz = 0; bz < 16; bz++){ | |
for (int bx = 0; bx < 16; bx++){ | |
PathingBlockType T = readCache(ptr, bx, by, bz); | |
type[T]++; // just count them for all present chunks | |
} | |
} | |
} | |
} | |
} | |
} | |
std::cout << "AIR\t" << type[PathingBlockType::AIR] << std::endl; | |
std::cout << "WATER\t" << type[PathingBlockType::WATER] << std::endl; | |
std::cout << "AVOID\t" << type[PathingBlockType::AVOID] << std::endl; | |
std::cout << "SOLID\t" << type[PathingBlockType::SOLID] << std::endl; | |
std::cout << "Live chunks: " << chunks << '\n' << std::endl; | |
std::cout << "Surface overview" << LOCATION; | |
using v = std::string_view; | |
long surface[BLOCKS_LAST]{}; | |
for (int i = 0; i < chunks; i++){ | |
for (int j = 0; j < 256; j++){ | |
unsigned short s; | |
cache.READ(s); | |
BSWAP(s); | |
//std::cout << s << '|'; | |
v name(sbuf.curr(), s); | |
cache.ignore(s); | |
//std::cout << name << '|'; | |
int id = BLOCKID.at(name); | |
//std::cout << id << std::endl; | |
surface[id]++; | |
} | |
} | |
// printing out surface block counts | |
/*for (int i = 0; i < BLOCKS_LAST; i++){ | |
if (surface[i] != 0){ | |
std::cout << i << '\t' << surface[i] | |
<< '\t' << BLOCKS.at(i) << std::endl; | |
} | |
}*/ | |
int len = 0; | |
for (int i = 0; i < BLOCKS_LAST; i++){ | |
if (surface[i] != 0){ | |
v b = BLOCKS.at(i); | |
std::cout << b << ", "; | |
len += 2 + b.size(); | |
if (len > 72) | |
{ | |
std::cout << '\n'; | |
len = 0; | |
} | |
} | |
} | |
std::cout << std::endl << std::endl; | |
std::cout << "Tracked blocks" << LOCATION; | |
for (int i = 0; i < chunks; i++) | |
{ | |
auto& [x,z] = chunkpos[i]; | |
unsigned short unique; | |
cache.READ(unique); | |
BSWAP(unique); | |
for (int u = 0; u < unique; u++) | |
{ | |
auto block = readUTF(cache); | |
//std::cout << block << std::endl; | |
unsigned short tracks; | |
cache.READ(tracks); | |
BSWAP(tracks); | |
for (int t = 0; t < tracks; t++) | |
{ | |
shortpos pos; | |
cache.READ(pos.packed); | |
BSWAP(pos.packed); | |
std::cout << x + pos.x << '\t' | |
<< z + pos.z << '\t' | |
<< pos.y << '\t' | |
<< block << std::endl; | |
// here I could make absolute coord | |
// and store it into a set | |
} | |
} | |
} | |
std::cout << '\n' << "Timestamps" << LOCATION; | |
time_t stamp, min, max; // millis since epoch | |
min = std::numeric_limits<time_t>::max(); | |
max = std::numeric_limits<time_t>::min(); | |
for (int i = 0; i < chunks; i++) | |
{ | |
cache.READ(stamp); | |
BSWAP(stamp); | |
if (stamp < min) min = stamp; | |
if (stamp > max) max = stamp; | |
} | |
min /= 1000; // ms to s | |
max /= 1000; // ms to s | |
std::cout << "min\t" << std::asctime((std::localtime(&min))); | |
std::cout << "max\t" << std::asctime((std::localtime(&max))); | |
delete[] archive; | |
delete[] bcr; | |
return 0; | |
} catch (const std::exception& e) { std::cerr << e.what(); } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// **Chunk caching** | |
Baritone simplifies chunks to a compacted internal 2-bit representation | |
(AIR, SOLID, WATER, AVOID) and stores them in RAM for better very-long-distance | |
pathing. There is also an option to save these cached chunks to disk. | |
// uncompressed cache takes lots of space thus it uses single GZIP stream | |
// you may unpack it with 7zip or other if you change extension to *.gz | |
// files need be named "r.{x}.{z}.bcr" to be valid, as name is used to locate it | |
// btw coordinate order = most significant = inner most loop | |
// for ex. XZY! order = for Y: { for Z: { for X: { block } } } | |
// minus sign indicates iteration with decrementing value | |
// base values used you need to know: | |
CACHED_REGION_MAGIC = 456022910; // BE int:0x1B2E5B7E | |
CHUNK_NOT_PRESENT = 0, // byte | |
CHUNK_PRESENT = 1; // byte | |
// baritone.utils.pathing.PathingBlockType: | |
AIR = 0b00, // 0 | |
WATER = 0b01, // 1 | |
AVOID = 0b10, // 2 | |
SOLID = 0b11; // 3 | |
// UTF-8 string: | |
- BE short: size (in bytes?) (2 bytes) | |
- array of characters of specified size (not a CString?) | |
// "baritone cache region" streamed fields: | |
- magic number | |
// Magic value to detect invalid cache files, or incompatible | |
// cache files saved in an old version of Baritone | |
- array of 1024 chunks {boolean exists, optional<BitSet> chunkData} // ZX! order | |
// if no chunk is present, it is just 1024 NUL bytes | |
// after each CHUNK_PRESENT, you skip BitSet to reach next boolean | |
- for each existing chunkData, array of 256 UTF-8 block name strings // XZ! order | |
// for surface overview; compute their pos using heigtmap made with BitSet | |
- for each existing chunkData, array of arrays of specil bloks! | |
// BE short number of unique block types, then | |
// UTF-8 block name string + BE short number of know relative postions | |
// following array of positions, 1st byte: Z << 4 | X; 2nd byte: just Y | |
- for each existing chunkData, 64 bit timestamp (miliseconds since epoch) | |
// EOF | |
// BitSet size is constant. Chunks are 16x16x256, each block requires 2 bits. | |
public static final int SIZE = 2 * 16 * 16 * 256; // 131072 = 0x20000 (bits) | |
// The size of the chunk data in bytes. Equals to 16 KiB. | |
public static final int SIZE_IN_BYTES = SIZE / 8; // 16384 = 0x4000 (bytes) | |
// The list of special blocks that are remembered in cache | |
public static final ImmutableSet<Block> BLOCKS_TO_KEEP_TRACK_OF; | |
// = ImmutableSet.of(Blocks...) | |
DIAMOND_BLOCK, COAL_BLOCK, IRON_BLOCK, GOLD_BLOCK, EMERALD_ORE, EMERALD_BLOCK, | |
ENDER_CHEST, FURNACE, CHEST, TRAPPED_CHEST, END_PORTAL, END_PORTAL_FRAME, | |
MOB_SPAWNER, BARRIER, OBSERVER, WHITE_SHULKER_BOX, ORANGE_SHULKER_BOX, | |
MAGENTA_SHULKER_BOX, LIGHT_BLUE_SHULKER_BOX, YELLOW_SHULKER_BOX, | |
LIME_SHULKER_BOX, PINK_SHULKER_BOX, GRAY_SHULKER_BOX, SILVER_SHULKER_BOX, | |
CYAN_SHULKER_BOX, PURPLE_SHULKER_BOX, BLUE_SHULKER_BOX, BROWN_SHULKER_BOX, | |
GREEN_SHULKER_BOX, RED_SHULKER_BOX, BLACK_SHULKER_BOX, PORTAL, HOPPER, | |
BEACON, BREWING_STAND, SKULL, ENCHANTING_TABLE, ANVIL,LIT_FURNACE, | |
BED, DRAGON_EGG, JUKEBOX, END_GATEWAY, WEB, NETHER_WART, LADDER, VINE | |
// Returns the raw bit index of the specified position | |
public static int getPositionIndex(int x, int y, int z) { | |
return (x << 1) | (z << 5) | (y << 9); | |
} | |
// CachedChunk pack(Chunk chunk) // creation of it | |
BitSet bitSet = new BitSet(CachedChunk.SIZE); // 0x4000 | |
Map<String, List<BlockPos>> specialBlocks = new HashMap<>(); | |
// the mapping of BlockStateContainer.getIndex | |
// from xyz to index is: y << 8 | z << 4 | x; // XZY! order | |
// for better cache locality, iterate in that order | |
for (int y0 = 0; y0 < 16; y0++) { // chunkInternalStorageArray[y0]; // null? | |
int yReal = y0 << 4; | |
for (int y1 = 0; y1 < 16; y1++) { | |
int y = y1 | yReal; | |
for (int z = 0; z < 16; z++) { | |
for (int x = 0; x < 16; x++) { | |
boolean[] bits = getPathingBlockType... | |
bitSet.set(index, bits[0]); | |
bitSet.set(index + 1, bits[1]); | |
// if "special" then add to specialBlocks | |
// The block names of each surface level block for generating an overview | |
IBlockState[] overview = new IBlockState[256]; // surface blocks or "air" | |
overview[z << 4 | x] = Blocks.AIR.getDefaultState(); // -YXZ!, first non AIR | |
// computed data is used to make cached chunk and then returned | |
new CachedChunk(chunk.x, chunk.z, bitSet, overview, specialBlocks, timestamp); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <array> | |
#include <string_view> | |
#include <unordered_map> | |
/// Given a map from keys to values, creates a new map from values to keys | |
template<typename K, typename V> | |
static auto reverse_map(const std::unordered_map<K, V>& m) { | |
std::unordered_map<V, K> r; | |
for (const auto& kv : m) | |
r[kv.second] = kv.first; | |
return r; | |
} | |
#define BLOCKS_LAST 255 | |
/// map of block entries, id -> name | |
std::unordered_map<int,std::string_view> const BLOCKS { | |
{ 0, "air"}, // AIR | |
{ 1, "stone"}, | |
{ 2, "grass"}, | |
{ 3, "dirt"}, | |
{ 4, "cobblestone"}, | |
{ 5, "planks"}, | |
{ 6, "sapling"}, | |
{ 7, "bedrock"}, | |
{ 8, "flowing_water"}, // META | |
{ 9, "water"}, // META | |
{ 10, "flowing_lava"}, // AVOID | |
{ 11, "lava"}, // AVOID | |
{ 12, "sand"}, | |
{ 13, "gravel"}, | |
{ 14, "gold_ore"}, | |
{ 15, "iron_ore"}, | |
{ 16, "coal_ore"}, | |
{ 17, "log"}, | |
{ 18, "leaves"}, | |
{ 19, "sponge"}, | |
{ 20, "glass"}, | |
{ 21, "lapis_ore"}, | |
{ 22, "lapis_block"}, | |
{ 23, "dispenser"}, | |
{ 24, "sandstone"}, | |
{ 25, "noteblock"}, | |
{ 26, "bed"}, | |
{ 27, "golden_rail"}, | |
{ 28, "detector_rail"}, | |
{ 29, "sticky_piston"}, | |
{ 30, "web"}, // AVOID | |
{ 31, "tallgrass"}, // AIR | |
{ 32, "deadbush"}, // AIR | |
{ 33, "piston"}, | |
{ 34, "piston_head"}, | |
{ 35, "wool"}, | |
{ 36, "piston_extension"}, | |
{ 37, "yellow_flower"}, // AIR | |
{ 38, "red_flower"}, // AIR | |
{ 39, "brown_mushroom"}, | |
{ 40, "red_mushroom"}, | |
{ 41, "gold_block"}, | |
{ 42, "iron_block"}, | |
{ 43, "double_stone_slab"}, | |
{ 44, "stone_slab"}, // META | |
{ 45, "brick_block"}, | |
{ 46, "tnt"}, | |
{ 47, "bookshelf"}, | |
{ 48, "mossy_cobblestone"}, | |
{ 49, "obsidian"}, | |
{ 50, "torch"}, | |
{ 51, "fire"}, // AVOID | |
{ 52, "mob_spawner"}, | |
{ 53, "oak_stairs"}, | |
{ 54, "chest"}, | |
{ 55, "redstone_wire"}, | |
{ 56, "diamond_ore"}, | |
{ 57, "diamond_block"}, | |
{ 58, "crafting_table"}, | |
{ 59, "wheat"}, | |
{ 60, "farmland"}, | |
{ 61, "furnace"}, | |
{ 62, "lit_furnace"}, | |
{ 63, "standing_sign"}, | |
{ 64, "wooden_door"}, | |
{ 65, "ladder"}, | |
{ 66, "rail"}, | |
{ 67, "stone_stairs"}, | |
{ 68, "wall_sign"}, | |
{ 69, "lever"}, | |
{ 70, "stone_pressure_plate"}, | |
{ 71, "iron_door"}, | |
{ 72, "wooden_pressure_plate"}, | |
{ 73, "redstone_ore"}, | |
{ 74, "lit_redstone_ore"}, | |
{ 75, "unlit_redstone_torch"}, | |
{ 76, "redstone_torch"}, | |
{ 77, "stone_button"}, | |
{ 78, "snow_layer"}, | |
{ 79, "ice"}, | |
{ 80, "snow"}, | |
{ 81, "cactus"}, // AVOID | |
{ 82, "clay"}, | |
{ 83, "reeds"}, | |
{ 84, "jukebox"}, | |
{ 85, "fence"}, | |
{ 86, "pumpkin"}, | |
{ 87, "netherrack"}, | |
{ 88, "soul_sand"}, | |
{ 89, "glowstone"}, | |
{ 90, "portal"}, | |
{ 91, "lit_pumpkin"}, | |
{ 92, "cake"}, | |
{ 93, "unpowered_repeater"}, | |
{ 94, "powered_repeater"}, | |
{ 95, "stained_glass"}, | |
{ 96, "trapdoor"}, | |
{ 97, "monster_egg"}, | |
{ 98, "stonebrick"}, | |
{ 99, "brown_mushroom_block"}, | |
{ 100, "red_mushroom_block"}, | |
{ 101, "iron_bars"}, | |
{ 102, "glass_pane"}, | |
{ 103, "melon_block"}, | |
{ 104, "pumpkin_stem"}, | |
{ 105, "melon_stem"}, | |
{ 106, "vine"}, | |
{ 107, "fence_gate"}, | |
{ 108, "brick_stairs"}, | |
{ 109, "stone_brick_stairs"}, | |
{ 110, "mycelium"}, | |
{ 111, "waterlily"}, | |
{ 112, "nether_brick"}, | |
{ 113, "nether_brick_fence"}, | |
{ 114, "nether_brick_stairs"}, | |
{ 115, "nether_wart"}, | |
{ 116, "enchanting_table"}, | |
{ 117, "brewing_stand"}, | |
{ 118, "cauldron"}, | |
{ 119, "end_portal"}, // AVOID | |
{ 120, "end_portal_frame"}, | |
{ 121, "end_stone"}, | |
{ 122, "dragon_egg"}, | |
{ 123, "redstone_lamp"}, | |
{ 124, "lit_redstone_lamp"}, | |
{ 125, "double_wooden_slab"}, | |
{ 126, "wooden_slab"}, // META | |
{ 127, "cocoa"}, | |
{ 128, "sandstone_stairs"}, | |
{ 129, "emerald_ore"}, | |
{ 130, "ender_chest"}, | |
{ 131, "tripwire_hook"}, | |
{ 132, "tripwire"}, | |
{ 133, "emerald_block"}, | |
{ 134, "spruce_stairs"}, | |
{ 135, "birch_stairs"}, | |
{ 136, "jungle_stairs"}, | |
{ 137, "command_block"}, | |
{ 138, "beacon"}, | |
{ 139, "cobblestone_wall"}, | |
{ 140, "flower_pot"}, | |
{ 141, "carrots"}, | |
{ 142, "potatoes"}, | |
{ 143, "wooden_button"}, | |
{ 144, "skull"}, | |
{ 145, "anvil"}, | |
{ 146, "trapped_chest"}, | |
{ 147, "light_weighted_pressure_plate"}, | |
{ 148, "heavy_weighted_pressure_plate"}, | |
{ 149, "unpowered_comparator"}, | |
{ 150, "powered_comparator"}, | |
{ 151, "daylight_detector"}, | |
{ 152, "redstone_block"}, | |
{ 153, "quartz_ore"}, | |
{ 154, "hopper"}, | |
{ 155, "quartz_block"}, | |
{ 156, "quartz_stairs"}, | |
{ 157, "activator_rail"}, | |
{ 158, "dropper"}, | |
{ 159, "stained_hardened_clay"}, | |
{ 160, "stained_glass_pane"}, | |
{ 161, "leaves2"}, | |
{ 162, "log2"}, | |
{ 163, "acacia_stairs"}, | |
{ 164, "dark_oak_stairs"}, | |
{ 165, "slime"}, | |
{ 166, "barrier"}, | |
{ 167, "iron_trapdoor"}, | |
{ 168, "prismarine"}, | |
{ 169, "sea_lantern"}, | |
{ 170, "hay_block"}, | |
{ 171, "carpet"}, | |
{ 172, "hardened_clay"}, | |
{ 173, "coal_block"}, | |
{ 174, "packed_ice"}, | |
{ 175, "double_plant"}, // AIR | |
{ 176, "standing_banner"}, | |
{ 177, "wall_banner"}, | |
{ 178, "daylight_detector_inverted"}, | |
{ 179, "red_sandstone"}, | |
{ 180, "red_sandstone_stairs"}, | |
{ 181, "double_stone_slab2"}, | |
{ 182, "stone_slab2"}, // META | |
{ 183, "spruce_fence_gate"}, | |
{ 184, "birch_fence_gate"}, | |
{ 185, "jungle_fence_gate"}, | |
{ 186, "dark_oak_fence_gate"}, | |
{ 187, "acacia_fence_gate"}, | |
{ 188, "spruce_fence"}, | |
{ 189, "birch_fence"}, | |
{ 190, "jungle_fence"}, | |
{ 191, "dark_oak_fence"}, | |
{ 192, "acacia_fence"}, | |
{ 193, "spruce_door"}, | |
{ 194, "birch_door"}, | |
{ 195, "jungle_door"}, | |
{ 196, "acacia_door"}, | |
{ 197, "dark_oak_door"}, | |
{ 198, "end_rod"}, | |
{ 199, "chorus_plant"}, | |
{ 200, "chorus_flower"}, | |
{ 201, "purpur_block"}, | |
{ 202, "purpur_pillar"}, | |
{ 203, "purpur_stairs"}, | |
{ 204, "purpur_double_slab"}, | |
{ 205, "purpur_slab"}, // META | |
{ 206, "end_bricks"}, | |
{ 207, "beetroots"}, | |
{ 208, "grass_path"}, | |
{ 209, "end_gateway"}, | |
{ 210, "repeating_command_block"}, | |
{ 211, "chain_command_block"}, | |
{ 212, "frosted_ice"}, | |
{ 213, "magma"}, // AVOID | |
{ 214, "nether_wart_block"}, | |
{ 215, "red_nether_brick"}, | |
{ 216, "bone_block"}, | |
{ 217, "structure_void"}, | |
{ 218, "observer"}, | |
{ 219, "white_shulker_box"}, | |
{ 220, "orange_shulker_box"}, | |
{ 221, "magenta_shulker_box"}, | |
{ 222, "light_blue_shulker_box"}, | |
{ 223, "yellow_shulker_box"}, | |
{ 224, "lime_shulker_box"}, | |
{ 225, "pink_shulker_box"}, | |
{ 226, "gray_shulker_box"}, | |
{ 227, "silver_shulker_box"}, | |
{ 228, "cyan_shulker_box"}, | |
{ 229, "purple_shulker_box"}, | |
{ 230, "blue_shulker_box"}, | |
{ 231, "brown_shulker_box"}, | |
{ 232, "green_shulker_box"}, | |
{ 233, "red_shulker_box"}, | |
{ 234, "black_shulker_box"}, | |
{ 235, "white_glazed_terracotta"}, | |
{ 236, "orange_glazed_terracotta"}, | |
{ 237, "magenta_glazed_terracotta"}, | |
{ 238, "light_blue_glazed_terracotta"}, | |
{ 239, "yellow_glazed_terracotta"}, | |
{ 240, "lime_glazed_terracotta"}, | |
{ 241, "pink_glazed_terracotta"}, | |
{ 242, "gray_glazed_terracotta"}, | |
{ 243, "silver_glazed_terracotta"}, | |
{ 244, "cyan_glazed_terracotta"}, | |
{ 245, "purple_glazed_terracotta"}, | |
{ 246, "blue_glazed_terracotta"}, | |
{ 247, "brown_glazed_terracotta"}, | |
{ 248, "green_glazed_terracotta"}, | |
{ 249, "red_glazed_terracotta"}, | |
{ 250, "black_glazed_terracotta"}, | |
{ 251, "concrete"}, | |
{ 252, "concrete_powder"}, | |
{ 255, "structure_block"} | |
}; | |
/// map of block entries, name -> id | |
auto const BLOCKID = reverse_map(BLOCKS); | |
/// preset array to ease determining block path type | |
std::array<bool, BLOCKS_LAST> TRACKED{}; | |
std::array<bool, BLOCKS_LAST> SOLIDS{}; | |
int BLOCKS_TO_KEEP_TRACK_OF[] = { | |
26, // BED, | |
30, // WEB, | |
41, // GOLD_BLOCK, | |
42, // IRON_BLOCK, | |
52, // MOB_SPAWNER, | |
54, // CHEST, | |
57, // DIAMOND_BLOCK, | |
61, // FURNACE, | |
62, // LIT_FURNACE, | |
65, // LADDER, | |
84, // JUKEBOX, | |
90, // PORTAL, | |
106, // VINE | |
115, // NETHER_WART, | |
116, // ENCHANTING_TABLE, | |
117, // BREWING_STAND, | |
119, // END_PORTAL, | |
120, // END_PORTAL_FRAME, | |
122, // DRAGON_EGG, | |
129, // EMERALD_ORE, | |
130, // ENDER_CHEST, | |
133, // EMERALD_BLOCK, | |
138, // BEACON, | |
144, // SKULL, | |
145, // ANVIL, | |
146, // TRAPPED_CHEST, | |
154, // HOPPER, | |
166, // BARRIER, | |
173, // COAL_BLOCK, | |
209, // END_GATEWAY, | |
218, // OBSERVER, | |
// SHULKER BOXES ! | |
219, // WHITE_SHULKER_BOX, | |
220, // ORANGE_SHULKER_BOX, | |
221, // MAGENTA_SHULKER_BOX, | |
222, // LIGHT_BLUE_SHULKER_BOX, | |
223, // YELLOW_SHULKER_BOX, | |
224, // LIME_SHULKER_BOX, | |
225, // INK_SHULKER_BOX, | |
226, // GRAY_SHULKER_BOX, | |
227, // SILVER_SHULKER_BOX, | |
228, // CYAN_SHULKER_BOX, | |
229, // PURPLE_SHULKER_BOX, | |
230, // BLUE_SHULKER_BOX, | |
231, // BROWN_SHULKER_BOX, | |
232, // GREEN_SHULKER_BOX, | |
233, // RED_SHULKER_BOX, | |
234 // BLACK_SHULKER_BOX, | |
}; | |
void initBlocks(){ | |
// intialise block array that have SOLID property | |
for (bool &property : SOLIDS) property = true; | |
// set block ids that are tracked by Baritone itself | |
for (int i : BLOCKS_TO_KEEP_TRACK_OF) TRACKED[i] = true; | |
// those may have different property than SOLID | |
for (int i : {0, 8, 9, 10, 11, 30, 31, 32, 37, 38, 44, | |
51, 81, 119, 126, 175, 182, 205, 213}) | |
SOLIDS[i] = false; // those need additional checks | |
} | |
inline bool isTracked(int id){ | |
return TRACKED[id]; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local dump = require 'ForgeRegistryDump' | |
local registry, registry_name = dump() | |
local header = 'std::unordered_map<int,std::string> const %s {\n' | |
local entry, footer, flush = ' { %d, "%s"}', '\n};\n', ',\n' | |
if not registry then return end | |
-- build sorted table | |
local ordered = {} | |
for k, v in pairs(registry) do table.insert(ordered, {id = k, name = v}) end | |
table.sort(ordered, function(a,b) return a.id < b.id end) | |
-- source code builder | |
local text, last = header:format(registry_name), #ordered | |
for current, res in ipairs(ordered) do | |
if current ~= last then | |
text = text .. entry:format(res.id, res.name) .. flush | |
else text = text .. entry:format(res.id, res.name) .. footer end | |
end | |
last = "#define "..registry_name.."_LAST "..ordered[last].id..'\n' | |
io.open(registry_name..".cxx", "w+"):write(last):write(text):close() | |
log("&6Dumped \""..registry_name.."\" registry to source file!") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef ENDIANNESS_HPP | |
#define ENDIANNESS_HPP | |
#ifdef __GNUC__ | |
#define __BSWAP__ | |
#include <x86intrin.h> | |
#define bswap16 __builtin_bswap16 | |
#define bswap32 __builtin_bswap32 | |
#define bswap64 __builtin_bswap64 | |
#endif // __GNUC__ | |
#ifdef _MSC_VER | |
#define __BSWAP__ | |
#include <intrin.h> | |
#define bswap16 _byteswap_ushort | |
#define bswap32 _byteswap_ulong | |
#define bswap64 _byteswap_uint64 | |
#endif // _MSC_VER | |
#ifdef __BSWAP__ | |
static inline float bswap_f(float val) | |
{ | |
union{ float fp; long long bytes; }; | |
fp = val, bytes = bswap32( bytes ); | |
return fp; | |
} | |
static inline double bswap_d(double val) | |
{ | |
union{ double fp; long long bytes; }; | |
fp = val, bytes = bswap64( bytes ); | |
return fp; | |
} | |
#endif // __BSWAP__ | |
#if not defined NETWORK_BYTE_ORDER and not defined __BSWAP__ | |
#error BYTESWAPS ARE NOT IMPLEMENTED! No code written for your compiler! | |
#elif defined NETWORK_BYTE_ORDER | |
#define bswap16(x) (x) | |
#define bswap32(x) (x) | |
#define bswap64(x) (x) | |
#define bswap_f(x) (x) | |
#define bswap_d(x) (x) | |
#endif | |
#endif // ENDIANNESS_HPP |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading [x:0,z:0] | |
"r.0.0.bcr": GZ 74227 4660101 | |
LIBDEFLATE_SUCCESS | |
MAGIC OK | |
Cached chunks @4 | |
AIR 12579406 | |
WATER 897160 | |
AVOID 14236 | |
SOLID 3286414 | |
Live chunks: 256 | |
Surface overview @400404 | |
stone, grass, dirt, cobblestone, planks, water, sand, gravel, log, leaves, | |
sandstone, bed, deadbush, brown_mushroom, red_mushroom, mossy_cobblestone, | |
wheat, stone_stairs, reeds, spruce_stairs, carrots, potatoes, spruce_fence, | |
grass_path, | |
Tracked blocks @47113c | |
1 1 65 bed | |
2 1 65 bed | |
1 2 65 bed | |
2 2 65 bed | |
121 51 44 chest | |
124 51 44 mob_spawner | |
170 145 21 chest | |
169 147 21 chest | |
171 147 21 mob_spawner | |
Timestamps @471385 | |
min Sun Mar 13 14:27:26 2022 | |
max Sun Mar 13 14:28:13 2022 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- a helper function to turn registry into table | |
local dumper = function(REGISTRY,includes_domain) | |
local Forge = luajava.bindClass'net.minecraftforge.fml.common.registry.ForgeRegistries' | |
local REGISTRY = REGISTRY or prompt( | |
"Choose registry to dump:", "choice", | |
table.unpack( luajava.getDeclaredFields( Forge ) ) | |
) | |
if not REGISTRY then return false end | |
local RegistryName = REGISTRY | |
REGISTRY = Forge[REGISTRY] | |
local entries = {} | |
local adapter = function(entry) | |
local K, V = entry:getKey() | |
if includes_domain then | |
V = K:toString() | |
else -- getResourcePath | |
V = K:func_110623_a() | |
end | |
--V = REGISTRY:getValue(K) | |
K = REGISTRY:getIDRaw(K) | |
entries[K] = V -- without "minecraft:" | |
end | |
local Consumer = "java.util.function.Consumer" | |
local adapt = luajava.createProxy( Consumer, { accept = adapter }) | |
REGISTRY:getEntries():forEach(adapt) | |
return entries, RegistryName | |
end | |
return dumper |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment