15 "track_corner_TL.bin",
16 "track_corner_TR.bin",
17 "track_corner_BL.bin",
18 "track_corner_BR.bin",
21 "track_floor_corner_TL.bin",
22 "track_floor_corner_TR.bin",
23 "track_floor_corner_BL.bin",
24 "track_floor_corner_BR.bin",
25 "track_floor_any.bin",
26 "wall_sword_house.bin",
48 const std::string& filename) {
49 if (
cache_.contains(filename)) {
54 std::filesystem::path full_path = std::filesystem::path(
base_path_) / filename;
56 std::ifstream file(full_path, std::ios::binary);
58 LOG_ERROR(
"CustomObjectManager",
"Failed to open file: %s", full_path.c_str());
59 return absl::NotFoundError(
"Could not open file: " + full_path.string());
63 std::vector<uint8_t> buffer((std::istreambuf_iterator<char>(file)),
64 std::istreambuf_iterator<char>());
67 if (!object_or_error.ok()) {
68 return object_or_error.status();
71 auto object_ptr = std::make_shared<CustomObject>(std::move(object_or_error.value()));
72 cache_[filename] = object_ptr;
80 int current_buffer_pos = 0;
90 constexpr int kBufferStride = 128;
92 while (cursor + 1 < data.size()) {
94 uint16_t header = data[cursor] | (data[cursor + 1] << 8);
97 if (header == 0)
break;
99 int count = header & 0x001F;
100 int jump_offset = (header >> 8) & 0xFF;
105 int row_start_pos = current_buffer_pos;
108 for (
int i = 0; i < count; ++i) {
109 if (cursor + 1 >= data.size()) {
110 LOG_WARN(
"CustomObjectManager",
"Unexpected end of file parsing object");
114 uint16_t tile_data = data[cursor] | (data[cursor + 1] << 8);
119 int rel_y = current_buffer_pos / kBufferStride;
120 int rel_x = (current_buffer_pos % kBufferStride) / 2;
122 obj.
tiles.push_back({rel_x, rel_y, tile_data});
124 current_buffer_pos += 2;
129 current_buffer_pos = row_start_pos + jump_offset;
136 const std::vector<std::string>* list =
nullptr;
139 if (object_id == 0x31) {
141 }
else if (object_id == 0x32) {
143 }
else if (object_id >= 0x100 && object_id <= 0x103) {
150 case 0x100: index = 2;
break;
151 case 0x101: index = 4;
break;
152 case 0x102: index = 3;
break;
153 case 0x103: index = 5;
break;
158 return absl::NotFoundError(
"Object ID not mapped to custom object");
161 if (index < 0 || index >=
static_cast<int>(list->size())) {
162 return absl::OutOfRangeError(
"Subtype index out of range");
169 if (object_id == 0x31 || (object_id >= 0x100 && object_id <= 0x103)) {
Manages loading and caching of custom object binary files.
int GetSubtypeCount(int object_id) const
absl::StatusOr< CustomObject > ParseBinaryData(const std::vector< uint8_t > &data)
static CustomObjectManager & Get()
absl::StatusOr< std::shared_ptr< CustomObject > > LoadObject(const std::string &filename)
absl::StatusOr< std::shared_ptr< CustomObject > > GetObjectInternal(int object_id, int subtype)
static const std::vector< std::string > kSubtype2Filenames
void Initialize(const std::string &custom_objects_folder)
std::unordered_map< std::string, std::shared_ptr< CustomObject > > cache_
static const std::vector< std::string > kSubtype1Filenames
#define LOG_ERROR(category, format,...)
#define LOG_WARN(category, format,...)
Represents a decoded custom object (from binary format)
std::vector< TileMapEntry > tiles