diff --git a/.gitignore b/.gitignore index 0329bfc..51f6d74 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,4 @@ cmake-** /projects/Utilities/Tests/input /projects/Utilities/Viewer /projects/Utilities/Tests/output +/profiler diff --git a/README.md b/README.md index b84221f..6948a75 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ LCE formats will be handled by [libLCE](https://github.com/DexrnZacAttack/libLCE - [X] World Engine - [X] Chunked Level - [X] Chunk Sections - - [ ] Palettes (for memory usage) + - [X] Palettes (for memory usage) - [ ] Lighting calculation (maybe?) - [ ] Biomes - [ ] POI/Structure system @@ -51,8 +51,9 @@ LCE formats will be handled by [libLCE](https://github.com/DexrnZacAttack/libLCE - [ ] PE/Bedrock # Credits -- [BinaryIO](https://github.com/DexrnZacAttack/libBIO) +- [BinaryIO](https://codeberg.org/Dexrn/libBIO) - [libNBT++ 2](https://github.com/PrismLauncher/libnbtplusplus) +- [danilwhale](https://codeberg.org/danilwhale) # Disclaimer -This project is not an official Microsoft, Minecraft, nor Mojang Studios product. \ No newline at end of file +This project is not an official Microsoft, Minecraft, nor Mojang Studios product. diff --git a/gdb/PrettyPrinters.py b/gdb/PrettyPrinters.py index 7a31005..24fff5a 100644 --- a/gdb/PrettyPrinters.py +++ b/gdb/PrettyPrinters.py @@ -5,7 +5,7 @@ def __init__(self, val): self.val = val def to_string(self): try: - return str(gdb.parse_and_eval(f"((lodestone::common::string::StringSerializable*){int(self.val.address)})->toString()")) # jank? + return str(gdb.parse_and_eval(f"if ((lodestone::common::string::StringSerializable*){int(self.val.address)}) ((lodestone::common::string::StringSerializable*){int(self.val.address)})->toString()")) # jank? except Exception as ex: print("tostring", ex) return None diff --git a/projects/Converters/Minecraft/Common/CMakeLists.txt b/projects/Converters/Minecraft/Common/CMakeLists.txt index a5d3591..27faf74 100644 --- a/projects/Converters/Minecraft/Common/CMakeLists.txt +++ b/projects/Converters/Minecraft/Common/CMakeLists.txt @@ -18,6 +18,7 @@ set(FILES include/Lodestone.Minecraft.Common/world/MinecraftWorld.h include/Lodestone.Minecraft.Common/region/RegionChunkIndice.h include/Lodestone.Minecraft.Common/region/RegionCompression.h + include/Lodestone.Minecraft.Common/player/Abilities.h ) add_library(Lodestone.Minecraft.Common OBJECT ${FILES}) diff --git a/projects/Converters/Minecraft/Common/include/Lodestone.Minecraft.Common/player/Abilities.h b/projects/Converters/Minecraft/Common/include/Lodestone.Minecraft.Common/player/Abilities.h new file mode 100644 index 0000000..5a3a598 --- /dev/null +++ b/projects/Converters/Minecraft/Common/include/Lodestone.Minecraft.Common/player/Abilities.h @@ -0,0 +1,16 @@ +// +// Created by DexrnZacAttack on 11/27/25 using zPc-i2. +// +#ifndef LODESTONE_GAMEMODE_H +#define LODESTONE_GAMEMODE_H +#include "Lodestone.Common/registry/Identifier.h" + +namespace lodestone::minecraft::common::player { + struct Abilities { + bool canFly; + bool invulnerable; + bool canInstabuild; + }; +} + +#endif // LODESTONE_GAMEMODE_H diff --git a/projects/Converters/Minecraft/Common/include/Lodestone.Minecraft.Common/player/MinecraftPlayer.h b/projects/Converters/Minecraft/Common/include/Lodestone.Minecraft.Common/player/MinecraftPlayer.h index 27663cc..ede5764 100644 --- a/projects/Converters/Minecraft/Common/include/Lodestone.Minecraft.Common/player/MinecraftPlayer.h +++ b/projects/Converters/Minecraft/Common/include/Lodestone.Minecraft.Common/player/MinecraftPlayer.h @@ -6,6 +6,8 @@ #include #include +#include "Lodestone.Minecraft.Common/player/Abilities.h" + namespace lodestone::minecraft::common::player { class MinecraftPlayer : public level::entity::Player { public: @@ -54,7 +56,10 @@ namespace lodestone::minecraft::common::player { const lodestone::common::registry::Identifier *getType() const override; - std::shared_ptr + const Abilities &getAbilities() const; + + void setAbilities(const Abilities &abilities); + std::shared_ptr getProperty(const std::string &name) override; private: @@ -102,6 +107,9 @@ namespace lodestone::minecraft::common::player { */ float mFallDistance; + /** The player's abilities */ + Abilities mAbilities; + /** The player's inventory * * @prop inventory diff --git a/projects/Converters/Minecraft/Common/src/player/MinecraftPlayer.cpp b/projects/Converters/Minecraft/Common/src/player/MinecraftPlayer.cpp index 90a4820..b5c90e7 100644 --- a/projects/Converters/Minecraft/Common/src/player/MinecraftPlayer.cpp +++ b/projects/Converters/Minecraft/Common/src/player/MinecraftPlayer.cpp @@ -93,23 +93,30 @@ namespace lodestone::minecraft::common::player { return &identifiers::MINECRAFT_COMMON; } + const Abilities &MinecraftPlayer::getAbilities() const { + return mAbilities; + } + + void MinecraftPlayer::setAbilities(const Abilities &abilities) { + mAbilities = abilities; + } + std::shared_ptr MinecraftPlayer::getProperty(const std::string &name) { switch (lodestone::common::util::Math::fnv1a64(name.data(), name.length())) { - ADD_PROPERTY("name", mName, std::string &); - ADD_PROPERTY("spawnPos", mSpawnPos, level::types::Vec3i &); - ADD_PROPERTY("deathTime", mDeathTime, short &); - ADD_PROPERTY("hurtTime", mHurtTime, short &); - ADD_PROPERTY("attackTime", mAttackTime, short &); - ADD_PROPERTY("fireTime", mFireTime, short &); - ADD_PROPERTY("breathingTime", mBreathingTime, short &); - ADD_PROPERTY("dimension", mDimension, - lodestone::common::registry::Identifier &); - ADD_PROPERTY("fallDistance", mFallDistance, float &); - ADD_PROPERTY("inventory", mInventory, - level::container::ItemContainer &); - ADD_PROPERTY("armor", mArmor, level::container::ItemContainer &); + ADD_FIELD_PROPERTY("name", mName); + ADD_FIELD_PROPERTY("spawnPos", mSpawnPos); + ADD_FIELD_PROPERTY("deathTime", mDeathTime); + ADD_FIELD_PROPERTY("hurtTime", mHurtTime); + ADD_FIELD_PROPERTY("attackTime", mAttackTime); + ADD_FIELD_PROPERTY("fireTime", mFireTime); + ADD_FIELD_PROPERTY("breathingTime", mBreathingTime); + ADD_FIELD_PROPERTY("dimension", mDimension); + ADD_FIELD_PROPERTY("fallDistance", mFallDistance); + ADD_FIELD_PROPERTY("inventory", mInventory); + ADD_FIELD_PROPERTY("armor", mArmor); + ADD_FIELD_PROPERTY("abilities", mAbilities); default: return Player::getProperty(name); } diff --git a/projects/Converters/Minecraft/Common/src/world/MinecraftWorld.cpp b/projects/Converters/Minecraft/Common/src/world/MinecraftWorld.cpp index 28e8e27..6f494f6 100644 --- a/projects/Converters/Minecraft/Common/src/world/MinecraftWorld.cpp +++ b/projects/Converters/Minecraft/Common/src/world/MinecraftWorld.cpp @@ -28,9 +28,9 @@ namespace lodestone::minecraft::common::world { MinecraftWorld::getProperty(const std::string &name) { switch (lodestone::common::util::Math::fnv1a64(name.data(), name.length())) { - ADD_PROPERTY("seed", mSeed, int64_t &); - ADD_PROPERTY("lastPlayed", mLastPlayed, int64_t &); - ADD_PROPERTY("time", mTime, int64_t &); + ADD_FIELD_PROPERTY("seed", mSeed); + ADD_FIELD_PROPERTY("lastPlayed", mLastPlayed); + ADD_FIELD_PROPERTY("time", mTime); default: return World::getProperty(name); } diff --git a/projects/Converters/Minecraft/Java/CMakeLists.txt b/projects/Converters/Minecraft/Java/CMakeLists.txt index 5c5beea..fcebf6a 100644 --- a/projects/Converters/Minecraft/Java/CMakeLists.txt +++ b/projects/Converters/Minecraft/Java/CMakeLists.txt @@ -54,6 +54,12 @@ set(FILES src/anvil/jungle/region/JungleAnvilRegion.cpp include/Lodestone.Minecraft.Java/anvil/jungle/region/JungleAnvilRegionIo.h src/anvil/jungle/region/JungleAnvilRegionIo.cpp + src/anvil/jungle/world/JungleAnvilWorld.cpp + include/Lodestone.Minecraft.Java/anvil/jungle/world/JungleAnvilWorld.h + src/anvil/jungle/world/JungleAnvilWorldIo.cpp + include/Lodestone.Minecraft.Java/anvil/jungle/world/JungleAnvilWorldIo.h + include/Lodestone.Minecraft.Java/GeneratorTypes.h + src/GeneratorTypes.cpp ) add_library(Lodestone.Minecraft.Java SHARED ${FILES}) @@ -66,7 +72,7 @@ target_link_libraries(Lodestone.Minecraft.Java PRIVATE Lodestone.Level Lodestone target_link_libraries(Lodestone.Minecraft.Java PUBLIC Lodestone.Core Lodestone.Minecraft.Common) option(USE_OPENMP "Use OpenMP" ON) -if (USE_OPENMP STREQUAL ON AND OpenMP_CXX_FOUND AND OpenMP_C_FOUND) +if (USE_OPENMP STREQUAL ON AND OpenMP_CXX_FOUND AND OpenMP_C_FOUND AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug") message(STATUS "Using OpenMP") target_link_libraries(Lodestone.Minecraft.Java PRIVATE OpenMP::OpenMP_CXX) target_compile_definitions(Lodestone.Minecraft.Java PRIVATE USE_OPENMP) diff --git a/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/GeneratorTypes.h b/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/GeneratorTypes.h new file mode 100644 index 0000000..9c9c042 --- /dev/null +++ b/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/GeneratorTypes.h @@ -0,0 +1,24 @@ +// +// Created by DexrnZacAttack on 11/9/25 using zPc-i2. +// +#ifndef LODESTONE_GENERATORTYPES_H +#define LODESTONE_GENERATORTYPES_H +#include + +namespace lodestone::minecraft::java { + struct GeneratorTypes { + static constexpr lodestone::common::registry::Identifier DEFAULT = { + "minecraft", "default"}; + static constexpr lodestone::common::registry::Identifier FLAT = { + "minecraft", "flat"}; + static constexpr lodestone::common::registry::Identifier LARGE_BIOMES = + {"minecraft", "large_biomes"}; + + static const lodestone::common::registry::Identifier & + generatorIdToIdentifier(const std::string &id); + static std::string identifierToGeneratorId( + const lodestone::common::registry::Identifier &id, int version); + }; +} // namespace lodestone::minecraft::java + +#endif diff --git a/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/alpha/world/AlphaWorldIo.h b/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/alpha/world/AlphaWorldIo.h index b8b3719..730c21c 100644 --- a/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/alpha/world/AlphaWorldIo.h +++ b/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/alpha/world/AlphaWorldIo.h @@ -8,7 +8,7 @@ namespace lodestone::minecraft::java::alpha::world { - class AlphaWorldIo final : public conversion::world::DirectoryWorldIO { + class AlphaWorldIo : public conversion::world::DirectoryWorldIO { public: const lodestone::conversion::level::LevelIO * getLevelIO(int version) const override; @@ -22,6 +22,15 @@ namespace lodestone::minecraft::java::alpha::world { lodestone::level::world::World *w, int version, const conversion::world::options::AbstractWorldWriteOptions &options) const override; + + const lodestone::conversion::chunk::ChunkIO * + getChunkIO(int version) const override; + + const lodestone::conversion::region::RegionIO * + getRegionIO(int version) const override; + + const lodestone::conversion::player::PlayerIO * + getPlayerIO(int version) const override; }; } // namespace lodestone::minecraft::java::alpha::world diff --git a/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/anvil/jungle/world/JungleAnvilWorld.h b/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/anvil/jungle/world/JungleAnvilWorld.h new file mode 100644 index 0000000..906e735 --- /dev/null +++ b/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/anvil/jungle/world/JungleAnvilWorld.h @@ -0,0 +1,18 @@ +// +// Created by Zero on 11/26/25. +// + +#ifndef LODESTONE_JUNGLEANVILWORLD_H +#define LODESTONE_JUNGLEANVILWORLD_H +#include "Lodestone.Minecraft.Java/mcregion/world/McRegionWorld.h" + +#include + +namespace lodestone::minecraft::java::anvil::jungle::world { + class JungleAnvilWorld : public mcregion::world::McRegionWorld { + public: + explicit JungleAnvilWorld(const std::string &name); + }; +} // namespace lodestone::minecraft::java::anvil::jungle::world + +#endif // LODESTONE_JUNGLEANVILWORLD_H diff --git a/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/anvil/jungle/world/JungleAnvilWorldIo.h b/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/anvil/jungle/world/JungleAnvilWorldIo.h new file mode 100644 index 0000000..68f32c3 --- /dev/null +++ b/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/anvil/jungle/world/JungleAnvilWorldIo.h @@ -0,0 +1,41 @@ +// +// Created by Zero on 11/26/25. +// + +#ifndef LODESTONE_JUNGLEANVILWORLDIO_H +#define LODESTONE_JUNGLEANVILWORLDIO_H +#include +#include + +#include + +namespace lodestone::minecraft::java::anvil::jungle::world { + + class JungleAnvilWorldIo : public conversion::world::DirectoryWorldIO { + public: + const conversion::level::LevelIO * + getLevelIO(int version) const override; + + std::unique_ptr + read(const std::filesystem::path &path, int version, + const conversion::world::options::AbstractWorldReadOptions + &options) const override; + + void write(const std::filesystem::path &path, level::world::World *w, + int version, + const conversion::world::options::AbstractWorldWriteOptions + &options) const override; + + const conversion::chunk::ChunkIO * + getChunkIO(int version) const override; + + const conversion::region::RegionIO * + getRegionIO(int version) const override; + + const conversion::player::PlayerIO * + getPlayerIO(int version) const override; + }; + +} // namespace lodestone::minecraft::java::anvil::jungle::world + +#endif // LODESTONE_JUNGLEANVILWORLDIO_H diff --git a/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/classic/minev2/MineV2WorldIo.h b/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/classic/minev2/MineV2WorldIo.h index 7e688d6..b3b693d 100644 --- a/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/classic/minev2/MineV2WorldIo.h +++ b/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/classic/minev2/MineV2WorldIo.h @@ -24,6 +24,15 @@ namespace lodestone::minecraft::java::classic::minev2 { std::ostream &out, const conversion::world::options::AbstractWorldWriteOptions &options) const override; + + const lodestone::conversion::chunk::ChunkIO * + getChunkIO(int version) const override; + + const lodestone::conversion::region::RegionIO * + getRegionIO(int version) const override; + + const lodestone::conversion::player::PlayerIO * + getPlayerIO(int version) const override; }; } // namespace lodestone::minecraft::java::classic::minev2 diff --git a/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/mcregion/region/McRegionRegionIo.h b/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/mcregion/region/McRegionRegionIo.h index 5aedecd..4d968d5 100644 --- a/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/mcregion/region/McRegionRegionIo.h +++ b/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/mcregion/region/McRegionRegionIo.h @@ -24,7 +24,7 @@ namespace lodestone::minecraft::java::mcregion::region { // into a Region. The coords are enough information to correctly write // the chunks void write(lodestone::level::Level *c, int version, - const lodestone::level::types::Vec2i &coords, + const lodestone::level::types::Vec2i ®ionCoords, std::ostream &out) const override; const conversion::chunk::ChunkIO * diff --git a/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/mcregion/world/McRegionWorldIo.h b/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/mcregion/world/McRegionWorldIo.h index 483875a..5129bb9 100644 --- a/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/mcregion/world/McRegionWorldIo.h +++ b/projects/Converters/Minecraft/Java/include/Lodestone.Minecraft.Java/mcregion/world/McRegionWorldIo.h @@ -22,6 +22,15 @@ namespace lodestone::minecraft::java::mcregion::world { lodestone::level::world::World *w, int version, const conversion::world::options::AbstractWorldWriteOptions &options) const override; + + const lodestone::conversion::chunk::ChunkIO * + getChunkIO(int version) const override; + + const lodestone::conversion::region::RegionIO * + getRegionIO(int version) const override; + + const lodestone::conversion::player::PlayerIO * + getPlayerIO(int version) const override; }; } // namespace lodestone::minecraft::java::mcregion::world diff --git a/projects/Converters/Minecraft/Java/src/GeneratorTypes.cpp b/projects/Converters/Minecraft/Java/src/GeneratorTypes.cpp new file mode 100644 index 0000000..1940ae2 --- /dev/null +++ b/projects/Converters/Minecraft/Java/src/GeneratorTypes.cpp @@ -0,0 +1,37 @@ +// +// Created by Zero on 11/26/25. +// +#include "Lodestone.Minecraft.Java/GeneratorTypes.h" + +#include + +namespace lodestone::minecraft::java { + + const lodestone::common::registry::Identifier & + GeneratorTypes::generatorIdToIdentifier(const std::string &id) { + switch ( + lodestone::common::util::Math::fnv1a64(id.data(), id.length())) { + default: + case "default"_hash: + return GeneratorTypes::DEFAULT; + case "flat"_hash: + return GeneratorTypes::FLAT; + case "largeBiomes"_hash: + return GeneratorTypes::LARGE_BIOMES; + } + } + + std::string GeneratorTypes::identifierToGeneratorId( + const lodestone::common::registry::Identifier &id, int version) { + switch (lodestone::common::util::Math::fnv1a64(id)) { + default: + case lodestone::common::util::Math::fnv1a64(GeneratorTypes::DEFAULT): + return "default"; + case lodestone::common::util::Math::fnv1a64(GeneratorTypes::FLAT): + return "flat"; + case lodestone::common::util::Math::fnv1a64( + GeneratorTypes::LARGE_BIOMES): + return "largeBiomes"; + } + } +} // namespace lodestone::minecraft::java \ No newline at end of file diff --git a/projects/Converters/Minecraft/Java/src/LodestoneJava.cpp b/projects/Converters/Minecraft/Java/src/LodestoneJava.cpp index 01e89a4..c7b1b6b 100644 --- a/projects/Converters/Minecraft/Java/src/LodestoneJava.cpp +++ b/projects/Converters/Minecraft/Java/src/LodestoneJava.cpp @@ -23,6 +23,7 @@ #include "Lodestone.Minecraft.Java/alpha/world/AlphaWorldIo.h" #include "Lodestone.Minecraft.Java/anvil/jungle/chunk/JungleAnvilChunkIo.h" #include "Lodestone.Minecraft.Java/anvil/jungle/region/JungleAnvilRegionIo.h" +#include "Lodestone.Minecraft.Java/anvil/jungle/world/JungleAnvilWorldIo.h" #include "Lodestone.Minecraft.Java/classic/minev2/MineV2WorldIo.h" #include "Lodestone.Minecraft.Java/mcregion/chunk/McRegionChunkIo.h" #include "Lodestone.Minecraft.Java/mcregion/player/McRegionPlayerIo.h" @@ -103,6 +104,10 @@ namespace lodestone::minecraft::java { .registerRegionIO( identifiers::ANVIL_JUNGLE, std::make_unique()); + + conversion::world::WorldIORegistry::getInstance().registerWorldIO( + identifiers::ANVIL_JUNGLE, + std::make_unique()); } LodestoneJava *LodestoneJava::getInstance() { diff --git a/projects/Converters/Minecraft/Java/src/alpha/world/AlphaWorldIo.cpp b/projects/Converters/Minecraft/Java/src/alpha/world/AlphaWorldIo.cpp index 427d3ea..20a4adf 100644 --- a/projects/Converters/Minecraft/Java/src/alpha/world/AlphaWorldIo.cpp +++ b/projects/Converters/Minecraft/Java/src/alpha/world/AlphaWorldIo.cpp @@ -283,5 +283,23 @@ namespace lodestone::minecraft::java::alpha::world { } } } + const conversion::chunk::ChunkIO * + AlphaWorldIo::getChunkIO(int version) const { + return static_cast( + conversion::chunk::ChunkIORegistry::getInstance().getChunkIO( + identifiers::MCREGION)); + } + + const conversion::region::RegionIO * + AlphaWorldIo::getRegionIO(int version) const { + return nullptr; + } + + const conversion::player::PlayerIO * + AlphaWorldIo::getPlayerIO(int version) const { + return static_cast( + conversion::player::PlayerIORegistry::getInstance().getPlayerIO( + identifiers::ALPHA)); + } } // namespace lodestone::minecraft::java::alpha::world \ No newline at end of file diff --git a/projects/Converters/Minecraft/Java/src/anvil/jungle/chunk/JungleAnvilChunkIo.cpp b/projects/Converters/Minecraft/Java/src/anvil/jungle/chunk/JungleAnvilChunkIo.cpp index 3afcfbe..003bfae 100644 --- a/projects/Converters/Minecraft/Java/src/anvil/jungle/chunk/JungleAnvilChunkIo.cpp +++ b/projects/Converters/Minecraft/Java/src/anvil/jungle/chunk/JungleAnvilChunkIo.cpp @@ -36,6 +36,7 @@ namespace lodestone::minecraft::java::anvil::jungle::chunk { section["Data"].get().as().get().data(); const int8_t *add = nullptr; + // todo handle when lighting doesn't exist const int8_t *skyLight = section["SkyLight"] .get() .as() @@ -54,7 +55,6 @@ namespace lodestone::minecraft::java::anvil::jungle::chunk { const int8_t sy = section["Y"].get().as(); const int lsy = sy * 16; // TODO lighting and entities - for (int cy = 0; cy < 16; cy++) { for (int cz = 0; cz < CHUNK_DEPTH; cz++) { for (int cx = 0; cx < CHUNK_WIDTH; cx++) { diff --git a/projects/Converters/Minecraft/Java/src/anvil/jungle/world/JungleAnvilWorld.cpp b/projects/Converters/Minecraft/Java/src/anvil/jungle/world/JungleAnvilWorld.cpp new file mode 100644 index 0000000..323f6af --- /dev/null +++ b/projects/Converters/Minecraft/Java/src/anvil/jungle/world/JungleAnvilWorld.cpp @@ -0,0 +1,11 @@ +// +// Created by Zero on 11/26/25. +// + +#include "Lodestone.Minecraft.Java/anvil/jungle/world/JungleAnvilWorld.h" + +namespace lodestone::minecraft::java::anvil::jungle::world { + + JungleAnvilWorld::JungleAnvilWorld(const std::string &name) + : McRegionWorld(name) {} +} // namespace lodestone::minecraft::java::anvil::jungle::world \ No newline at end of file diff --git a/projects/Converters/Minecraft/Java/src/anvil/jungle/world/JungleAnvilWorldIo.cpp b/projects/Converters/Minecraft/Java/src/anvil/jungle/world/JungleAnvilWorldIo.cpp new file mode 100644 index 0000000..33130ea --- /dev/null +++ b/projects/Converters/Minecraft/Java/src/anvil/jungle/world/JungleAnvilWorldIo.cpp @@ -0,0 +1,346 @@ +// +// Created by Zero on 11/26/25. +// + +#include "Lodestone.Minecraft.Java/anvil/jungle/world/JungleAnvilWorldIo.h" + +#include + +#include + +#include +#include +#include +#include + +#include "Lodestone.Minecraft.Java/Identifiers.h" +#include "Lodestone.Minecraft.Java/anvil/jungle/chunk/JungleAnvilChunkIo.h" +#include "Lodestone.Minecraft.Java/anvil/jungle/region/JungleAnvilRegionIo.h" +#include "Lodestone.Minecraft.Java/anvil/jungle/world/JungleAnvilWorld.h" +#include "Lodestone.Minecraft.Java/mcregion/player/McRegionPlayer.h" +#include "Lodestone.Minecraft.Java/mcregion/player/McRegionPlayerIo.h" +#include "Lodestone.Minecraft.Java/mcregion/region/McRegionRegion.h" +#include "Lodestone.Minecraft.Java/mcregion/region/McRegionRegionIo.h" +#include +#include +#include + +#include +#include +#include + +namespace lodestone::minecraft::java::anvil::jungle::world { + const conversion::level::LevelIO * + JungleAnvilWorldIo::getLevelIO(int version) const { + return conversion::level::LevelIoRegistry::getInstance().getLevelIO( + identifiers::ANVIL_JUNGLE); + } + + std::unique_ptr JungleAnvilWorldIo::read( + const std::filesystem::path &path, int version, + const conversion::world::options::AbstractWorldReadOptions &options) + const { + if (!std::filesystem::exists(path)) + return nullptr; + + map_t dims; + dims.emplace(0, path); // main dim + + // scan for dims + for (auto &d : std::filesystem::directory_iterator(path)) { + const std::string name = d.path().filename().string(); + + if (!d.is_directory() || !name.starts_with("DIM")) + continue; + + const std::string nm = + name.substr(3, name.size() - 3); // remove dim + + int i = std::stoi(nm); + dims.emplace(i, d.path()); + } + + level::types::Vec3i spawnPos = {0, 64, 0}; + std::unique_ptr world = + std::make_unique(); + if (std::filesystem::exists(path / "level.dat")) { + // TODO we can get DataVersion later and check for fields depending + // on it another way is to just try to get fields and if they dont + // exist then Too Bad. + + std::ifstream dat(path / "level.dat", std::ios::binary); + zlib::izlibstream strm(dat); + + nbt::io::stream_reader nbt(strm); + auto [nm, tag] = nbt.read_compound(); + + nbt::tag_compound &data = + (tag.get()->at("Data").as()); + + std::string name = data["LevelName"].get().as(); + std::unique_ptr w = + std::make_unique(name); + + // todo handle player tag + + int spawnX = data["SpawnX"].get().as(); + int spawnY = data["SpawnY"].get().as(); + int spawnZ = data["SpawnZ"].get().as(); + spawnPos = {spawnX, spawnY, spawnZ}; + + int64_t time = data["Time"].get().as(); + w->setTime(time); + + int rainTime = data["rainTime"].get().as(); + int thunderTime = data["thunderTime"].get().as(); + + w->setRainTime(rainTime); + w->setThunderTime(thunderTime); + + bool raining = data["raining"].get().as(); + bool thundering = data["thundering"].get().as(); + + w->setIsRaining(raining); + w->setIsThundering(thundering); + + int64_t seed = data["RandomSeed"].get().as(); + w->setSeed(seed); + + int ver = data["version"].get().as(); + w->setVersion(ver); + + int64_t lastPlayed = data["LastPlayed"].get().as(); + w->setLastPlayed(lastPlayed); + + LOG_DEBUG(w->toString()); + world = std::move(w); + dat.close(); + } + + if (std::filesystem::exists(path / "players") && + std::filesystem::is_directory(path / "players")) { + auto pio = static_cast( + getPlayerIO(version)); + for (const auto &f : + std::filesystem::directory_iterator(path / "players")) { + if (!std::filesystem::is_regular_file(f)) + continue; + + std::ifstream ifs(f.path(), std::ifstream::binary); + zlib::izlibstream strm(ifs); + + nbt::io::stream_reader nbt(strm); + auto [nm, root] = nbt.read_compound(); + + std::unique_ptr r = + pio->read(f, *root, version); // todo return value? + + LOG_DEBUG(r->toString()); + + world->addPlayer(std::move(r), false); + ifs.close(); + } + } + + auto *io = static_cast( + getRegionIO(version)); + + int t = 2; + // do I need to call exists? + for (auto [id, pth] : dims) { + if (std::filesystem::exists(pth / "region") && + std::filesystem::is_directory(pth / "region")) { + + LOG_DEBUG(pth); + + level::Level *dim = new level::Level(); +#ifdef USE_OPENMP + std::vector e; + for (auto &f : + std::filesystem::directory_iterator(pth / "region")) { + e.push_back(f); + } + +#pragma omp parallel for + for (size_t i = 0; i < e.size(); ++i) { + const auto &f = e[i]; +#else + for (const auto &f : + std::filesystem::directory_iterator(pth / "region")) { +#endif + if (!std::filesystem::is_regular_file(f) || + f.path().extension() != ".mca") + continue; + + level::types::Vec2i coords = + mcregion::region::McRegionRegion::getCoordsFromFilename( + f.path().filename().string()); + + std::ifstream ifs(f.path(), std::ifstream::binary); + + std::unique_ptr r = + io->read(ifs, version, coords); // todo return value? + + LOG_DEBUG(r->toString()); + + dim->merge(std::move(r)); + ifs.close(); + } + + dim->setSpawnPos( + spawnPos); // in beta, only worlds have the spawn position + // get dim (or temp name if conversion unknown) + lodestone::common::registry::Identifier d = + mcregion::player::McRegionPlayer::dimensionIdToIdentifier( + id); + + if (d == level::world::World::Dimension::UNKNOWN) + d = lodestone::common::registry::Identifier( + "lodestone", + ("unknown_dim_" + std::to_string(t)).c_str()); + + world->addLevel( + d, std::unique_ptr( + dim)); // todo move dimension id shit to world + } + t++; + } + + // move players to correct level otherwise they're stuck at correct + // coords in diff level + for (const auto &[name, plr] : world->getPlayers()) { + const mcregion::player::McRegionPlayer *p = + dynamic_cast(plr.get()); + if (!p) + continue; + + if (world->hasLevel(p->getDimension())) + world->movePlayerToLevel(name, p->getDimension(), false); + } + + return world; + } + + void JungleAnvilWorldIo::write( + const std::filesystem::path &path, level::world::World *w, int version, + const conversion::world::options::AbstractWorldWriteOptions &options) + const { + if (!exists(path)) + std::filesystem::create_directories(path); + if (!std::filesystem::is_directory(path)) + throw std::runtime_error( + "Cannot write a world to a path that is not a directory"); + + { + // Leveldat + // TODO incomplete + std::ofstream dat(path / "level.dat", std::ios::binary); + zlib::ozlibstream strm(dat, Z_DEFAULT_COMPRESSION, true); + + nbt::io::stream_writer nbt(strm); + nbt::tag_compound root{}; + nbt::tag_compound data{}; + + data["LevelName"] = w->getName(); + + auto lastPlayed = w->getProperty("lastPlayed"); + data["LastPlayed"] = + lastPlayed + ? lastPlayed + ->as< + level::properties::TemplatedProperty>() + ->getValue() + : static_cast(0); + + auto seed = w->getProperty("seed"); + data["RandomSeed"] = + seed + ? seed->as< + level::properties::TemplatedProperty>() + ->getValue() + : static_cast(0); + + // TODO: Write default player tag here + + level::types::Vec3i sp = w->getDefaultLevel()->getSpawnPos(); + data["SpawnX"] = sp.x; + data["SpawnY"] = sp.y; + data["SpawnZ"] = sp.z; + + auto time = w->getProperty("time"); + data["Time"] = + time + ? time->as< + level::properties::TemplatedProperty>() + ->getValue() + : static_cast(0); + + data["SizeOnDisk"] = static_cast(0); + + root.emplace("Data", data); + nbt.write_tag("", root); + } + // Regions + auto *io = + static_cast( + getRegionIO(version)); + + std::filesystem::path p = path; + + int i = 2; + for (auto &[id, lvl] : w->getLevels()) { + if (const int dim = + mcregion::player::McRegionPlayer::identifierToDimensionId( + id); + dim != 0) { + p = path / + ("DIM" + std::to_string(dim == 0x7FFFFFFF ? i : dim)); + } + i++; + + std::filesystem::path r = p / "region"; + if (!std::filesystem::exists(r)) + std::filesystem::create_directory(r); + + level::types::Bounds3i bounds = lvl->getChunkBounds(); + + for (int rx = bounds.min.x; rx < bounds.max.x; rx += 32 * 32) { + for (int rz = bounds.min.z; rz < bounds.max.z; rz += 32 * 32) { + std::ofstream o(r / ("r." + std::to_string(rx) + "." + + std::to_string(rz) + ".mcr")); + + io->write(lvl.get(), version, {rx, rz}, o); + + o.close(); + } + } + } + + // TODO player data + // TODO settings class for readers & writers, lets us pass a default + // player to put in level.dat too! + // TODO for block states we might be able to make registry that maps + // fields to bits in data byte per block + } + const conversion::chunk::ChunkIO * + JungleAnvilWorldIo::getChunkIO(int version) const { + return static_cast( + conversion::chunk::ChunkIORegistry::getInstance().getChunkIO( + identifiers::ANVIL_JUNGLE)); + } + + const conversion::region::RegionIO * + JungleAnvilWorldIo::getRegionIO(int version) const { + return static_cast( + conversion::region::RegionIORegistry::getInstance().getRegionIO( + identifiers::ANVIL_JUNGLE)); + } + + const conversion::player::PlayerIO * + JungleAnvilWorldIo::getPlayerIO(int version) const { + return static_cast( + conversion::player::PlayerIORegistry::getInstance().getPlayerIO( + identifiers::ANVIL_JUNGLE)); + } + +} // namespace lodestone::minecraft::java::anvil::jungle::world \ No newline at end of file diff --git a/projects/Converters/Minecraft/Java/src/classic/minev1/MineV1LevelIO.cpp b/projects/Converters/Minecraft/Java/src/classic/minev1/MineV1LevelIO.cpp index 05bf040..9936673 100644 --- a/projects/Converters/Minecraft/Java/src/classic/minev1/MineV1LevelIO.cpp +++ b/projects/Converters/Minecraft/Java/src/classic/minev1/MineV1LevelIO.cpp @@ -62,15 +62,15 @@ namespace lodestone::minecraft::java::classic::minev1 { for (int y = 0; y < HEIGHT; y++) { for (int z = 0; z < DEPTH; z++) { for (int x = 0; x < WIDTH; x++) { - const level::block::properties::BlockProperties *b = + const level::block::properties::BlockProperties &b = l->getBlock(x, y, z); uint8_t v = 0; - if (b->getBlock() != + if (b.getBlock() != level::block::BlockRegistry::sDefaultBlock) { const lodestone::conversion::block::data:: AbstractBlockData *bd = - io->convertBlockFromInternal(b); + io->convertBlockFromInternal(&b); v = (bd->as()) ->getId(); diff --git a/projects/Converters/Minecraft/Java/src/classic/minev2/MineV2LevelIO.cpp b/projects/Converters/Minecraft/Java/src/classic/minev2/MineV2LevelIO.cpp index a2b9e45..97ba468 100644 --- a/projects/Converters/Minecraft/Java/src/classic/minev2/MineV2LevelIO.cpp +++ b/projects/Converters/Minecraft/Java/src/classic/minev2/MineV2LevelIO.cpp @@ -82,15 +82,15 @@ namespace lodestone::minecraft::java::classic::minev2 { for (int y = 0; y < h; y++) { for (int z = 0; z < d; z++) { for (int x = 0; x < w; x++) { - const level::block::properties::BlockProperties *b = + const level::block::properties::BlockProperties &b = l->getBlock(x + min.x, y + min.y, z + min.z); uint8_t v = 0; - if (b->getBlock() != + if (b.getBlock() != level::block::BlockRegistry::sDefaultBlock) { if (const lodestone::conversion::block::data:: AbstractBlockData *bl = - bio->convertBlockFromInternal(b)) + bio->convertBlockFromInternal(&b)) v = bl->as() ->getId(); diff --git a/projects/Converters/Minecraft/Java/src/classic/minev2/MineV2WorldIo.cpp b/projects/Converters/Minecraft/Java/src/classic/minev2/MineV2WorldIo.cpp index 38e8590..a39596d 100644 --- a/projects/Converters/Minecraft/Java/src/classic/minev2/MineV2WorldIo.cpp +++ b/projects/Converters/Minecraft/Java/src/classic/minev2/MineV2WorldIo.cpp @@ -85,4 +85,19 @@ namespace lodestone::minecraft::java::classic::minev2 { lio->write(w->getLevel(writeOptions->level), version, bos.getStream()); // todo: VERSION STUFF } + + const lodestone::conversion::chunk::ChunkIO * + MineV2WorldIO::getChunkIO(int version) const { + return nullptr; + } + + const lodestone::conversion::region::RegionIO * + MineV2WorldIO::getRegionIO(int version) const { + return nullptr; + } + + const lodestone::conversion::player::PlayerIO * + MineV2WorldIO::getPlayerIO(int version) const { + return nullptr; + } } // namespace lodestone::minecraft::java::classic::minev2 diff --git a/projects/Converters/Minecraft/Java/src/mcregion/chunk/McRegionChunkIo.cpp b/projects/Converters/Minecraft/Java/src/mcregion/chunk/McRegionChunkIo.cpp index 8ba5b6a..c2e6aa3 100644 --- a/projects/Converters/Minecraft/Java/src/mcregion/chunk/McRegionChunkIo.cpp +++ b/projects/Converters/Minecraft/Java/src/mcregion/chunk/McRegionChunkIo.cpp @@ -122,10 +122,10 @@ namespace lodestone::minecraft::java::mcregion::chunk { for (int cy = 0; cy < CHUNK_HEIGHT; cy++) { const size_t idx = INDEX_XZY(cx, cy, cz, CHUNK_HEIGHT, CHUNK_DEPTH); - const level::block::properties::BlockProperties *b = + const level::block::properties::BlockProperties &b = c->getBlock(cx, cy, cz); #ifdef USE_RISKY_OPTIMIZATIONS - if (b->getBlock() != + if (b.getBlock() != level::block::BlockRegistry::sDefaultBlock) { #endif uint8_t id = 0; @@ -136,7 +136,7 @@ namespace lodestone::minecraft::java::mcregion::chunk { #endif if (const lodestone::conversion::block::data:: NumericBlockData *bl = - bio->convertBlockFromInternal(b) + bio->convertBlockFromInternal(&b) ->as< lodestone::conversion::block:: data::NumericBlockData>()) { diff --git a/projects/Converters/Minecraft/Java/src/mcregion/player/McRegionPlayer.cpp b/projects/Converters/Minecraft/Java/src/mcregion/player/McRegionPlayer.cpp index 8593f55..746ca90 100644 --- a/projects/Converters/Minecraft/Java/src/mcregion/player/McRegionPlayer.cpp +++ b/projects/Converters/Minecraft/Java/src/mcregion/player/McRegionPlayer.cpp @@ -62,8 +62,8 @@ namespace lodestone::minecraft::java::mcregion::player { McRegionPlayer::getProperty(const std::string &name) { switch (lodestone::common::util::Math::fnv1a64(name.data(), name.length())) { - ADD_PROPERTY("sleepTimer", mSleepTimer, short &); - ADD_PROPERTY("sleeping", mIsSleeping, bool &); + ADD_FIELD_PROPERTY("sleepTimer", mSleepTimer); + ADD_FIELD_PROPERTY("sleeping", mIsSleeping); default: return MinecraftPlayer::getProperty(name); } diff --git a/projects/Converters/Minecraft/Java/src/mcregion/region/McRegionRegionIo.cpp b/projects/Converters/Minecraft/Java/src/mcregion/region/McRegionRegionIo.cpp index 0df2746..9787a36 100644 --- a/projects/Converters/Minecraft/Java/src/mcregion/region/McRegionRegionIo.cpp +++ b/projects/Converters/Minecraft/Java/src/mcregion/region/McRegionRegionIo.cpp @@ -99,29 +99,27 @@ namespace lodestone::minecraft::java::mcregion::region { return region; } - void McRegionRegionIO::write(lodestone::level::Level *c, const int version, - const lodestone::level::types::Vec2i &coords, - std::ostream &out) const { + void + McRegionRegionIO::write(lodestone::level::Level *c, const int version, + const lodestone::level::types::Vec2i ®ionCoords, + std::ostream &out) const { bio::stream::BinaryOutputStream bos(out); - const chunk::McRegionChunkIO *chunkIo = - dynamic_cast(getChunkIO(version)); + auto *chunkIo = + static_cast(getChunkIO(version)); bos.fill(0, (4 * 1024) * 2); - const int minX = coords.x << 5; - const int minZ = coords.z << 5; - // since this is such pain with a stream // although doing it like this is messy, I would like to refactor this // sometime. TODO - for (char x = 0; x < 16; x++) { - for (char z = 0; z < 16; z++) { + for (char x = 0; x < 32; x++) { + for (char z = 0; z < 32; z++) { // get chunk coords - int cx = minX + x; - int cz = minZ + z; + int cx = regionCoords.x * 32 + x; + int cz = regionCoords.z * 32 + z; - size_t idx = ((cx % 32) + (cz % 32) * 32) * 4; + const size_t idx = ((cx & 31) + (cz & 31) * 32) * 4; // get our chunk level::chunk::Chunk *ch = c->getChunk(cx, cz); diff --git a/projects/Converters/Minecraft/Java/src/mcregion/world/McRegionWorld.cpp b/projects/Converters/Minecraft/Java/src/mcregion/world/McRegionWorld.cpp index 3b200f7..e101cd8 100644 --- a/projects/Converters/Minecraft/Java/src/mcregion/world/McRegionWorld.cpp +++ b/projects/Converters/Minecraft/Java/src/mcregion/world/McRegionWorld.cpp @@ -52,11 +52,11 @@ namespace lodestone::minecraft::java::mcregion::world { McRegionWorld::getProperty(const std::string &name) { switch (lodestone::common::util::Math::fnv1a64(name.data(), name.length())) { - ADD_PROPERTY("raining", mIsRaining, bool &); - ADD_PROPERTY("rainTime", mRainTime, int32_t &); - ADD_PROPERTY("thundering", mIsThundering, bool &); - ADD_PROPERTY("thunderTime", mThunderTime, int32_t &); - ADD_PROPERTY("version", mVersion, int32_t &); + ADD_FIELD_PROPERTY("raining", mIsRaining); + ADD_FIELD_PROPERTY("rainTime", mRainTime); + ADD_FIELD_PROPERTY("thundering", mIsThundering); + ADD_FIELD_PROPERTY("thunderTime", mThunderTime); + ADD_FIELD_PROPERTY("version", mVersion); default: return MinecraftWorld::getProperty(name); } diff --git a/projects/Converters/Minecraft/Java/src/mcregion/world/McRegionWorldIo.cpp b/projects/Converters/Minecraft/Java/src/mcregion/world/McRegionWorldIo.cpp index 3b40cc4..12a3774 100644 --- a/projects/Converters/Minecraft/Java/src/mcregion/world/McRegionWorldIo.cpp +++ b/projects/Converters/Minecraft/Java/src/mcregion/world/McRegionWorldIo.cpp @@ -8,6 +8,8 @@ #ifdef USE_OPENMP #include #endif +#include + #include #include @@ -22,6 +24,7 @@ #include #include "Lodestone.Minecraft.Java/mcregion/chunk/McRegionChunk.h" +#include "Lodestone.Minecraft.Java/mcregion/chunk/McRegionChunkIo.h" #include "Lodestone.Minecraft.Java/mcregion/player/McRegionPlayer.h" #include "Lodestone.Minecraft.Java/mcregion/player/McRegionPlayerIo.h" #include "Lodestone.Minecraft.Java/mcregion/region/McRegionRegion.h" @@ -121,10 +124,9 @@ namespace lodestone::minecraft::java::mcregion::world { if (std::filesystem::exists(path / "players") && std::filesystem::is_directory(path / "players")) { - const java::mcregion::player::McRegionPlayerIO *pio = static_cast< - const java::mcregion::player::McRegionPlayerIO *>( - lodestone::conversion::player::PlayerIORegistry::getInstance() - .getPlayerIO(java::identifiers::MCREGION)); + const player::McRegionPlayerIO *pio = + static_cast( + getPlayerIO(version)); for (const auto &f : std::filesystem::directory_iterator(path / "players")) { if (!std::filesystem::is_regular_file(f)) @@ -146,10 +148,8 @@ namespace lodestone::minecraft::java::mcregion::world { } } - const java::mcregion::region::McRegionRegionIO *io = - static_cast( - lodestone::conversion::region::RegionIORegistry::getInstance() - .getRegionIO(java::identifiers::MCREGION)); + const region::McRegionRegionIO *io = + static_cast(getRegionIO(version)); int t = 2; // do I need to call exists? @@ -224,8 +224,7 @@ namespace lodestone::minecraft::java::mcregion::world { } void McRegionWorldIo::write( - const std::filesystem::path &path, lodestone::level::world::World *w, - int version, + const std::filesystem::path &path, level::world::World *w, int version, const conversion::world::options::AbstractWorldWriteOptions &options) const { if (!exists(path)) @@ -247,47 +246,46 @@ namespace lodestone::minecraft::java::mcregion::world { data["LevelName"] = w->getName(); - // int spawnX = data["SpawnX"].get().as(); - // int spawnY = data["SpawnY"].get().as(); - // int spawnZ = data["SpawnZ"].get().as(); - // spawnPos = {spawnX, spawnY, spawnZ}; - // - // int64_t time = data["Time"].get().as(); - // w->setTime(time); - // - // int rainTime = data["rainTime"].get().as(); - // int thunderTime = data["thunderTime"].get().as(); - // - // w->setRainTime(rainTime); - // w->setThunderTime(thunderTime); - // - // bool raining = data["raining"].get().as(); - // bool thundering = data["thundering"].get().as(); - // - // w->setIsRaining(raining); - // w->setIsThundering(thundering); - // - // int64_t seed = data["RandomSeed"].get().as(); - // w->setSeed(seed); - // - // int ver = data["version"].get().as(); - // w->setVersion(ver); - // - // int64_t lastPlayed = - // data["LastPlayed"].get().as(); - // w->setLastPlayed(lastPlayed); - // - // int64_t size = data["SizeOnDisk"].get().as(); - // w->setSize(size); + auto lastPlayed = w->getProperty("lastPlayed"); + data["LastPlayed"] = + lastPlayed + ? lastPlayed + ->as< + level::properties::TemplatedProperty>() + ->getValue() + : static_cast(0); + + auto seed = w->getProperty("seed"); + data["RandomSeed"] = + seed + ? seed->as< + level::properties::TemplatedProperty>() + ->getValue() + : static_cast(0); + + // TODO: Write default player tag here + + level::types::Vec3i sp = w->getDefaultLevel()->getSpawnPos(); + data["SpawnX"] = sp.x; + data["SpawnY"] = sp.y; + data["SpawnZ"] = sp.z; + + auto time = w->getProperty("time"); + data["Time"] = + time + ? time->as< + level::properties::TemplatedProperty>() + ->getValue() + : static_cast(0); + + data["SizeOnDisk"] = static_cast(0); root.emplace("Data", data); nbt.write_tag("", root); } // Regions - const java::mcregion::region::McRegionRegionIO *io = - static_cast( - lodestone::conversion::region::RegionIORegistry::getInstance() - .getRegionIO(java::identifiers::MCREGION)); + auto io = + static_cast(getRegionIO(version)); std::filesystem::path p = path; @@ -296,8 +294,8 @@ namespace lodestone::minecraft::java::mcregion::world { if (const int dim = player::McRegionPlayer::identifierToDimensionId(id); dim != 0) { - const int d = dim == 0x7FFFFFFF ? i : dim; - p = path / ("DIM" + std::to_string(d)); + p = path / + ("DIM" + std::to_string(dim == 0x7FFFFFFF ? i : dim)); } i++; @@ -307,8 +305,8 @@ namespace lodestone::minecraft::java::mcregion::world { level::types::Bounds3i bounds = lvl->getChunkBounds(); - for (int rx = bounds.min.x; rx < bounds.max.x; rx += 32 * 32) { - for (int rz = bounds.min.z; rz < bounds.max.z; rz += 32 * 32) { + for (int rx = bounds.min.x >> 5; rx < bounds.max.x >> 5; rx++) { + for (int rz = bounds.min.z >> 5; rz < bounds.max.z >> 5; rz++) { std::ofstream o(r / ("r." + std::to_string(rx) + "." + std::to_string(rz) + ".mcr")); @@ -325,4 +323,25 @@ namespace lodestone::minecraft::java::mcregion::world { // TODO for block states we might be able to make registry that maps // fields to bits in data byte per block } + + const conversion::chunk::ChunkIO * + McRegionWorldIo::getChunkIO(int version) const { + return static_cast( + conversion::chunk::ChunkIORegistry::getInstance().getChunkIO( + identifiers::MCREGION)); + } + + const conversion::region::RegionIO * + McRegionWorldIo::getRegionIO(int version) const { + return static_cast( + conversion::region::RegionIORegistry::getInstance().getRegionIO( + identifiers::MCREGION)); + } + + const conversion::player::PlayerIO * + McRegionWorldIo::getPlayerIO(int version) const { + return static_cast( + conversion::player::PlayerIORegistry::getInstance().getPlayerIO( + identifiers::MCREGION)); + } } // namespace lodestone::minecraft::java::mcregion::world diff --git a/projects/Libraries/CMakeLists.txt b/projects/Libraries/CMakeLists.txt index c83ff8f..82fe436 100644 --- a/projects/Libraries/CMakeLists.txt +++ b/projects/Libraries/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.30) project(Lodestone VERSION 1.0.0) -set(VERSION_SUFFIX "-dev.34") # used for non-stable versions, otherwise blank +set(VERSION_SUFFIX "-dev.35") # used for non-stable versions, otherwise blank set(CMAKE_CXX_STANDARD 20) if (CMAKE_BUILD_TYPE STREQUAL "Debug") diff --git a/projects/Libraries/Common/CMakeLists.txt b/projects/Libraries/Common/CMakeLists.txt index 483bda5..b45528d 100644 --- a/projects/Libraries/Common/CMakeLists.txt +++ b/projects/Libraries/Common/CMakeLists.txt @@ -18,6 +18,16 @@ set(FILES src/util/Math.cpp include/Lodestone.Common/util/Math.h include/Lodestone.Common/util/Logging.h + src/storage/bits/BitsArray.cpp + include/Lodestone.Common/storage/bits/BitsArray.h + include/Lodestone.Common/storage/bits/ImmutableBitsArray.h + src/storage/bits/ImmutableBitsArray.cpp + src/storage/bits/AbstractBitsArray.cpp + include/Lodestone.Common/storage/bits/AbstractBitsArray.h + include/Lodestone.Common/storage/palette/PalletizedStorage.tpp + include/Lodestone.Common/storage/palette/PalletizedStorage.h + include/Lodestone.Common/exception/PaletteIndexTooLargeException.h + include/Lodestone.Common/exception/InvalidPaletteReferenceCountException.h ) add_library(Lodestone.Common OBJECT ${FILES}) diff --git a/projects/Libraries/Common/include/Lodestone.Common/exception/InvalidPaletteReferenceCountException.h b/projects/Libraries/Common/include/Lodestone.Common/exception/InvalidPaletteReferenceCountException.h new file mode 100644 index 0000000..22552a8 --- /dev/null +++ b/projects/Libraries/Common/include/Lodestone.Common/exception/InvalidPaletteReferenceCountException.h @@ -0,0 +1,16 @@ +// +// Created by DexrnZacAttack on 1/9/26 using zPc-i2. +// +#ifndef LODESTONE_INVALIDPALETTEREFERENCECOUNTEXCEPTION_H +#define LODESTONE_INVALIDPALETTEREFERENCECOUNTEXCEPTION_H +#include + +namespace lodestone::common::exception { + class InvalidPaletteReferenceCountException : public std::exception { + const char *what() const noexcept override { + return "Invalid palette reference count"; + }; + }; +} + +#endif // LODESTONE_INVALIDPALETTEREFERENCECOUNTEXCEPTION_H diff --git a/projects/Libraries/Common/include/Lodestone.Common/exception/PaletteIndexTooLargeException.h b/projects/Libraries/Common/include/Lodestone.Common/exception/PaletteIndexTooLargeException.h new file mode 100644 index 0000000..bcb8324 --- /dev/null +++ b/projects/Libraries/Common/include/Lodestone.Common/exception/PaletteIndexTooLargeException.h @@ -0,0 +1,16 @@ +// +// Created by DexrnZacAttack on 1/9/26 using zPc-i2. +// +#ifndef LODESTONE_PALETTEINDEXTOOLARGEEXCEPTION_H +#define LODESTONE_PALETTEINDEXTOOLARGEEXCEPTION_H +#include + +namespace lodestone::common::exception { + class PaletteIndexTooLargeException : public std::exception { + const char *what() const noexcept override { + return "Index palette too large"; + }; + }; +} + +#endif // LODESTONE_PALETTEINDEXTOOLARGEEXCEPTION_H \ No newline at end of file diff --git a/projects/Libraries/Common/include/Lodestone.Common/registry/Identifier.h b/projects/Libraries/Common/include/Lodestone.Common/registry/Identifier.h index ac441bf..1f6c365 100644 --- a/projects/Libraries/Common/include/Lodestone.Common/registry/Identifier.h +++ b/projects/Libraries/Common/include/Lodestone.Common/registry/Identifier.h @@ -7,6 +7,8 @@ #include #include +#include "Lodestone.Common/util/Math.h" + // this class required me to upgrade to c++20 namespace lodestone::common::registry { class Identifier : public string::StringSerializable { @@ -31,8 +33,9 @@ namespace lodestone::common::registry { constexpr std::string toString() const override { return getString(); }; constexpr bool operator==(const Identifier &rhs) const noexcept { - return this->mName == rhs.mName && - this->mNamespace == rhs.mNamespace; + return util::Math::strcmpConstexpr(this->mName, rhs.mName) && + util::Math::strcmpConstexpr(this->mNamespace, + rhs.mNamespace); } constexpr operator std::string() const noexcept override { diff --git a/projects/Libraries/Level/include/Lodestone.Level/types/AbstractNibbleArray.h b/projects/Libraries/Common/include/Lodestone.Common/storage/bits/AbstractBitsArray.h similarity index 78% rename from projects/Libraries/Level/include/Lodestone.Level/types/AbstractNibbleArray.h rename to projects/Libraries/Common/include/Lodestone.Common/storage/bits/AbstractBitsArray.h index 02f3107..611c632 100644 --- a/projects/Libraries/Level/include/Lodestone.Level/types/AbstractNibbleArray.h +++ b/projects/Libraries/Common/include/Lodestone.Common/storage/bits/AbstractBitsArray.h @@ -4,10 +4,10 @@ #ifndef LODESTONE_ABSTRACTNIBBLEARRAY_H #define LODESTONE_ABSTRACTNIBBLEARRAY_H -namespace lodestone::level::types { - class AbstractNibbleArray { +namespace lodestone::common::storage::bits { + class AbstractBitsArray { public: - virtual ~AbstractNibbleArray() = default; + virtual ~AbstractBitsArray() = default; virtual int getIndex(int x, int y, int z) const = 0; virtual int getNibble(int x, int y, int z) const = 0; diff --git a/projects/Libraries/Level/include/Lodestone.Level/types/NibbleArray.h b/projects/Libraries/Common/include/Lodestone.Common/storage/bits/BitsArray.h similarity index 65% rename from projects/Libraries/Level/include/Lodestone.Level/types/NibbleArray.h rename to projects/Libraries/Common/include/Lodestone.Common/storage/bits/BitsArray.h index cce160d..5c34e24 100644 --- a/projects/Libraries/Level/include/Lodestone.Level/types/NibbleArray.h +++ b/projects/Libraries/Common/include/Lodestone.Common/storage/bits/BitsArray.h @@ -6,15 +6,15 @@ #define LODESTONE_NIBBLEARRAY_H #include -#include "Lodestone.Level/types/AbstractNibbleArray.h" +#include "Lodestone.Common/storage/bits/AbstractBitsArray.h" -namespace lodestone::level::types { +namespace lodestone::common::storage::bits { - class NibbleArray : public AbstractNibbleArray { + class BitsArray : public AbstractBitsArray { public: - NibbleArray(int length, int bits); - NibbleArray(uint8_t *data, int bits); - ~NibbleArray() override; + BitsArray(int length, int bits); + BitsArray(uint8_t *data, int bits); + ~BitsArray() override; int getIndex(int x, int y, int z) const override; int getNibble(int x, int y, int z) const override; diff --git a/projects/Libraries/Level/include/Lodestone.Level/types/EmptyNibbleArray.h b/projects/Libraries/Common/include/Lodestone.Common/storage/bits/ImmutableBitsArray.h similarity index 61% rename from projects/Libraries/Level/include/Lodestone.Level/types/EmptyNibbleArray.h rename to projects/Libraries/Common/include/Lodestone.Common/storage/bits/ImmutableBitsArray.h index f1acba7..82ff253 100644 --- a/projects/Libraries/Level/include/Lodestone.Level/types/EmptyNibbleArray.h +++ b/projects/Libraries/Common/include/Lodestone.Common/storage/bits/ImmutableBitsArray.h @@ -3,15 +3,15 @@ // #ifndef LODESTONE_EMPTYNIBBLEARRAY_H #define LODESTONE_EMPTYNIBBLEARRAY_H -#include "Lodestone.Level/types/NibbleArray.h" +#include "Lodestone.Common/storage/bits/AbstractBitsArray.h" -namespace lodestone::level::types { - class EmptyNibbleArray : public AbstractNibbleArray { +namespace lodestone::common::storage::bits { + class ImmutableBitsArray : public AbstractBitsArray { protected: - EmptyNibbleArray() = default; + ImmutableBitsArray() = default; public: - static EmptyNibbleArray *getInstance(); + static ImmutableBitsArray *getInstance(); int getIndex(int x, int y, int z) const override; int getNibble(int x, int y, int z) const override; diff --git a/projects/Libraries/Common/include/Lodestone.Common/storage/palette/PalletizedStorage.h b/projects/Libraries/Common/include/Lodestone.Common/storage/palette/PalletizedStorage.h new file mode 100644 index 0000000..2b73259 --- /dev/null +++ b/projects/Libraries/Common/include/Lodestone.Common/storage/palette/PalletizedStorage.h @@ -0,0 +1,69 @@ +// +// Created by DexrnZacAttack on 11/27/25 using zPc-i2. +// +#ifndef LODESTONE_PALLETIZEDSTORAGE_H +#define LODESTONE_PALLETIZEDSTORAGE_H + +#include +#include +#include + +#include +#include +#include "Lodestone.Common/exception/PaletteIndexTooLargeException.h" +#include "Lodestone.Common/exception/InvalidPaletteReferenceCountException.h" +#include "Lodestone.Common/string/StringSerializable.h" + +namespace lodestone::common::storage::palette { + // thanks danil for allowing us to port your code + // modified slightly to allow for any arbitrary object to be stored + // also based off of https://www.longor.net/articles/voxel-palette-compression-reddit + template + class PalletizedStorage : public string::StringSerializable { + public: + struct PaletteEntry { + T value; + int references; + }; + + explicit PalletizedStorage(int capacity); + explicit PalletizedStorage(int capacity, T fillWith); + + void setValue(int index, T value); + T getCopy(int index) const; + + void fill(T value); + + const T &getValue(int index) const; + + size_t getNewSize() const; + + // allows for getting the object reference but not write to it (since writing will modify ALL instances, because indexes will point to that one object) + const T &operator[](int index) const; + + constexpr std::string toString() const override { + return std::string("PalletizedStorage{") + + "capacity=" + std::to_string(mCapacity) + + ", paletteSize=" + std::to_string(mPaletteSize) + + ", indiceCount=" + std::to_string(mIndices.size()); + }; + protected: + int getPaletteIndex(int index) const; + void setPaletteIndex(int index, int value); + + int obtainPaletteEntry(); + void grow(); + private: + // todo do we want array pool? + std::vector mIndices; + std::vector mPalette; + + const int mCapacity; + int mPaletteSize = 0; + int mIndexBits = 1; + }; + +#include "Lodestone.Common/storage/palette/PalletizedStorage.tpp" +} + +#endif // LODESTONE_PALLETIZEDSTORAGE_H diff --git a/projects/Libraries/Common/include/Lodestone.Common/storage/palette/PalletizedStorage.tpp b/projects/Libraries/Common/include/Lodestone.Common/storage/palette/PalletizedStorage.tpp new file mode 100644 index 0000000..0b62512 --- /dev/null +++ b/projects/Libraries/Common/include/Lodestone.Common/storage/palette/PalletizedStorage.tpp @@ -0,0 +1,189 @@ +// +// Created by DexrnZacAttack on 11/28/25 using zPc-i2. +// +#ifndef PALLETIZEDSTORAGE_TPP +#define PALLETIZEDSTORAGE_TPP + +// TODO we need to document this whole file since I don't really understand the logic behind it + +template +PalletizedStorage::PalletizedStorage(const int capacity) : mCapacity(capacity) { + fill(T{}); +} + +template +PalletizedStorage::PalletizedStorage(const int capacity, T fillWith) : mCapacity(capacity) { + fill(fillWith); +} + +template +void PalletizedStorage::setValue(int index, T value) { + int idx = getPaletteIndex(index); + PaletteEntry &cur = mPalette[idx]; + + if (cur.references <= 0) + throw exception::InvalidPaletteReferenceCountException(); + + --cur.references; + + for (int i = 0; i < mPalette.size(); i++) { + if (PaletteEntry &e = mPalette[i]; e.value == value) { + setPaletteIndex(index, i); + ++e.references; + return; + } + } + + if (cur.references == 0) { + cur = { + std::move(value), + 1 + }; + + return; + } + + int n = obtainPaletteEntry(); + mPalette[n] = { + std::move(value), + 1 + }; + + setPaletteIndex(index, n); + mPaletteSize++; +} + +template +T PalletizedStorage::getCopy(int index) const { + return mPalette[getPaletteIndex(index)].value; +} + +template +const T &PalletizedStorage::getValue(int index) const { + return mPalette[getPaletteIndex(index)].value; +} + +template +size_t PalletizedStorage::getNewSize() const { + return (mCapacity * mIndexBits + 7) >> 3; +} + +template +const T & PalletizedStorage::operator[](int index) const { + return mPalette[getPaletteIndex(index)].value; +} + +template +void PalletizedStorage::fill(T value) +{ + mIndices.assign(getNewSize(), 0); + mPalette.clear(); + mPalette.resize(1); + + mPalette[0] = { value, mCapacity }; + + mIndexBits = 0; + mPaletteSize = 1; +} + +template +int PalletizedStorage::getPaletteIndex(int index) const { + // https://github.com/Pannoniae/BlockGame/blob/2e02356c73dd927a09c4299b41a13cbad972a57f/src/world/chunk/PaletteBlockData.cs#L145 + // Permission was given from Pannoniae to continue porting this code + switch (mIndexBits) { + case 0: return 0; + case 1: return (mIndices[index >> 3] >> (index & 7)) & 1; + case 2: return (mIndices[index >> 2] >> ((index & 3) << 1)) & 3; + case 4: return (mIndices[index >> 1] >> ((index & 1) << 2)) & 15; + case 8: return mIndices[index]; + case 16: { + const int idx = index << 1; + return (mIndices[idx] << 8) + | (mIndices[idx + 1]); + } + case 32: { + const int idx = index << 2; + return (mIndices[idx] << 24) + | (mIndices[idx + 1] << 16) + | (mIndices[idx + 2] << 8) + | (mIndices[idx + 3]); + } + default: throw exception::PaletteIndexTooLargeException(); + } +} + +template +void PalletizedStorage::setPaletteIndex(int index, int value) { + // https://github.com/Pannoniae/BlockGame/blob/2e02356c73dd927a09c4299b41a13cbad972a57f/src/world/chunk/PaletteBlockData.cs#L185 + // Permission was given from Pannoniae to continue porting this code + switch (mIndexBits) + { + case 0: + return; + case 1: + mIndices[index >> 3] = static_cast((mIndices[index >> 3] & ~(1 << (index & 7))) | + ((value & 1) << (index & 7))); + return; + case 2: + mIndices[index >> 2] = static_cast((mIndices[index >> 2] & ~(3 << ((index & 3) << 1))) | + ((value & 3) << ((index & 3) << 1))); + return; + case 4: + mIndices[index >> 1] = static_cast((mIndices[index >> 1] & ~(15 << ((index & 1) << 2))) | + ((value & 15) << ((index & 1) << 2))); + return; + case 8: + mIndices[index] = static_cast(value); + return; + case 16: { + const int idx = index << 1; + mIndices[idx ] = static_cast(value & 0xFF); + mIndices[idx + 1] = static_cast((value >> 8) & 0xFF); + return; + } + case 32: { + const int idx = index << 2; + mIndices[idx ] = static_cast(value & 0xFF); + mIndices[idx + 1] = static_cast((value >> 8) & 0xFF); + mIndices[idx + 2] = static_cast((value >> 16) & 0xFF); + mIndices[idx + 3] = static_cast((value >> 24) & 0xFF); + + return; + } + default: + throw exception::PaletteIndexTooLargeException(); + } +} + +template +int PalletizedStorage::obtainPaletteEntry() { + while (true) { + for (int i = 0; i < mPalette.size(); i++) + if (mPalette[i].references == 0) return i; + + this->grow(); + } +} + +template +void PalletizedStorage::grow() { + if (mIndexBits >= 32) + throw exception::PaletteIndexTooLargeException(); + + std::vector indices(mCapacity); + for (int i = 0; i < mCapacity; ++i) + indices[i] = getPaletteIndex(i); + + mIndexBits = (mIndexBits == 0) ? 1 : (mIndexBits << 1); // it implodes if I don't do this + + std::vector n(1 << mIndexBits); + for (int i = 0; i < mPaletteSize; ++i) + n[i] = std::move(mPalette[i]); + + mPalette = std::move(n); + mIndices.assign(getNewSize(), 0); + + for (int i = 0; i < mCapacity; ++i) + setPaletteIndex(i, indices[i]); +} +#endif // PALLETIZEDSTORAGE_TPP diff --git a/projects/Libraries/Common/include/Lodestone.Common/util/Math.h b/projects/Libraries/Common/include/Lodestone.Common/util/Math.h index cb272e8..7be30df 100644 --- a/projects/Libraries/Common/include/Lodestone.Common/util/Math.h +++ b/projects/Libraries/Common/include/Lodestone.Common/util/Math.h @@ -32,6 +32,10 @@ namespace lodestone::common::util { return h; } + static constexpr uint64_t fnv1a64(const std::string &s) { + return fnv1a64(s.data(), s.length()); + } + /** Gets a random number * * @return A random number @@ -44,6 +48,15 @@ namespace lodestone::common::util { * @return String of base36 of value */ static std::string base36(int value); + + static constexpr bool strcmpConstexpr(const char *rhs, const char *lhs) { + while (*rhs || *lhs) { + if (*rhs++ != *lhs++) + return false; + } + + return true; + } }; } // namespace lodestone::common::util diff --git a/projects/Libraries/Common/src/storage/bits/AbstractBitsArray.cpp b/projects/Libraries/Common/src/storage/bits/AbstractBitsArray.cpp new file mode 100644 index 0000000..5268765 --- /dev/null +++ b/projects/Libraries/Common/src/storage/bits/AbstractBitsArray.cpp @@ -0,0 +1,6 @@ +// +// Created by DexrnZacAttack on 11/26/25 using zPc-i2. +// +#include "Lodestone.Common/storage/bits/AbstractBitsArray.h" + +namespace lodestone::common::storage::bits {} \ No newline at end of file diff --git a/projects/Libraries/Level/src/types/NibbleArray.cpp b/projects/Libraries/Common/src/storage/bits/BitsArray.cpp similarity index 66% rename from projects/Libraries/Level/src/types/NibbleArray.cpp rename to projects/Libraries/Common/src/storage/bits/BitsArray.cpp index 5807d5b..9d7628f 100644 --- a/projects/Libraries/Level/src/types/NibbleArray.cpp +++ b/projects/Libraries/Common/src/storage/bits/BitsArray.cpp @@ -2,27 +2,26 @@ // Created by Zero on 11/25/25. // -#include "Lodestone.Level/types/NibbleArray.h" +#include "Lodestone.Common/storage/bits/BitsArray.h" -namespace lodestone::level::types { - - NibbleArray::NibbleArray(const int length, const int bits) { +namespace lodestone::common::storage::bits { + BitsArray::BitsArray(const int length, const int bits) { this->mData = new uint8_t[length >> 1]{}; this->mBits = bits; } - NibbleArray::NibbleArray(uint8_t *data, const int bits) { + BitsArray::BitsArray(uint8_t *data, const int bits) { this->mData = data; this->mBits = bits; } - NibbleArray::~NibbleArray() { delete this->mData; } + BitsArray::~BitsArray() { delete this->mData; } - int NibbleArray::getIndex(const int x, const int y, const int z) const { + int BitsArray::getIndex(const int x, const int y, const int z) const { return y << (this->mBits + 4) | z << this->mBits | x; } - int NibbleArray::getNibble(const int x, const int y, const int z) const { + int BitsArray::getNibble(const int x, const int y, const int z) const { const int index = getIndex(x, y, z); if ((index & 1) == 0) { @@ -32,7 +31,7 @@ namespace lodestone::level::types { return this->mData[index >> 1] >> this->mBits & 0xF; } - void NibbleArray::setNibble(const int x, const int y, const int z, + void BitsArray::setNibble(const int x, const int y, const int z, const int value) { const int index = getIndex(x, y, z); diff --git a/projects/Libraries/Common/src/storage/bits/ImmutableBitsArray.cpp b/projects/Libraries/Common/src/storage/bits/ImmutableBitsArray.cpp new file mode 100644 index 0000000..84adcf5 --- /dev/null +++ b/projects/Libraries/Common/src/storage/bits/ImmutableBitsArray.cpp @@ -0,0 +1,18 @@ +// +// Created by Zero on 11/25/25. +// +#include "Lodestone.Common/storage/bits/ImmutableBitsArray.h" + +namespace lodestone::common::storage::bits { + ImmutableBitsArray *ImmutableBitsArray::getInstance() { + static ImmutableBitsArray sInstance; + return &sInstance; + } + + int ImmutableBitsArray::getIndex(int x, int y, int z) const { return 0; } + + int ImmutableBitsArray::getNibble(int x, int y, int z) const { return 0; } + + void ImmutableBitsArray::setNibble(const int x, const int y, const int z, + const int value) {} +} // namespace lodestone::level::types \ No newline at end of file diff --git a/projects/Libraries/Common/src/util/Math.cpp b/projects/Libraries/Common/src/util/Math.cpp index 4620f34..3e06a8d 100644 --- a/projects/Libraries/Common/src/util/Math.cpp +++ b/projects/Libraries/Common/src/util/Math.cpp @@ -3,6 +3,9 @@ // #include "Lodestone.Common/util/Math.h" +#include +#include + namespace lodestone::common::util { std::random_device Math::sRd; std::mt19937_64 Math::sRand(sRd()); diff --git a/projects/Libraries/Conversion/include/Lodestone.Conversion/world/WorldIO.h b/projects/Libraries/Conversion/include/Lodestone.Conversion/world/WorldIO.h index c1518e2..3b5b84d 100644 --- a/projects/Libraries/Conversion/include/Lodestone.Conversion/world/WorldIO.h +++ b/projects/Libraries/Conversion/include/Lodestone.Conversion/world/WorldIO.h @@ -3,7 +3,11 @@ // #ifndef LODESTONE_WORLDIO_H #define LODESTONE_WORLDIO_H +#include "Lodestone.Conversion/chunk/ChunkIO.h" #include "Lodestone.Conversion/level/LevelIO.h" +#include "Lodestone.Conversion/player/PlayerIO.h" +#include "Lodestone.Conversion/region/RegionIO.h" + #include namespace lodestone::conversion::world { @@ -14,6 +18,18 @@ namespace lodestone::conversion::world { /** Gets the corresponding LevelIO */ virtual const lodestone::conversion::level::LevelIO * getLevelIO(int version) const = 0; + + /** Gets the corresponding ChunkIO */ + virtual const lodestone::conversion::chunk::ChunkIO * + getChunkIO(int version) const = 0; + + /** Gets the corresponding RegionIO */ + virtual const lodestone::conversion::region::RegionIO * + getRegionIO(int version) const = 0; + + /** Gets the corresponding PlayerIO */ + virtual const lodestone::conversion::player::PlayerIO * + getPlayerIO(int version) const = 0; }; } // namespace lodestone::conversion::world diff --git a/projects/Libraries/Level/CMakeLists.txt b/projects/Libraries/Level/CMakeLists.txt index 40659c5..db2f570 100644 --- a/projects/Libraries/Level/CMakeLists.txt +++ b/projects/Libraries/Level/CMakeLists.txt @@ -26,7 +26,7 @@ set(FILES src/block/properties/BlockProperties.cpp include/Lodestone.Level/block/properties/BlockProperties.h src/chunk/section/EmptySection.cpp - include/Lodestone.Level/chunk/section/EmptySection.h + include/Lodestone.Level/chunk/section/ImmutableSection.h src/chunk/section/Section.cpp include/Lodestone.Level/chunk/section/Section.h include/Lodestone.Level/chunk/section/LevelSection.h @@ -36,7 +36,7 @@ set(FILES src/chunk/LevelChunk.cpp include/Lodestone.Level/chunk/LevelChunk.h src/chunk/EmptyChunk.cpp - include/Lodestone.Level/chunk/EmptyChunk.h + include/Lodestone.Level/chunk/ImmutableChunk.h src/world/World.cpp include/Lodestone.Level/world/World.h @@ -69,17 +69,12 @@ set(FILES include/Lodestone.Level/Identifiers.h include/Lodestone.Level/properties/TemplatedProperty.h include/Lodestone.Level/item/Items.h - src/block/properties/EmptyBlockProperties.cpp - include/Lodestone.Level/block/properties/EmptyBlockProperties.h - src/types/NibbleArray.cpp - include/Lodestone.Level/types/NibbleArray.h - include/Lodestone.Level/types/EmptyNibbleArray.h - src/types/EmptyNibbleArray.cpp + src/block/properties/ImmutableBlockProperties.cpp + include/Lodestone.Level/block/properties/ImmutableBlockProperties.h include/Lodestone.Level/properties/ReflectiveProperties.h - include/Lodestone.Level/properties/OptionalTemplatedProperty.h src/properties/ReflectiveProperties.cpp - src/types/AbstractNibbleArray.cpp - include/Lodestone.Level/types/AbstractNibbleArray.h + include/Lodestone.Level/block/blocks/TranslucentBlock.h + include/Lodestone.Level/block/blocks/AirBlock.h ) # if (CMAKE_BUILD_TYPE STREQUAL "Debug") diff --git a/projects/Libraries/Level/include/Lodestone.Level/Level.h b/projects/Libraries/Level/include/Lodestone.Level/Level.h index 017d64d..9cac620 100644 --- a/projects/Libraries/Level/include/Lodestone.Level/Level.h +++ b/projects/Libraries/Level/include/Lodestone.Level/Level.h @@ -24,7 +24,7 @@ namespace lodestone::level { public: bool isChunkInBounds(const types::Vec2i &coords) override; - block::properties::BlockProperties * + const block::properties::BlockProperties & getBlock(signed_size_t x, signed_size_t y, signed_size_t z); void setBlock(block::properties::BlockProperties &&blk, signed_size_t x, @@ -48,13 +48,13 @@ namespace lodestone::level { void setHeightAtCreate(int16_t h, signed_size_t x, signed_size_t z, int height = 256); - const block::properties::BlockProperties * + const block::properties::BlockProperties & getBlockmapBlockAt(signed_size_t x, signed_size_t z) const; - void setBlockmapBlockAt(block::properties::BlockProperties *b, + void setBlockmapBlockAt(const block::properties::BlockProperties &b, signed_size_t x, signed_size_t z); - void setBlockmapBlockAtCreate(block::properties::BlockProperties *b, + void setBlockmapBlockAtCreate(const block::properties::BlockProperties &b, signed_size_t x, signed_size_t z, int height = 256); diff --git a/projects/Libraries/Level/include/Lodestone.Level/block/Block.h b/projects/Libraries/Level/include/Lodestone.Level/block/Block.h index 520ef1a..2fffeac 100644 --- a/projects/Libraries/Level/include/Lodestone.Level/block/Block.h +++ b/projects/Libraries/Level/include/Lodestone.Level/block/Block.h @@ -17,16 +17,15 @@ namespace lodestone::level::block { class Block : public common::string::StringSerializable { public: - constexpr Block(const lodestone::common::registry::Identifier *id, + constexpr Block(const common::registry::Identifier *id, const material::Material &material) : mId(id), mMaterial(material) { - this->mItem = - new lodestone::level::item::block::BlockItem(id, this); + this->mItem = new item::block::BlockItem(id, this); }; constexpr ~Block() override = default; - constexpr const lodestone::common::registry::Identifier *getID() const { + constexpr const common::registry::Identifier *getID() const { return mId; }; @@ -35,7 +34,7 @@ namespace lodestone::level::block { constexpr material::Material getMaterial() const { return mMaterial; } std::string toString() const override { - return (common::string::OperatorStringBuilder(typeid(*this))) + return common::string::OperatorStringBuilder(typeid(*this)) .addField("id", *mId) ->addField("material", mMaterial.toString()) ->toString(); @@ -45,6 +44,14 @@ namespace lodestone::level::block { return mItem; } + constexpr virtual bool isTransparent() const { + return false; + } + + constexpr virtual bool heightmapShouldIgnore() const { + return false; + } + private: const lodestone::common::registry::Identifier *mId; const item::block::BlockItem *mItem; diff --git a/projects/Libraries/Level/include/Lodestone.Level/block/BlockRegistry.h b/projects/Libraries/Level/include/Lodestone.Level/block/BlockRegistry.h index 77625a7..37b12f6 100644 --- a/projects/Libraries/Level/include/Lodestone.Level/block/BlockRegistry.h +++ b/projects/Libraries/Level/include/Lodestone.Level/block/BlockRegistry.h @@ -18,7 +18,9 @@ namespace lodestone::level::block { public: #define REGISTER_BLOCK(n, m) {n, new Block(n, m)} +#define REGISTER_DERIVED_BLOCK(n, m, f) {n, new f(n, m)} #define REGISTER_BLOCK_FUNC(n, m) registerBlock(n, new Block(n, m)) +#define REGISTER_DERIVED_BLOCK_FUNC(n, m, f) registerBlock(n, new f(n, m)) static const Block *sDefaultBlock; diff --git a/projects/Libraries/Level/include/Lodestone.Level/block/Blocks.h b/projects/Libraries/Level/include/Lodestone.Level/block/Blocks.h index bf70d99..1465d4d 100644 --- a/projects/Libraries/Level/include/Lodestone.Level/block/Blocks.h +++ b/projects/Libraries/Level/include/Lodestone.Level/block/Blocks.h @@ -11,9 +11,10 @@ namespace lodestone::level::block { #define ADD_BLOCK(name, id) \ static constexpr const lodestone::common::registry::Identifier name = \ lodestone::common::registry::Identifier { \ - "lodestone", id \ + "lodestone", "block/" id \ } + // todo we can replace with builtin EMPTY block since Air might not be what we want across games ADD_BLOCK(AIR, "air"); }; } // namespace lodestone::level::block diff --git a/projects/Libraries/Level/include/Lodestone.Level/block/blocks/AirBlock.h b/projects/Libraries/Level/include/Lodestone.Level/block/blocks/AirBlock.h new file mode 100644 index 0000000..df90f1a --- /dev/null +++ b/projects/Libraries/Level/include/Lodestone.Level/block/blocks/AirBlock.h @@ -0,0 +1,22 @@ +// +// Created by DexrnZacAttack on 1/22/26 using zPc-i2. +// +#ifndef LODESTONE_AIRBLOCK_H +#define LODESTONE_AIRBLOCK_H +#include "Lodestone.Level/block/blocks/TranslucentBlock.h" + +namespace lodestone::level::block::blocks { + class AirBlock : public TranslucentBlock { + public: + constexpr AirBlock(const lodestone::common::registry::Identifier *id, + const lodestone::level::material::Material &material) +: TranslucentBlock(id, material) { + }; + + constexpr bool heightmapShouldIgnore() const override { + return true; + }; + }; +} + +#endif // LODESTONE_AIRBLOCK_H \ No newline at end of file diff --git a/projects/Libraries/Level/include/Lodestone.Level/block/blocks/TranslucentBlock.h b/projects/Libraries/Level/include/Lodestone.Level/block/blocks/TranslucentBlock.h new file mode 100644 index 0000000..75c2d25 --- /dev/null +++ b/projects/Libraries/Level/include/Lodestone.Level/block/blocks/TranslucentBlock.h @@ -0,0 +1,22 @@ +// +// Created by DexrnZacAttack on 1/22/26 using zPc-i2. +// +#ifndef LODESTONE_TRANSLUCENTBLOCK_H +#define LODESTONE_TRANSLUCENTBLOCK_H +#include "Lodestone.Level/block/Block.h" + +namespace lodestone::level::block::blocks { + class TranslucentBlock : public lodestone::level::block::Block { + public: + constexpr TranslucentBlock(const lodestone::common::registry::Identifier *id, + const lodestone::level::material::Material &material) + : Block(id, material) { + }; + + constexpr bool isTransparent() const override { + return true; + } + }; +} + +#endif // LODESTONE_TRANSLUCENTBLOCK_H \ No newline at end of file diff --git a/projects/Libraries/Level/include/Lodestone.Level/block/properties/EmptyBlockProperties.h b/projects/Libraries/Level/include/Lodestone.Level/block/properties/ImmutableBlockProperties.h similarity index 76% rename from projects/Libraries/Level/include/Lodestone.Level/block/properties/EmptyBlockProperties.h rename to projects/Libraries/Level/include/Lodestone.Level/block/properties/ImmutableBlockProperties.h index 8fb8804..694e0fc 100644 --- a/projects/Libraries/Level/include/Lodestone.Level/block/properties/EmptyBlockProperties.h +++ b/projects/Libraries/Level/include/Lodestone.Level/block/properties/ImmutableBlockProperties.h @@ -1,18 +1,18 @@ // // Created by DexrnZacAttack on 11/15/25 using zPc-i2. // -#ifndef LODESTONE_EMPTYBLOCKPROPERTIES_H -#define LODESTONE_EMPTYBLOCKPROPERTIES_H +#ifndef LODESTONE_ImmutableBlockProperties_H +#define LODESTONE_ImmutableBlockProperties_H #include "Lodestone.Level/block/properties/BlockProperties.h" namespace lodestone::level::block::properties { /** Block properties type that cannot be written to */ - class EmptyBlockProperties : public BlockProperties { + class ImmutableBlockProperties : public BlockProperties { private: - EmptyBlockProperties(); + ImmutableBlockProperties(); public: - static EmptyBlockProperties *getInstance(); + static ImmutableBlockProperties *getInstance(); bool hasProperty(const std::string &id) const override; @@ -34,4 +34,4 @@ namespace lodestone::level::block::properties { }; } // namespace lodestone::level::block::properties -#endif // LODESTONE_EMPTYBLOCKPROPERTIES_H +#endif // LODESTONE_ImmutableBlockProperties_H diff --git a/projects/Libraries/Level/include/Lodestone.Level/chunk/Chunk.h b/projects/Libraries/Level/include/Lodestone.Level/chunk/Chunk.h index 2b546ea..b1c7806 100644 --- a/projects/Libraries/Level/include/Lodestone.Level/chunk/Chunk.h +++ b/projects/Libraries/Level/include/Lodestone.Level/chunk/Chunk.h @@ -8,7 +8,7 @@ #include #include "Lodestone.Level/block/BlockRegistry.h" -#include "Lodestone.Level/chunk/section/EmptySection.h" +#include "Lodestone.Level/chunk/section/ImmutableSection.h" #include "Lodestone.Level/types/Vec2.h" namespace lodestone::level::chunk { @@ -64,9 +64,9 @@ namespace lodestone::level::chunk { virtual const int16_t *getHeightmap() const; - virtual const block::properties::BlockProperties **getBlockmap() const; + virtual const block::properties::BlockProperties *getBlockmap() const; - virtual block::properties::BlockProperties *getBlock(int x, int y, + virtual const block::properties::BlockProperties &getBlock(int x, int y, int z) const = 0; /** Sets a block at the given X, Y, and Z coordinates. @@ -87,10 +87,10 @@ namespace lodestone::level::chunk { virtual void setHeightAt(int16_t h, int x, int z); - virtual const block::properties::BlockProperties * + virtual const block::properties::BlockProperties & getBlockmapBlockAt(int x, int z) const; - virtual void setBlockmapBlockAt(block::properties::BlockProperties *b, + virtual void setBlockmapBlockAt(const block::properties::BlockProperties &b, int x, int z); bool hasCoords() const; @@ -127,10 +127,9 @@ namespace lodestone::level::chunk { * * Each x and z coord corresponds to the topmost block's state */ - block::properties::BlockProperties **mBlockmap = - new block::properties::BlockProperties - *[common::constants::CHUNK_WIDTH * - common::constants::CHUNK_DEPTH]{}; + block::properties::BlockProperties *mBlockmap = + new block::properties::BlockProperties[common::constants::CHUNK_WIDTH * + common::constants::CHUNK_DEPTH] {}; // map_t mTileEntities; // map_t mEntities; diff --git a/projects/Libraries/Level/include/Lodestone.Level/chunk/EmptyChunk.h b/projects/Libraries/Level/include/Lodestone.Level/chunk/ImmutableChunk.h similarity index 74% rename from projects/Libraries/Level/include/Lodestone.Level/chunk/EmptyChunk.h rename to projects/Libraries/Level/include/Lodestone.Level/chunk/ImmutableChunk.h index 5d6ee8f..f49a4c7 100644 --- a/projects/Libraries/Level/include/Lodestone.Level/chunk/EmptyChunk.h +++ b/projects/Libraries/Level/include/Lodestone.Level/chunk/ImmutableChunk.h @@ -6,15 +6,15 @@ #include "Lodestone.Level/chunk/Chunk.h" namespace lodestone::level::chunk { - class EmptyChunk : public Chunk { + class ImmutableChunk : public Chunk { public: - static EmptyChunk *getInstance(); + static ImmutableChunk *getInstance(); - EmptyChunk() : Chunk() {} + ImmutableChunk() : Chunk() {} - explicit EmptyChunk(const types::Vec2i &coords) : Chunk(coords) {} + explicit ImmutableChunk(const types::Vec2i &coords) : Chunk(coords) {} - EmptyChunk(ChunkContainer *container, const types::Vec2i &coords) + ImmutableChunk(ChunkContainer *container, const types::Vec2i &coords) : Chunk(container, coords) {} void calculateHeightmap() override; @@ -23,7 +23,7 @@ namespace lodestone::level::chunk { section::Section *getSection(int y) const override; - block::properties::BlockProperties *getBlock(int x, int y, + const block::properties::BlockProperties &getBlock(int x, int y, int z) const override; section::Section *getSectionCreate(int y) override; @@ -38,7 +38,7 @@ namespace lodestone::level::chunk { void calculateBlockmap() override; - void setBlockmapBlockAt(block::properties::BlockProperties *h, int x, + void setBlockmapBlockAt(const block::properties::BlockProperties &h, int x, int z) override; void calculateMaps() override; diff --git a/projects/Libraries/Level/include/Lodestone.Level/chunk/LevelChunk.h b/projects/Libraries/Level/include/Lodestone.Level/chunk/LevelChunk.h index de8332e..38d5715 100644 --- a/projects/Libraries/Level/include/Lodestone.Level/chunk/LevelChunk.h +++ b/projects/Libraries/Level/include/Lodestone.Level/chunk/LevelChunk.h @@ -44,7 +44,7 @@ namespace lodestone::level::chunk { void calculateMapsAtColumn(int x, int z, int height) override; - block::properties::BlockProperties * + const block::properties::BlockProperties & getBlock(const int x, const int y, const int z) const override; void setBlock(block::properties::BlockProperties &&blk, int x, int y, diff --git a/projects/Libraries/Level/include/Lodestone.Level/chunk/section/EmptySection.h b/projects/Libraries/Level/include/Lodestone.Level/chunk/section/ImmutableSection.h similarity index 59% rename from projects/Libraries/Level/include/Lodestone.Level/chunk/section/EmptySection.h rename to projects/Libraries/Level/include/Lodestone.Level/chunk/section/ImmutableSection.h index 198854f..7700e8a 100644 --- a/projects/Libraries/Level/include/Lodestone.Level/chunk/section/EmptySection.h +++ b/projects/Libraries/Level/include/Lodestone.Level/chunk/section/ImmutableSection.h @@ -7,27 +7,29 @@ #include "Lodestone.Level/block/properties/BlockProperties.h" #include "Lodestone.Level/chunk/section/LevelSection.h" #include "Lodestone.Level/chunk/section/Section.h" -#include "Lodestone.Level/types/EmptyNibbleArray.h" +#include namespace lodestone::level::chunk::section { /** Immutable section, used in place of returning empty/null LevelSection */ - class EmptySection : public Section { + class ImmutableSection : public Section { + private: + static const common::storage::palette::PalletizedStorage EMPTY_STORAGE; public: - static EmptySection *getInstance(); + static ImmutableSection *getInstance(); SectionType getType() override; - const block::properties::BlockProperties *getBlocks() override; + const common::storage::palette::PalletizedStorage &getStorage() override; - types::AbstractNibbleArray *getBlockLight() override; + lodestone::common::storage::bits::AbstractBitsArray *getBlockLight() override; - types::AbstractNibbleArray *getSkyLight() override; + lodestone::common::storage::bits::AbstractBitsArray *getSkyLight() override; void setBlockLight(int x, int y, int z, uint8_t l) override; void setSkyLight(int x, int y, int z, uint8_t l) override; - block::properties::BlockProperties * + const block::properties::BlockProperties & getBlock(const int x, const int y, const int z) const override; void setBlock(block::properties::BlockProperties &&blk, int x, int y, diff --git a/projects/Libraries/Level/include/Lodestone.Level/chunk/section/LevelSection.h b/projects/Libraries/Level/include/Lodestone.Level/chunk/section/LevelSection.h index 3cbe60f..d471448 100644 --- a/projects/Libraries/Level/include/Lodestone.Level/chunk/section/LevelSection.h +++ b/projects/Libraries/Level/include/Lodestone.Level/chunk/section/LevelSection.h @@ -6,47 +6,48 @@ #include +#include #include "Lodestone.Level/block/properties/BlockProperties.h" +#include "Lodestone.Level/block/properties/ImmutableBlockProperties.h" #include "Lodestone.Level/chunk/section/Section.h" -#include "Lodestone.Level/types/NibbleArray.h" +#include namespace lodestone::level::chunk::section { class LevelSection : public Section { public: - LevelSection(); + LevelSection() = default; ~LevelSection() override; - types::AbstractNibbleArray *getBlockLight() override; + lodestone::common::storage::bits::AbstractBitsArray *getBlockLight() override; - types::AbstractNibbleArray *getSkyLight() override; + lodestone::common::storage::bits::AbstractBitsArray *getSkyLight() override; void setBlockLight(int x, int y, int z, uint8_t l) override; void setSkyLight(int x, int y, int z, uint8_t l) override; - block::properties::BlockProperties *getBlock(int x, int y, + const block::properties::BlockProperties &getBlock(int x, int y, int z) const override; void setBlock(block::properties::BlockProperties &&blk, int x, int y, int z) override; - const block::properties::BlockProperties *getBlocks() override; + const common::storage::palette::PalletizedStorage &getStorage() override; SectionType getType() override; private: - block::properties::BlockProperties *mBlocks = new block::properties:: - BlockProperties[common::constants::CHUNK_WIDTH * - common::constants::SECTION_HEIGHT * - common::constants::CHUNK_DEPTH](); + common::storage::palette::PalletizedStorage mBlocks = common::storage::palette::PalletizedStorage(common::constants::CHUNK_WIDTH * + common::constants::SECTION_HEIGHT * + common::constants::CHUNK_DEPTH, *block::properties::ImmutableBlockProperties::getInstance()); // TODO: we could also calculate lighting for blocks, could have a map // of xyz -> Block specifically for light blocks - types::NibbleArray mBlockLight = types::NibbleArray( + common::storage::bits::BitsArray mBlockLight = common::storage::bits::BitsArray( common::constants::CHUNK_WIDTH * common::constants::SECTION_HEIGHT * common::constants::CHUNK_DEPTH, 4); - types::NibbleArray mSkyLight = types::NibbleArray( + common::storage::bits::BitsArray mSkyLight = common::storage::bits::BitsArray( common::constants::CHUNK_WIDTH * common::constants::SECTION_HEIGHT * common::constants::CHUNK_DEPTH, 4); diff --git a/projects/Libraries/Level/include/Lodestone.Level/chunk/section/Section.h b/projects/Libraries/Level/include/Lodestone.Level/chunk/section/Section.h index 18dc499..297040f 100644 --- a/projects/Libraries/Level/include/Lodestone.Level/chunk/section/Section.h +++ b/projects/Libraries/Level/include/Lodestone.Level/chunk/section/Section.h @@ -3,7 +3,8 @@ // #ifndef LODESTONE_SECTION_H #define LODESTONE_SECTION_H -#include "Lodestone.Level/types/NibbleArray.h" +#include +#include namespace lodestone::level::block { namespace properties { @@ -18,17 +19,17 @@ namespace lodestone::level::chunk::section { enum class SectionType { LevelSection, EmptySection }; - virtual const block::properties::BlockProperties *getBlocks() = 0; + virtual const common::storage::palette::PalletizedStorage &getStorage() = 0; - virtual types::AbstractNibbleArray *getBlockLight() = 0; + virtual lodestone::common::storage::bits::AbstractBitsArray *getBlockLight() = 0; - virtual types::AbstractNibbleArray *getSkyLight() = 0; + virtual lodestone::common::storage::bits::AbstractBitsArray *getSkyLight() = 0; virtual void setBlockLight(int x, int y, int z, uint8_t l) = 0; virtual void setSkyLight(int x, int y, int z, uint8_t l) = 0; - virtual block::properties::BlockProperties * + virtual const block::properties::BlockProperties & getBlock(const int x, const int y, const int z) const = 0; virtual void setBlock(block::properties::BlockProperties &&blk, int x, diff --git a/projects/Libraries/Level/include/Lodestone.Level/properties/OptionalTemplatedProperty.h b/projects/Libraries/Level/include/Lodestone.Level/properties/OptionalTemplatedProperty.h deleted file mode 100644 index 779bc78..0000000 --- a/projects/Libraries/Level/include/Lodestone.Level/properties/OptionalTemplatedProperty.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// Created by DexrnZacAttack on 11/25/25 using zPc-i2. -// -#ifndef LODESTONE_OPTIONALTEMPLATEDPROPERTY_H -#define LODESTONE_OPTIONALTEMPLATEDPROPERTY_H -#include "Lodestone.Level/properties/TemplatedProperty.h" - -template -using OptionalTemplatedProperty = - lodestone::level::properties::TemplatedProperty>; - -#endif // LODESTONE_OPTIONALTEMPLATEDPROPERTY_H \ No newline at end of file diff --git a/projects/Libraries/Level/include/Lodestone.Level/properties/ReflectiveProperties.h b/projects/Libraries/Level/include/Lodestone.Level/properties/ReflectiveProperties.h index c745281..8d78bf2 100644 --- a/projects/Libraries/Level/include/Lodestone.Level/properties/ReflectiveProperties.h +++ b/projects/Libraries/Level/include/Lodestone.Level/properties/ReflectiveProperties.h @@ -11,12 +11,11 @@ namespace lodestone::level::properties { class ReflectiveProperties { public: - // oh no nfts -#define ADD_PROPERTY(n, f, t) \ +#define ADD_FIELD_PROPERTY(n, f) \ case n##_hash: \ - return (typeid(t) == typeid(f)) \ + return (typeid(decltype(f)&) == typeid(f)) \ ? std::make_shared< \ - lodestone::level::properties::TemplatedProperty>( \ + lodestone::level::properties::TemplatedProperty>( \ f) \ : nullptr diff --git a/projects/Libraries/Level/src/Level.cpp b/projects/Libraries/Level/src/Level.cpp index a810cb2..0f81477 100644 --- a/projects/Libraries/Level/src/Level.cpp +++ b/projects/Libraries/Level/src/Level.cpp @@ -7,7 +7,7 @@ #include #include -#include "Lodestone.Level/block/properties/EmptyBlockProperties.h" +#include "Lodestone.Level/block/properties/ImmutableBlockProperties.h" #include "Lodestone.Level/chunk/LevelChunk.h" #include @@ -15,7 +15,7 @@ namespace lodestone::level { #pragma region Blocks bool Level::isChunkInBounds(const types::Vec2i &coords) { return true; } - block::properties::BlockProperties *Level::getBlock(const signed_size_t x, + const block::properties::BlockProperties &Level::getBlock(const signed_size_t x, const signed_size_t y, const signed_size_t z) { if (const chunk::Chunk *c = getChunk(CHUNK_IDX(x), CHUNK_IDX(z))) @@ -23,7 +23,7 @@ namespace lodestone::level { CHUNK_LOCAL_IDX(x, common::constants::CHUNK_WIDTH), y, CHUNK_LOCAL_IDX(z, common::constants::CHUNK_DEPTH)); - return block::properties::EmptyBlockProperties::getInstance(); + return *block::properties::ImmutableBlockProperties::getInstance(); } void Level::setBlock(block::properties::BlockProperties &&blk, @@ -104,7 +104,7 @@ namespace lodestone::level { #pragma endregion #pragma region Blockmap - const block::properties::BlockProperties * + const block::properties::BlockProperties & Level::getBlockmapBlockAt(const signed_size_t x, const signed_size_t z) const { if (const chunk::Chunk *c = getChunk(CHUNK_IDX(x), CHUNK_IDX(z))) @@ -112,10 +112,10 @@ namespace lodestone::level { CHUNK_LOCAL_IDX(x, common::constants::CHUNK_WIDTH), CHUNK_LOCAL_IDX(z, common::constants::CHUNK_DEPTH)); - return block::properties::EmptyBlockProperties::getInstance(); + return *block::properties::ImmutableBlockProperties::getInstance(); } - void Level::setBlockmapBlockAt(block::properties::BlockProperties *b, + void Level::setBlockmapBlockAt(const block::properties::BlockProperties &b, const signed_size_t x, const signed_size_t z) { if (chunk::Chunk *c = getChunk(CHUNK_IDX(x), CHUNK_IDX(z))) @@ -124,7 +124,7 @@ namespace lodestone::level { CHUNK_LOCAL_IDX(z, common::constants::CHUNK_DEPTH)); } - void Level::setBlockmapBlockAtCreate(block::properties::BlockProperties *b, + void Level::setBlockmapBlockAtCreate(const block::properties::BlockProperties &b, const signed_size_t x, const signed_size_t z, const int height) { diff --git a/projects/Libraries/Level/src/block/BlockRegistry.cpp b/projects/Libraries/Level/src/block/BlockRegistry.cpp index 9f1b49a..0e1aa19 100644 --- a/projects/Libraries/Level/src/block/BlockRegistry.cpp +++ b/projects/Libraries/Level/src/block/BlockRegistry.cpp @@ -3,6 +3,8 @@ #include "Lodestone.Level/item/ItemRegistry.h" #include +#include "Lodestone.Level/block/blocks/AirBlock.h" + #if CMAKE_BUILD_DEBUG #include #endif @@ -14,7 +16,7 @@ namespace lodestone::level::block { getInstance().getBlock(&Blocks::AIR); BlockRegistry::BlockRegistry() { - REGISTER_BLOCK_FUNC(&Blocks::AIR, material::Material({0, 0, 0, 0})); + REGISTER_DERIVED_BLOCK_FUNC(&Blocks::AIR, material::Material({0, 0, 0, 0}), blocks::AirBlock); } BlockRegistry &BlockRegistry::getInstance() { diff --git a/projects/Libraries/Level/src/block/properties/EmptyBlockProperties.cpp b/projects/Libraries/Level/src/block/properties/ImmutableBlockProperties.cpp similarity index 50% rename from projects/Libraries/Level/src/block/properties/EmptyBlockProperties.cpp rename to projects/Libraries/Level/src/block/properties/ImmutableBlockProperties.cpp index 0310b40..5aadf4d 100644 --- a/projects/Libraries/Level/src/block/properties/EmptyBlockProperties.cpp +++ b/projects/Libraries/Level/src/block/properties/ImmutableBlockProperties.cpp @@ -1,41 +1,41 @@ // // Created by DexrnZacAttack on 11/15/25 using zPc-i2. // -#include "Lodestone.Level/block/properties/EmptyBlockProperties.h" +#include "Lodestone.Level/block/properties/ImmutableBlockProperties.h" namespace lodestone::level::block::properties { - EmptyBlockProperties::EmptyBlockProperties() + ImmutableBlockProperties::ImmutableBlockProperties() : BlockProperties(BlockRegistry::sDefaultBlock) {} - EmptyBlockProperties *EmptyBlockProperties::getInstance() { - static EmptyBlockProperties sInstance; + ImmutableBlockProperties *ImmutableBlockProperties::getInstance() { + static ImmutableBlockProperties sInstance; return &sInstance; } - bool EmptyBlockProperties::hasProperty(const std::string &id) const { + bool ImmutableBlockProperties::hasProperty(const std::string &id) const { return false; } const level::properties::AbstractProperty * - EmptyBlockProperties::getProperty(const std::string &id) const { + ImmutableBlockProperties::getProperty(const std::string &id) const { return nullptr; } level::properties::AbstractProperty * - EmptyBlockProperties::getProperty(const std::string &id) { + ImmutableBlockProperties::getProperty(const std::string &id) { return nullptr; } - void EmptyBlockProperties::setProperty( + void ImmutableBlockProperties::setProperty( const std::string &id, level::properties::AbstractProperty *property) {} const level::properties::AbstractProperty * - EmptyBlockProperties::operator[](const std::string &id) const { + ImmutableBlockProperties::operator[](const std::string &id) const { return nullptr; } level::properties::AbstractProperty * - EmptyBlockProperties::operator[](const std::string &id) { + ImmutableBlockProperties::operator[](const std::string &id) { return nullptr; } } // namespace lodestone::level::block::properties diff --git a/projects/Libraries/Level/src/chunk/Chunk.cpp b/projects/Libraries/Level/src/chunk/Chunk.cpp index 74a2000..688ee3c 100644 --- a/projects/Libraries/Level/src/chunk/Chunk.cpp +++ b/projects/Libraries/Level/src/chunk/Chunk.cpp @@ -3,6 +3,7 @@ // #include "Lodestone.Level/chunk/Chunk.h" +#include "Lodestone.Level/block/properties/ImmutableBlockProperties.h" #include "Lodestone.Level/chunk/ChunkContainer.h" #include "Lodestone.Level/properties/TemplatedProperty.h" @@ -12,7 +13,7 @@ namespace lodestone::level::chunk { for (int x = 0; x < lodestone::common::constants::CHUNK_WIDTH * common::constants::CHUNK_DEPTH; ++x) { - mBlockmap[x] = new block::properties::BlockProperties(); + mBlockmap[x] = *block::properties::ImmutableBlockProperties::getInstance(); } } @@ -38,8 +39,8 @@ namespace lodestone::level::chunk { const int16_t *Chunk::getHeightmap() const { return mHeightmap; } - const block::properties::BlockProperties **Chunk::getBlockmap() const { - return const_cast( + const block::properties::BlockProperties *Chunk::getBlockmap() const { + return const_cast( mBlockmap); } @@ -51,12 +52,12 @@ namespace lodestone::level::chunk { mHeightmap[z * common::constants::CHUNK_WIDTH + x] = h; } - const block::properties::BlockProperties * + const block::properties::BlockProperties & Chunk::getBlockmapBlockAt(const int x, const int z) const { return mBlockmap[z * common::constants::CHUNK_WIDTH + x]; } - void Chunk::setBlockmapBlockAt(block::properties::BlockProperties *b, + void Chunk::setBlockmapBlockAt(const block::properties::BlockProperties &b, const int x, const int z) { mBlockmap[z * common::constants::CHUNK_WIDTH + x] = b; } diff --git a/projects/Libraries/Level/src/chunk/EmptyChunk.cpp b/projects/Libraries/Level/src/chunk/EmptyChunk.cpp index 2f5996e..a623727 100644 --- a/projects/Libraries/Level/src/chunk/EmptyChunk.cpp +++ b/projects/Libraries/Level/src/chunk/EmptyChunk.cpp @@ -1,49 +1,49 @@ // // Created by DexrnZacAttack on 10/14/25 using zPc-i2. // -#include "Lodestone.Level/chunk/EmptyChunk.h" +#include "Lodestone.Level/chunk/ImmutableChunk.h" namespace lodestone::level::chunk { - EmptyChunk *EmptyChunk::getInstance() { - static EmptyChunk sInstance; + ImmutableChunk *ImmutableChunk::getInstance() { + static ImmutableChunk sInstance; return &sInstance; } - void EmptyChunk::calculateHeightmap() {} + void ImmutableChunk::calculateHeightmap() {} - int EmptyChunk::getChunkHeight() const { return 0; } + int ImmutableChunk::getChunkHeight() const { return 0; } - section::Section *EmptyChunk::getSection(int y) const { - return section::EmptySection::getInstance(); + section::Section *ImmutableChunk::getSection(int y) const { + return section::ImmutableSection::getInstance(); } - block::properties::BlockProperties * - EmptyChunk::getBlock(const int x, const int y, const int z) const { - return section::EmptySection::getInstance()->getBlock(x, y, z); + const block::properties::BlockProperties & + ImmutableChunk::getBlock(const int x, const int y, const int z) const { + return section::ImmutableSection::getInstance()->getBlock(x, y, z); } - section::Section *EmptyChunk::getSectionCreate(int y) { - return section::EmptySection::getInstance(); + section::Section *ImmutableChunk::getSectionCreate(int y) { + return section::ImmutableSection::getInstance(); } - void EmptyChunk::setBlock(block::properties::BlockProperties &&blk, int x, + void ImmutableChunk::setBlock(block::properties::BlockProperties &&blk, int x, int y, int z) {} - void EmptyChunk::setBlockRaw(block::properties::BlockProperties &&blk, + void ImmutableChunk::setBlockRaw(block::properties::BlockProperties &&blk, int x, int y, int z) {} - void EmptyChunk::setHeightAt(int16_t h, int x, int z) {} + void ImmutableChunk::setHeightAt(int16_t h, int x, int z) {} - void EmptyChunk::calculateBlockmap() {} + void ImmutableChunk::calculateBlockmap() {} - void EmptyChunk::setBlockmapBlockAt(block::properties::BlockProperties *h, + void ImmutableChunk::setBlockmapBlockAt(const block::properties::BlockProperties &h, int x, int z) {} - void EmptyChunk::calculateMaps() {} + void ImmutableChunk::calculateMaps() {} - void EmptyChunk::calculateBlockmapAtColumn(int x, int z, int height) {} + void ImmutableChunk::calculateBlockmapAtColumn(int x, int z, int height) {} - void EmptyChunk::calculateHeightmapAtColumn(int x, int z, int height) {} + void ImmutableChunk::calculateHeightmapAtColumn(int x, int z, int height) {} - void EmptyChunk::calculateMapsAtColumn(int x, int z, int height) {} + void ImmutableChunk::calculateMapsAtColumn(int x, int z, int height) {} } // namespace lodestone::level::chunk \ No newline at end of file diff --git a/projects/Libraries/Level/src/chunk/LevelChunk.cpp b/projects/Libraries/Level/src/chunk/LevelChunk.cpp index 0c2c3f9..b55e6fe 100644 --- a/projects/Libraries/Level/src/chunk/LevelChunk.cpp +++ b/projects/Libraries/Level/src/chunk/LevelChunk.cpp @@ -5,6 +5,8 @@ #include +#include "Lodestone.Level/block/properties/ImmutableBlockProperties.h" + namespace lodestone::level::chunk { LevelChunk::LevelChunk(const int height) { this->mSections = std::vector>( @@ -39,7 +41,7 @@ namespace lodestone::level::chunk { section::Section *LevelChunk::getSection(const int y) const { // if non-existent, return fake one if (!hasSection(y)) - return section::EmptySection::getInstance(); + return section::ImmutableSection::getInstance(); return mSections[y].get(); } @@ -51,7 +53,7 @@ namespace lodestone::level::chunk { return mSections[y].get(); } - block::properties::BlockProperties * + const block::properties::BlockProperties & LevelChunk::getBlock(const int x, const int y, const int z) const { return getSection(y >> 4)->getBlock(x, y & 15, z); } @@ -72,10 +74,10 @@ namespace lodestone::level::chunk { for (int z = 0; z < common::constants::CHUNK_DEPTH; z++) { for (int x = 0; x < common::constants::CHUNK_WIDTH; x++) { for (int y = height; y >= 0; y--) { - if (block::properties::BlockProperties *s = + if (const block::properties::BlockProperties &s = getBlock(x, y, z); s != getBlockmapBlockAt(x, z) && - *s != block::BlockRegistry::sDefaultBlock) { + !s.getBlock()->heightmapShouldIgnore()) { setBlockmapBlockAt(s, x, z); break; } @@ -97,7 +99,7 @@ namespace lodestone::level::chunk { void LevelChunk::calculateHeightmapAtColumn(const int x, const int z, const int height) { for (int y = height; y >= 0; y--) { - if (getBlock(x, y, z)->getBlock() != + if (getBlock(x, y, z).getBlock() != block::BlockRegistry::sDefaultBlock) { setHeightAt(std::min(y + 1, height - 1), x, z); break; @@ -108,9 +110,9 @@ namespace lodestone::level::chunk { void LevelChunk::calculateBlockmapAtColumn(const int x, const int z, const int height) { for (int y = height; y >= 0; y--) { - if (block::properties::BlockProperties *s = getBlock(x, y, z); + if (const block::properties::BlockProperties &s = getBlock(x, y, z); s != getBlockmapBlockAt(x, z) && - *s != block::BlockRegistry::sDefaultBlock) { + !s.getBlock()->heightmapShouldIgnore()) { setBlockmapBlockAt(s, x, z); break; } @@ -120,8 +122,8 @@ namespace lodestone::level::chunk { void LevelChunk::calculateMapsAtColumn(const int x, const int z, const int height) { for (int y = height; y >= 0; y--) { - if (block::properties::BlockProperties *s = getBlock(x, y, z); - *s != block::BlockRegistry::sDefaultBlock) { + if (const block::properties::BlockProperties &s = getBlock(x, y, z); + !s.getBlock()->heightmapShouldIgnore()) { setHeightAt(std::min(y + 1, height - 1), x, z); if (s != getBlockmapBlockAt(x, z)) @@ -140,24 +142,24 @@ namespace lodestone::level::chunk { "attempted to set blockstate with null block"); const int height = getChunkBlockHeight(); - if (blk.getBlock() != block::BlockRegistry::sDefaultBlock) { + if (!blk.getBlock()->heightmapShouldIgnore()) { // if our block is higher than the current height, and isn't air, // then it's obviously higher up. so we set the new height if (y + 1 > getHeightAt(x, z)) { setHeightAt(std::min(y + 1, height - 1), x, z); - if (&blk != getBlockmapBlockAt(x, z)) - setBlockmapBlockAt(&blk, x, z); + if (blk != getBlockmapBlockAt(x, z)) + setBlockmapBlockAt(blk, x, z); }; } else { // if our air block's position is the topmost block of any column if (y + 1 == getHeightAt(x, z)) { // then we get the new topmost block for (int i = y; i >= 0; i--) { - if (block::properties::BlockProperties *s = + if (const block::properties::BlockProperties &s = getBlock(x, i, z); - s->getBlock() != block::BlockRegistry::sDefaultBlock && - s->getBlock()) { + s.getBlock() && + !s.getBlock()->heightmapShouldIgnore()) { setHeightAt(std::min(i + 1, height - 1), x, z); // new highest block @@ -169,11 +171,11 @@ namespace lodestone::level::chunk { } // there were no blocks - setBlockmapBlockAt(new block::properties::BlockProperties(), x, + setBlockmapBlockAt(*block::properties::ImmutableBlockProperties::getInstance(), x, z); // should be good? setHeightAt(x, z, 0); - } else if (!getBlockmapBlockAt(x, z)->getBlock()) { - setBlockmapBlockAt(new block::properties::BlockProperties(), x, + } else if (!getBlockmapBlockAt(x, z).getBlock()) { + setBlockmapBlockAt(*block::properties::ImmutableBlockProperties::getInstance(), x, z); // should be good? } } diff --git a/projects/Libraries/Level/src/chunk/section/EmptySection.cpp b/projects/Libraries/Level/src/chunk/section/EmptySection.cpp index 42a02d2..e501a47 100644 --- a/projects/Libraries/Level/src/chunk/section/EmptySection.cpp +++ b/projects/Libraries/Level/src/chunk/section/EmptySection.cpp @@ -1,41 +1,43 @@ // // Created by DexrnZacAttack on 10/14/25 using zPc-i2. // -#include "Lodestone.Level/chunk/section/EmptySection.h" +#include "Lodestone.Level/chunk/section/ImmutableSection.h" #include "Lodestone.Level/block/properties/BlockProperties.h" -#include "Lodestone.Level/block/properties/EmptyBlockProperties.h" +#include "Lodestone.Level/block/properties/ImmutableBlockProperties.h" namespace lodestone::level::chunk::section { - EmptySection *EmptySection::getInstance() { - static EmptySection sInstance; + const common::storage::palette::PalletizedStorage ImmutableSection::EMPTY_STORAGE = common::storage::palette::PalletizedStorage(0, *block::properties::ImmutableBlockProperties::getInstance()); + + ImmutableSection *ImmutableSection::getInstance() { + static ImmutableSection sInstance; return &sInstance; } - Section::SectionType EmptySection::getType() { + Section::SectionType ImmutableSection::getType() { return SectionType::EmptySection; } - const block::properties::BlockProperties *EmptySection::getBlocks() { - return nullptr; + const common::storage::palette::PalletizedStorage &ImmutableSection::getStorage() { + return ImmutableSection::EMPTY_STORAGE; } - types::AbstractNibbleArray *EmptySection::getBlockLight() { - return types::EmptyNibbleArray::getInstance(); + lodestone::common::storage::bits::AbstractBitsArray *ImmutableSection::getBlockLight() { + return common::storage::bits::ImmutableBitsArray::getInstance(); } - types::AbstractNibbleArray *EmptySection::getSkyLight() { - return types::EmptyNibbleArray::getInstance(); + lodestone::common::storage::bits::AbstractBitsArray *ImmutableSection::getSkyLight() { + return common::storage::bits::ImmutableBitsArray::getInstance(); } - void EmptySection::setBlockLight(int x, int y, int z, uint8_t l) {} + void ImmutableSection::setBlockLight(int x, int y, int z, uint8_t l) {} - void EmptySection::setSkyLight(int x, int y, int z, uint8_t l) {} + void ImmutableSection::setSkyLight(int x, int y, int z, uint8_t l) {} - block::properties::BlockProperties * - EmptySection::getBlock(const int x, const int y, const int z) const { - return block::properties::EmptyBlockProperties::getInstance(); + const block::properties::BlockProperties & + ImmutableSection::getBlock(const int x, const int y, const int z) const { + return *block::properties::ImmutableBlockProperties::getInstance(); } - void EmptySection::setBlock(block::properties::BlockProperties &&blk, int x, + void ImmutableSection::setBlock(block::properties::BlockProperties &&blk, int x, int y, int z) {} } // namespace lodestone::level::chunk::section diff --git a/projects/Libraries/Level/src/chunk/section/LevelSection.cpp b/projects/Libraries/Level/src/chunk/section/LevelSection.cpp index 5bb29a6..776f96b 100644 --- a/projects/Libraries/Level/src/chunk/section/LevelSection.cpp +++ b/projects/Libraries/Level/src/chunk/section/LevelSection.cpp @@ -6,18 +6,15 @@ #include namespace lodestone::level::chunk::section { - LevelSection::LevelSection() {} - LevelSection::~LevelSection() { delete[] mBiomes; - delete[] mBlocks; } - types::AbstractNibbleArray *LevelSection::getBlockLight() { + lodestone::common::storage::bits::AbstractBitsArray *LevelSection::getBlockLight() { return &mBlockLight; } - types::AbstractNibbleArray *LevelSection::getSkyLight() { + lodestone::common::storage::bits::AbstractBitsArray *LevelSection::getSkyLight() { return &mSkyLight; } @@ -31,13 +28,13 @@ namespace lodestone::level::chunk::section { this->mSkyLight.setNibble(x, y, z, l & 0xF); } - block::properties::BlockProperties * + const block::properties::BlockProperties & LevelSection::getBlock(const int x, const int y, const int z) const { - return &mBlocks[INDEX_YZX(x, y, z, common::constants::CHUNK_WIDTH, - common::constants::CHUNK_DEPTH)]; + return mBlocks.getValue(INDEX_YZX(x, y, z, common::constants::CHUNK_WIDTH, + common::constants::CHUNK_DEPTH)); } - const block::properties::BlockProperties *LevelSection::getBlocks() { + const common::storage::palette::PalletizedStorage &LevelSection::getStorage() { return mBlocks; } @@ -47,7 +44,7 @@ namespace lodestone::level::chunk::section { void LevelSection::setBlock(block::properties::BlockProperties &&blk, const int x, const int y, const int z) { - mBlocks[INDEX_YZX(x, y, z, common::constants::CHUNK_WIDTH, - common::constants::CHUNK_DEPTH)] = std::move(blk); + mBlocks.setValue(INDEX_YZX(x, y, z, common::constants::CHUNK_WIDTH, + common::constants::CHUNK_DEPTH), std::move(blk)); } } // namespace lodestone::level::chunk::section diff --git a/projects/Libraries/Level/src/entity/Player.cpp b/projects/Libraries/Level/src/entity/Player.cpp index 39e9404..7bf0d17 100644 --- a/projects/Libraries/Level/src/entity/Player.cpp +++ b/projects/Libraries/Level/src/entity/Player.cpp @@ -87,7 +87,7 @@ namespace lodestone::level::entity { if (std::modf(this->mPosition->y, &t) == 0 && lvl->getBlock(this->mPosition->x, this->mPosition->y - 1, this->mPosition->z) - ->getBlock() != level::block::BlockRegistry::sDefaultBlock) + .getBlock() != level::block::BlockRegistry::sDefaultBlock) return true; return false; diff --git a/projects/Libraries/Level/src/types/AbstractNibbleArray.cpp b/projects/Libraries/Level/src/types/AbstractNibbleArray.cpp deleted file mode 100644 index 42912f1..0000000 --- a/projects/Libraries/Level/src/types/AbstractNibbleArray.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// -// Created by DexrnZacAttack on 11/26/25 using zPc-i2. -// -#include "Lodestone.Level/types/AbstractNibbleArray.h" - -namespace lodestone::level::types {} diff --git a/projects/Libraries/Level/src/types/EmptyNibbleArray.cpp b/projects/Libraries/Level/src/types/EmptyNibbleArray.cpp deleted file mode 100644 index 09667fa..0000000 --- a/projects/Libraries/Level/src/types/EmptyNibbleArray.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// -// Created by Zero on 11/25/25. -// -#include "Lodestone.Level/types/EmptyNibbleArray.h" - -namespace lodestone::level::types { - EmptyNibbleArray *EmptyNibbleArray::getInstance() { - static EmptyNibbleArray sInstance; - return &sInstance; - } - - int EmptyNibbleArray::getIndex(int x, int y, int z) const { return 0; } - - int EmptyNibbleArray::getNibble(int x, int y, int z) const { return 0; } - - void EmptyNibbleArray::setNibble(const int x, const int y, const int z, - const int value) {} -} // namespace lodestone::level::types \ No newline at end of file diff --git a/projects/Utilities/Tests/src/tests/MainTests.cpp b/projects/Utilities/Tests/src/tests/MainTests.cpp index d2411cf..e93a851 100644 --- a/projects/Utilities/Tests/src/tests/MainTests.cpp +++ b/projects/Utilities/Tests/src/tests/MainTests.cpp @@ -3,6 +3,8 @@ // #include "Lodestone.Tests/tests/MainTests.h" +#include + #include #include @@ -49,30 +51,22 @@ namespace lodestone::tests::test { "Write Alpha World"); } void MainTests::readAnvilWorld() { - std::string name("r.0.-1"); - OPEN_FILE_STREAM("AnvilWorld" / "region" / std::format("{}.mca", name), - c); + const std::string name("AnvilWorld"); + const std::filesystem::path dir(util::INPUT_FOLDER / name); - auto io = static_cast( - conversion::region::RegionIORegistry::getInstance().getRegionIO( + const auto *io = static_cast< + const minecraft::java::anvil::jungle::world::JungleAnvilWorldIo *>( + conversion::world::WorldIORegistry::getInstance().getWorldIO( minecraft::java::identifiers::ANVIL_JUNGLE)); - std::unique_ptr r = - io->read(in, minecraft::java::Version::r1_2_1, - minecraft::java::anvil::jungle::region::JungleAnvilRegion:: - getCoordsFromFilename(name)); + const auto w = io->read(dir, minecraft::java::Version::r1_2_1, {}); - // world - level::world::World w("New World"); - w.addLevel(level::world::World::Dimension::OVERWORLD, std::move(r)); - - const minecraft::java::alpha::world::AlphaWorldIo *converter = - (minecraft::java::alpha::world::AlphaWorldIo *) - conversion::world::WorldIORegistry::getInstance() - .getWorldIO(minecraft::java::identifiers::ALPHA); + const auto converter = static_cast< + const minecraft::java::mcregion::world::McRegionWorldIo *>( + conversion::world::WorldIORegistry::getInstance().getWorldIO( + minecraft::java::identifiers::MCREGION)); - converter->write(util::OUTPUT_FOLDER / name, &w, minecraft::java::b1_3, - {}); + converter->write(util::OUTPUT_FOLDER / name, w.get(), + minecraft::java::b1_3, {}); } void MainTests::readMcrChunk() { diff --git a/scripts/checkIncludePaths.py b/scripts/checkIncludePaths.py old mode 100644 new mode 100755