summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/file/metadata.hpp13
-rw-r--r--include/file/world.hpp87
-rw-r--r--include/util/io.hpp2
3 files changed, 65 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!");
}
}
};
diff --git a/include/util/io.hpp b/include/util/io.hpp
index e99c86a..629bf59 100644
--- a/include/util/io.hpp
+++ b/include/util/io.hpp
@@ -209,4 +209,6 @@ public:
}
};
+using serialized_file = serialized_io<file_io>;
+
} \ No newline at end of file