diff options
Diffstat (limited to 'include/file')
| -rw-r--r-- | include/file/metadata.hpp | 13 | ||||
| -rw-r--r-- | include/file/world.hpp | 87 |
2 files changed, 63 insertions, 37 deletions
diff --git a/include/file/metadata.hpp b/include/file/metadata.hpp index 8b9ec4f..35b0a24 100644 --- a/include/file/metadata.hpp +++ b/include/file/metadata.hpp @@ -8,18 +8,19 @@ namespace file { -enum class filetype : uint8_t { - Map = 1, - World, - Player, - TOTAL, -}; struct metadata { static constexpr auto magic = 27981915666277746uL; static constexpr auto magic_mask = 0xFFFFFFFFFFFFFFuL; static constexpr auto size = 20; + enum class filetype : uint8_t { + Map = 1, + World, + Player, + TOTAL, + }; + enum class flags { Favorite, }; diff --git a/include/file/world.hpp b/include/file/world.hpp index 300a3e0..c204c76 100644 --- a/include/file/world.hpp +++ b/include/file/world.hpp @@ -1,12 +1,9 @@ #pragma once -#include <array> #include <cstdint> #include <cstdio> #include <fcntl.h> #include <filesystem> -#include <fstream> -#include <iostream> #include <stdexcept> #include <string> #include <vector> @@ -19,27 +16,63 @@ namespace file { class world { - int32_t version; - // metadata meta; + // TODO: World, Player and Map files probably share similar(or the same) header format. + // If so, move this into file/header.hpp, and defile `struct header : file::header` here + struct header { + int32_t version; + metadata meta; + std::vector<int32_t> positions; + bitset<0> importance; + - std::vector<uint32_t> positions; - bitset<0> importance; + ssize_t read(io::serialized_file f) + { + auto bytes = f.read(version); - int32_t seed; - std::array<uint8_t, 16> guid; - int32_t worldID; - int32_t world_left; - int32_t world_right; - int32_t world_top; - int32_t world_botton; - int32_t height; - int32_t width; + if (version < 88 || version > terraria_version) { + throw std::runtime_error("unsupported world version"); + } -public: - void load_header(std::ifstream& f) - { - } + if (version >= 135) { + bytes += f.read(meta); + if (meta.ftype != metadata::filetype::World) { + throw std::runtime_error("unexpected relogic file format"); + } + } else { + throw std::runtime_error("unimplemented"); + } + + int16_t positions_size; + bytes += f.read(positions_size); + positions.resize(positions_size); + bytes += f.read(positions); + + int16_t importance_size; + bytes += f.read(importance_size); + importance.resize(bits_ceil(importance_size)); + bytes += f.read(importance); + return bytes; + } + }; + + enum file_positions { + FileHeaderEnd, + HeaderEnd, + WorldTilesEnd, + ChestsEnd, + SignsEnd, + NPCsEnd, + DummiesEnd, // Terraria[116;122) + TileEntitiesEnd = DummiesEnd, + WeightedPressurePlatesEnd, + TownManagerEnd, + BestiaryEnd, + CreativePowersEnd, + }; + header hdr; + +public: world(std::string filename) { if (!std::filesystem::exists(filename)) { @@ -47,17 +80,9 @@ public: } auto rw = io::serialized_io(io::file_io { filename }); - rw.read(version); - if (version <= 88 || version > terraria_version) { - throw std::runtime_error("invalid world file version"); - } - std::cout << version << std::endl; - metadata meta; - - rw.read(meta); - - if (meta.ftype != filetype::World) { - throw std::runtime_error("expected world file"); + auto offset = rw.read(hdr); + if (offset != hdr.positions[file_positions::FileHeaderEnd]) { + throw std::runtime_error("currupted file!"); } } }; |
